[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kmail-devel
Subject:    PATCH imap body search
From:       Carsten Burghardt <burghardt () kde ! org>
Date:       2004-09-03 19:32:14
Message-ID: 200409032132.17503.burghardt () kde ! org
[Download RAW message or body]

[Attachment #2 (multipart/signed)]

[Attachment #4 (multipart/mixed)]


Hi folks,

I finally implemented IMAP body search. I extended the normal local search so 
that the results are merged with the imap search. I don't download the 
messages one by one but use the server. The logic is splitted: searches for 
<message> and <body> are send to the server while the rest is done locally. I 
don't know if there are any other cases that can't be done with the msgbase 
but the cases I checked worked quite well.


Carsten

["imapsearch.diff" (text/x-diff)]

? imapsearch.diff
Index: folderstorage.cpp
===================================================================
RCS file: /home/kde/kdepim/kmail/folderstorage.cpp,v
retrieving revision 1.29
diff -u -3 -p -r1.29 folderstorage.cpp
--- folderstorage.cpp	19 Aug 2004 07:03:38 -0000	1.29
+++ folderstorage.cpp	3 Sep 2004 19:30:37 -0000
@@ -46,6 +46,7 @@
 #include "listjob.h"
 using KMail::ListJob;
 #include "kmailicalifaceimpl.h"
+#include "kmsearchpattern.h"
 
 #include <klocale.h>
 #include <kconfig.h>
@@ -1006,4 +1007,17 @@ void FolderStorage::setContentsType( KMa
   }
 }
 
+//-----------------------------------------------------------------------------
+void FolderStorage::search( KMSearchPattern* pattern )
+{
+  QValueList<Q_UINT32> serNums;
+  for ( int i = 0; i < count(); ++i ) 
+  {
+    Q_UINT32 serNum = kmkernel->msgDict()->getMsgSerNum( folder(), i );
+    if ( pattern->matches( serNum ) )
+      serNums.append( serNum );
+  }
+  emit searchDone( folder(), serNums );
+}
+
 #include "folderstorage.moc"
Index: folderstorage.h
===================================================================
RCS file: /home/kde/kdepim/kmail/folderstorage.h,v
retrieving revision 1.27
diff -u -3 -p -r1.27 folderstorage.h
--- folderstorage.h	18 Jun 2004 17:04:42 -0000	1.27
+++ folderstorage.h	3 Sep 2004 19:30:38 -0000
@@ -46,6 +46,7 @@
 using KMail::FolderJob;
 #include "listjob.h"
 using KMail::ListJob;
+#include "kmsearchpattern.h"
 
 #include "mimelib/string.h"
 
@@ -405,6 +406,12 @@ public:
   /// @return the type of contents held in this folder (mail, calendar, etc.)
   KMail::FolderContentsType contentsType() const { return mContentsType; }
 
+  /** 
+    * Search for messages
+    * The end is signaled with searchDone()
+    */
+  virtual void search( KMSearchPattern* );
+
 signals:
   /** Emitted when the status, name, or associated accounts of this
     folder changed. */
@@ -447,6 +454,12 @@ signals:
   /** Emitted when a folder was removed */
   void removed(KMFolder*, bool);
 
+  /** 
+   * Emitted when a search is completed
+   * The matching serial numbers are included 
+   */
+  void searchDone( KMFolder*, QValueList<Q_UINT32> serNums );
+
 public slots:
   /** Incrementally update the index if possible else call writeIndex */
   virtual int updateIndex() = 0;
Index: kmfldsearch.cpp
===================================================================
RCS file: /home/kde/kdepim/kmail/kmfldsearch.cpp,v
retrieving revision 1.133
diff -u -3 -p -r1.133 kmfldsearch.cpp
--- kmfldsearch.cpp	13 Jul 2004 08:48:21 -0000	1.133
+++ kmfldsearch.cpp	3 Sep 2004 19:30:38 -0000
@@ -95,8 +95,6 @@ KMFldSearch::KMFldSearch(KMMainWidget* w
 
   connect(mCbxFolders, SIGNAL(activated(int)),
           this, SLOT(slotFolderActivated(int)));
-  connect(mCbxFolders, SIGNAL(activated(int)),
-          this, SLOT(slotFilterAvailableRules()));
     
   mChkSubFolders = new QCheckBox(i18n("I&nclude sub-folders"), searchWidget);
   mChkSubFolders->setChecked(true);
@@ -241,11 +239,6 @@ KMFldSearch::KMFldSearch(KMMainWidget* w
   else
       kdDebug(5006) << "KMFldSearch: regExpLineEdit not found" << endl;
 
-  // Remove the <message> and <body> rule fields when searching imap folders
-  slotFilterAvailableRules();
-  connect(mChkbxAllFolders, SIGNAL(toggled(bool)),
-          this, SLOT(slotFilterAvailableRules()));
-
   //set up actions
   KActionCollection *ac = actionCollection();
   mReplyAction = new KAction( i18n("&Reply..."), "mail_reply", 0, this,
@@ -365,21 +358,6 @@ void KMFldSearch::slotFolderActivated(in
     mBtnSearch->setEnabled(folder);
 }
 
-
-//-----------------------------------------------------------------------------
-void KMFldSearch::slotFilterAvailableRules()
-{
-    static bool lastHeadersOnly = false;
-    KMFolder* folder = mCbxFolders->getFolder();
-    bool headersOnly = folder->folderType() == KMFolderTypeImap;
-    if (mChkbxAllFolders->isChecked())
-	headersOnly = false;
-    if (headersOnly != lastHeadersOnly)
-	mPatternEdit->setHeadersOnly( headersOnly );
-    lastHeadersOnly = headersOnly;
-}
-
-
 //-----------------------------------------------------------------------------
 void KMFldSearch::activateFolder(KMFolder *curFolder)
 {
Index: kmfldsearch.h
===================================================================
RCS file: /home/kde/kdepim/kmail/kmfldsearch.h,v
retrieving revision 1.44
diff -u -3 -p -r1.44 kmfldsearch.h
--- kmfldsearch.h	13 Jul 2004 08:48:21 -0000	1.44
+++ kmfldsearch.h	3 Sep 2004 19:30:38 -0000
@@ -69,7 +69,6 @@ protected slots:
   virtual void copySelectedToFolder( int menuId );
   virtual void moveSelectedToFolder( int menuId );
   virtual void slotFolderActivated(int nr);
-  virtual void slotFilterAvailableRules();
   void slotClearSelection();
   void slotReplyToMsg();
   void slotReplyAllToMsg();
Index: kmfolderimap.cpp
===================================================================
RCS file: /home/kde/kdepim/kmail/kmfolderimap.cpp,v
retrieving revision 1.231
diff -u -3 -p -r1.231 kmfolderimap.cpp
--- kmfolderimap.cpp	28 Aug 2004 12:57:50 -0000	1.231
+++ kmfolderimap.cpp	3 Sep 2004 19:30:39 -0000
@@ -29,6 +29,7 @@
 #include "kmfoldertree.h"
 #include "undostack.h"
 #include "kmfoldermgr.h"
+#include "kmmsgdict.h"
 #include "imapjob.h"
 using KMail::ImapJob;
 #include "attachmentstrategy.h"
@@ -1887,4 +1888,91 @@ void KMFolderImap::slotCreatePendingFold
   mFoldersPendingCreation.clear();
 }
 
+//-----------------------------------------------------------------------------
+void KMFolderImap::search( KMSearchPattern* pattern )
+{
+  mLastSearchPattern = pattern;
+
+  // first make sure the folder is complete
+  // needed for local searches and to map the uid to the serial number later
+  connect ( this, SIGNAL( folderComplete( KMFolderImap*, bool ) ),
+            this, SLOT( slotSearch()) );
+  getFolder();
+}
+
+//-----------------------------------------------------------------------------
+void KMFolderImap::slotSearch()
+{
+  disconnect ( this, SIGNAL( folderComplete( KMFolderImap*, bool ) ),
+            this, SLOT( slotSearch()) );
+  if ( !mLastSearchPattern->requiresBody() || 
+        mLastSearchPattern->asImapString().isEmpty() )
+    return FolderStorage::search( mLastSearchPattern );
+
+  // do the IMAP search  
+  KURL url = mAccount->getUrl();
+  url.setPath( imapPath() + ";SECTION=" + mLastSearchPattern->asImapString() );
+  QByteArray packedArgs;
+  QDataStream stream( packedArgs, IO_WriteOnly );
+  stream << (int) 'E' << url;
+  KIO::SimpleJob *job = KIO::special( url, packedArgs, false );
+  KIO::Scheduler::assignJobToSlave(mAccount->slave(), job);
+  connect( job, SIGNAL(infoMessage(KIO::Job*,const QString&)),
+      SLOT(slotSearchData(KIO::Job*,const QString&)) );
+  connect( job, SIGNAL(result(KIO::Job *)),
+      SLOT(slotSearchResult(KIO::Job *)) );
+}
+
+//-----------------------------------------------------------------------------
+void KMFolderImap::slotSearchData( KIO::Job* job, const QString& data )
+{
+  if ( job->error() )
+   return; 
+  
+  QValueList<Q_UINT32> serNums;
+  // search for the serial number of the UIDs
+  // data contains all found uids separated by blank
+  if ( mLastSearchPattern->op() == KMSearchPattern::OpAnd )
+  {
+    for ( int i = 0; i < count(); ++i )
+    {
+      KMMsgBase * base = getMsgBase( i );
+      Q_UINT32 serNum = kmkernel->msgDict()->getMsgSerNum( folder(), i );
+      // merge imap search and local search
+      if ( data.contains( QString::number(base->UID()) ) &&
+           mLastSearchPattern->matches( serNum, true ) )
+      {
+        serNums.append( serNum );
+      }
+    }
+  } else if ( mLastSearchPattern->op() == KMSearchPattern::OpOr )
+  {
+    for ( int i = 0; i < count(); ++i )
+    {
+      KMMsgBase * base = getMsgBase( i );
+      Q_UINT32 serNum = kmkernel->msgDict()->getMsgSerNum( folder(), i );
+      // either imap search or local search have to match
+      if ( data.contains( QString::number(base->UID()) ) ||
+           mLastSearchPattern->matches( serNum, true ) )
+      {
+        serNums.append( serNum );
+      }
+    }
+  } else
+    kdDebug(5006) << k_funcinfo << "unknown operator" << endl;
+
+  emit searchDone( folder(), serNums );
+}
+
+//-----------------------------------------------------------------------------
+void KMFolderImap::slotSearchResult(KIO::Job *job)
+{
+  if ( job->error() )
+  {
+    QValueList<Q_UINT32> serNums;
+    mAccount->handleJobError( job, i18n("Error while searching.") );
+    emit searchDone( folder(), serNums );
+  }
+}
+
 #include "kmfolderimap.moc"
Index: kmfolderimap.h
===================================================================
RCS file: /home/kde/kdepim/kmail/kmfolderimap.h,v
retrieving revision 1.80
diff -u -3 -p -r1.80 kmfolderimap.h
--- kmfolderimap.h	3 Aug 2004 20:29:57 -0000	1.80
+++ kmfolderimap.h	3 Sep 2004 19:30:39 -0000
@@ -40,6 +40,7 @@ using KMail::ImapAccountBase;
 
 class KMFolderTreeItem;
 class KMFolderImap;
+class KMSearchPattern;
 namespace KMail {
   class FolderJob;
   class ImapJob;
@@ -285,6 +286,13 @@ public:
   /** Set the user's rights on this folder - called by getUserRights */
   void setUserRights( unsigned int userRights );
 
+  /** 
+    * Search for messages
+    * The actual search is done in slotSearch and the end
+    * is signaled with searchDone()
+    */
+  virtual void search( KMSearchPattern* );
+
 signals:
   void folderComplete(KMFolderImap *folder, bool success);
 
@@ -417,6 +425,18 @@ protected slots:
    */
   void slotCreatePendingFolders();
 
+  /**
+   * Do an IMAP search
+   * It uses the mLastSearchPattern for this
+   */
+  void slotSearch();
+
+  /**
+   * Is called when the search is done
+   */ 
+  void slotSearchData( KIO::Job * job, const QString& data );
+  void slotSearchResult( KIO::Job * job );
+  
 protected:
   QString     mImapPath;
   ulong       mLastUid;
@@ -437,6 +457,8 @@ private:
   QGuardedPtr<ProgressItem> mMailCheckProgressItem;
   ProgressItem *mListDirProgressItem;
   QStringList mFoldersPendingCreation;
+  // remember the SearchPattern
+  KMSearchPattern* mLastSearchPattern;
 };
 
 #endif // kmfolderimap_h
Index: kmfoldersearch.cpp
===================================================================
RCS file: /home/kde/kdepim/kmail/kmfoldersearch.cpp,v
retrieving revision 1.57
diff -u -3 -p -r1.57 kmfoldersearch.cpp
--- kmfoldersearch.cpp	4 Aug 2004 17:09:06 -0000	1.57
+++ kmfoldersearch.cpp	3 Sep 2004 19:30:40 -0000
@@ -55,10 +55,8 @@ KMSearch::KMSearch(QObject * parent, con
     :QObject(parent, name)
 {
     mRemainingFolders = -1;
-    mRemainingMessages = -1;
     mRecursive = true;
     mRunByIndex = mRunning = false;
-    mIdle = false;
     mRoot = 0;
     mSearchPattern = 0;
     mSearchedCount = 0;
@@ -90,22 +88,22 @@ bool KMSearch::write(QString location) c
 
 bool KMSearch::read(QString location)
 {
-    KConfig config(location);
-    config.setGroup("Search Folder");
-    if (!mSearchPattern)
+    KConfig config( location );
+    config.setGroup( "Search Folder" );
+    if ( !mSearchPattern )
         mSearchPattern = new KMSearchPattern();
-    mSearchPattern->readConfig(&config);
-    QString rootString = config.readEntry("Base");
-    mRoot = kmkernel->findFolderById(rootString);
-    mRecursive = config.readBoolEntry("Recursive");
+    mSearchPattern->readConfig( &config );
+    QString rootString = config.readEntry( "Base" );
+    mRoot = kmkernel->findFolderById( rootString );
+    mRecursive = config.readBoolEntry( "Recursive" );
     return true;
 }
 
 void KMSearch::setSearchPattern(KMSearchPattern *searchPattern)
 {
-    if (running())
+    if ( running() )
         stop();
-    if (mSearchPattern != searchPattern) {
+    if ( mSearchPattern != searchPattern ) {
         delete mSearchPattern;
         mSearchPattern = searchPattern;
     }
@@ -113,15 +111,15 @@ void KMSearch::setSearchPattern(KMSearch
 
 bool KMSearch::inScope(KMFolder* folder) const
 {
-    if (mRoot.isNull() || folder == mRoot)
+    if ( mRoot.isNull() || folder == mRoot )
         return true;
-    if (!recursive())
+    if ( !recursive() )
         return false;
 
     KMFolderDir *rootDir = mRoot->child();
     KMFolderDir *ancestorDir = folder->parent();
-    while (ancestorDir) {
-        if (ancestorDir == rootDir)
+    while ( ancestorDir ) {
+        if ( ancestorDir == rootDir )
             return true;
         ancestorDir = ancestorDir->parent();
     }
@@ -130,10 +128,10 @@ bool KMSearch::inScope(KMFolder* folder)
 
 void KMSearch::start()
 {
-    if (running())
+    if ( running() )
         return;
 
-    if (!mSearchPattern) {
+    if ( !mSearchPattern ) {
         emit finished(true);
         return;
     }
@@ -142,198 +140,119 @@ void KMSearch::start()
     mFoundCount = 0;
     mRunning = true;
     mRunByIndex = false;
-    if(kmkernel->msgIndex() && kmkernel->msgIndex()->startQuery(this)) {
+    // check if this query can be done with the index
+    if ( kmkernel->msgIndex() && kmkernel->msgIndex()->startQuery( this ) ) {
         mRunByIndex = true;
         return;
     }
 
-    QValueList<QGuardedPtr<KMFolder> > folders;
-    folders.append(mRoot);
-    if (recursive()) { //Append all descendants to folders
+    mFolders.append( mRoot );
+    if ( recursive() ) 
+    { 
+        //Append all descendants to folders
         KMFolderNode* node;
         KMFolder* folder;
         QValueListConstIterator<QGuardedPtr<KMFolder> > it;
-        for (it = folders.begin(); it != folders.end(); ++it) {
+        for ( it = mFolders.begin(); it != mFolders.end(); ++it ) 
+        {
             folder = *it;
             KMFolderDir *dir = 0;
-            if (folder)
+            if ( folder )
                 dir = folder->child();
             else
                 dir = &kmkernel->folderMgr()->dir();
-            if (!dir)
+            if ( !dir )
                 continue;
             QPtrListIterator<KMFolderNode> it(*dir);
-            while ((node = it.current())) {
+            while ( (node = it.current()) ) {
                 ++it;
-                if (!node->isDir())
-                {
-                    KMFolder* kmf = dynamic_cast<KMFolder*>(node);
-                    if (kmf)
-                        folders.append(kmf);
+                if ( !node->isDir() ) {
+                    KMFolder* kmf = dynamic_cast<KMFolder*>( node );
+                    if ( kmf ) 
+                        mFolders.append( kmf );
                 }
             }
         }
     }
-
+    
+    mRemainingFolders = mFolders.count();
     mLastFolder = QString::null;
-    mRemainingFolders = folders.count();
-    mRemainingMessages = 0;
-    QValueListConstIterator<QGuardedPtr<KMFolder> > it;
-    for (it = folders.begin(); it != folders.end(); ++it) {
-        KMFolder *folder = *it;
-        if (!folder) {
-            --mRemainingFolders;
-            continue;
-        }
-        //TODO: Get rid of this protocol check, need a bool KMFolder::isComplete()
-        if (folder->folderType() == KMFolderTypeImap) {
-            KMFolderImap *imapFolder =
-                dynamic_cast<KMFolderImap*>( folder->storage() );
-            if (imapFolder && imapFolder->getContentState() ==
-                    KMFolderImap::imapNoInformation) {
-                mIncompleteFolders.append(imapFolder);
-                connect(imapFolder, SIGNAL(folderComplete(KMFolderImap*, bool)),
-                        SLOT(slotFolderComplete(KMFolderImap*, bool)));
-                imapFolder->getFolder();
-            } else {
-                mFolders.append(folder);
-            }
-        } else {
-            mFolders.append(folder);
-        }
-    }
-
-    mProcessNextBatchTimer->start(0, true);
+    mProcessNextBatchTimer->start( 0, true );
 }
 
 void KMSearch::stop()
 {
-    if (!running())
+    if ( !running() )
         return;
-    if(mRunByIndex) {
-        if(kmkernel->msgIndex())
-            kmkernel->msgIndex()->stopQuery(this);
+    if ( mRunByIndex ) {
+        if ( kmkernel->msgIndex() )
+            kmkernel->msgIndex()->stopQuery( this );
     } else {
-        //kill all pending jobs
-        QValueListConstIterator<QGuardedPtr<KMFolderImap> > it;
-        for (it = mIncompleteFolders.begin();
-                it != mIncompleteFolders.end(); ++it) {
-            KMFolderImap *aFolder = (*it);
-            if (aFolder)
-                disconnect(aFolder,
-                        SIGNAL(folderComplete(KMFolderImap*, bool)),
-                        this,
-                        SLOT(slotFolderComplete(KMFolderImap*, bool)));
-        }
         mIncompleteFolders.clear();
         QValueListConstIterator<QGuardedPtr<KMFolder> > jt;
-        for (jt = mOpenedFolders.begin(); jt != mOpenedFolders.end(); ++jt) {
+        for ( jt = mOpenedFolders.begin(); jt != mOpenedFolders.end(); ++jt ) {
             KMFolder *folder = *jt;
             if (folder)
                 folder->close();
         }
     }
-    mOpenedFolders.clear();
-    mRemainingMessages = -1;
     mRemainingFolders = -1;
+    mOpenedFolders.clear();
     mFolders.clear();
-    mLastFolder = "";
+    mLastFolder = QString::null;
     mRunByIndex = mRunning = false;
-    mIdle = false;
     emit finished(false);
 }
 
 void KMSearch::slotProcessNextBatch()
 {
-    if (!running())
+    if ( !running() )
         return;
-    mIdle = false;
 
-    if (mSerNums.count() != 0) {
-        int i = 10;
-        QValueListIterator<Q_UINT32> it;
-        for (it = mSerNums.begin(); it != mSerNums.end();) {
-            if (--i == 0)
-                break;
-
-            Q_UINT32 serNum = *it;
-            it = mSerNums.erase(it);
-            --mRemainingMessages;
-            ++mSearchedCount;
-
-            //TODO: matches should try header rules first and check
-            // rule->needsBody() and download imap message if needed
-            if (mSearchPattern && !mSearchPattern->matches(serNum))
-                continue;
-            emit found(serNum);
-            ++mFoundCount;
-        }
-        mProcessNextBatchTimer->start(0, true);
+    if ( mFolders.count() != 0 ) 
+    {
+        KMFolder *folder = *( mFolders.begin() );
+        mFolders.erase( mFolders.begin() );
+        if ( folder ) 
+        {
+            mLastFolder = folder->label();
+            folder->open();
+            mOpenedFolders.append( folder );
+            connect( folder->storage(), 
+                    SIGNAL( searchDone( KMFolder*, QValueList<Q_UINT32> ) ),
+                    this,
+                    SLOT( slotSearchFolderDone( KMFolder*, QValueList<Q_UINT32> ) ) );
+            folder->storage()->search( mSearchPattern );
+        } else
+          --mRemainingFolders;
+        mProcessNextBatchTimer->start( 0, true );
         return;
     }
+}
 
-    if (mFolders.count() != 0) {
-        --mRemainingFolders;
-        KMFolder *folder = *(mFolders.begin());
-        if (folder) {
-            if (folder->isSystemFolder())
-                mLastFolder = i18n(folder->name().utf8());
-            else
-                mLastFolder = folder->name();
-        }
-        mFolders.erase(mFolders.begin());
-        if (folder) {
-            folder->open();
-            mOpenedFolders.append(folder);
-            for(int i = 0; i < folder->count(); ++i) {
-                Q_UINT32 serNum = kmkernel->msgDict()->getMsgSerNum(folder, i);
-                ++mRemainingMessages;
-                // Prepend message to the list to search newest mail first.
-                mSerNums.prepend(serNum);
-            }
-        }
-        mProcessNextBatchTimer->start(0, true);
-        return;
+void KMSearch::slotSearchFolderDone( KMFolder* folder, QValueList<Q_UINT32> serNums )
+{
+    kdDebug(5006) << k_funcinfo << folder->label() << " found " << serNums.count() << endl;
+    --mRemainingFolders;
+    mSearchedCount += folder->count();
+    folder->close();
+    mOpenedFolders.remove( folder );
+    QValueListIterator<Q_UINT32> it;
+    for ( it = serNums.begin(); it != serNums.end(); ++it )
+    {
+        emit found( *it );
+        ++mFoundCount;
     }
-    if (mRemainingFolders == 0) {
+    if ( mRemainingFolders <= 0 )
+    {
         mRunning = false;
-        QValueListConstIterator<QGuardedPtr<KMFolder> > it;
-        for (it = mOpenedFolders.begin(); it != mOpenedFolders.end(); ++it) {
-            KMFolder *folder = *it;
-            if (folder)
-                folder->close();
-        }
-        mOpenedFolders.clear();
-        mRemainingMessages = -1;
+        mLastFolder = QString::null;
         mRemainingFolders = -1;
         mFolders.clear();
-        mLastFolder = "";
-        emit finished(true);
-        return;
-    }
-
-    //wait for imap folders to be retrieved
-    mIdle = true;
-}
-
-void KMSearch::slotFolderComplete(KMFolderImap *folder, bool success)
-{
-    disconnect(folder, SIGNAL(folderComplete(KMFolderImap*, bool)),
-            this, SLOT(slotFolderComplete(KMFolderImap*, bool)));
-
-    if (success) {
-        //if !(mSearchPattern.hasBodyRules())
-        mFolders.append(folder->folder());
-        //else
-        //  get all the bodies of messages in the folder, need kroupware body caching
-        if (mIdle)
-            mProcessNextBatchTimer->start(0, true);
-    } else {
-        stop();
+        emit finished( true );
     }
 }
 
-
 //-----------------------------------------------------------------------------
 KMFolderSearch::KMFolderSearch(KMFolder* folder, const char* name)
   : FolderStorage(folder, name)
Index: kmfoldersearch.h
===================================================================
RCS file: /home/kde/kdepim/kmail/kmfoldersearch.h,v
retrieving revision 1.26
diff -u -3 -p -r1.26 kmfoldersearch.h
--- kmfoldersearch.h	10 Jun 2004 16:03:40 -0000	1.26
+++ kmfoldersearch.h	3 Sep 2004 19:30:40 -0000
@@ -63,7 +63,7 @@ signals:
 
 protected slots:
   void slotProcessNextBatch();
-  void slotFolderComplete(KMFolderImap *folder, bool success);
+  void slotSearchFolderDone( KMFolder*, QValueList<Q_UINT32> );
 
 protected:
   friend class KMIndexSearchTarget;
@@ -73,7 +73,6 @@ protected:
   void setCurrentFolder(const QString &f) { mLastFolder = f; }
 
 private:
-  int mRemainingMessages;
   int mRemainingFolders;
   bool mRecursive, mRunning, mIdle, mRunByIndex;
   QGuardedPtr<KMFolder> mRoot;
Index: kmsearchpattern.cpp
===================================================================
RCS file: /home/kde/kdepim/kmail/kmsearchpattern.cpp,v
retrieving revision 1.70
diff -u -3 -p -r1.70 kmsearchpattern.cpp
--- kmsearchpattern.cpp	31 Jul 2004 13:47:10 -0000	1.70
+++ kmsearchpattern.cpp	3 Sep 2004 19:30:40 -0000
@@ -161,6 +161,25 @@ const QString KMSearchRule::asString() c
   return result;
 }
 
+QString KMSearchRule::asImapString() const
+{
+  QString result;
+  if ( mFunction == FuncContainsNot )
+    result = "NOT ";
+  else if ( mFunction != FuncContains )
+    return QString::null;
+
+  if ( mField == "<message>" )
+    result += "TEXT ";
+  else if ( mField == "<body>" )
+    result += "BODY ";
+  else
+    return QString::null;
+
+  result += "\"" + mContents + "\"";
+
+  return result;
+}
 
 
 //==================================================
@@ -685,7 +704,7 @@ KMSearchPattern::~KMSearchPattern()
 {
 }
 
-bool KMSearchPattern::matches( const KMMessage * msg ) const
+bool KMSearchPattern::matches( const KMMessage * msg, bool ignoreBody ) const
 {
   if ( isEmpty() )
     return true;
@@ -694,20 +713,22 @@ bool KMSearchPattern::matches( const KMM
   switch ( mOperator ) {
   case OpAnd: // all rules must match
     for ( it.toFirst() ; it.current() ; ++it )
-      if ( !(*it)->matches( msg ) )
-	return false;
+      if ( !((*it)->requiresBody() && ignoreBody) )
+        if ( !(*it)->matches( msg ) )
+          return false;
     return true;
   case OpOr:  // at least one rule must match
     for ( it.toFirst() ; it.current() ; ++it )
-      if ( (*it)->matches( msg ) )
-	return true;
+      if ( !((*it)->requiresBody() && ignoreBody) )
+        if ( (*it)->matches( msg ) )
+          return true;
     // fall through
   default:
     return false;
   }
 }
 
-bool KMSearchPattern::matches( const DwString & aStr ) const
+bool KMSearchPattern::matches( const DwString & aStr, bool ignoreBody ) const
 {
   if ( isEmpty() )
     return true;
@@ -717,20 +738,22 @@ bool KMSearchPattern::matches( const DwS
   switch ( mOperator ) {
   case OpAnd: // all rules must match
     for ( it.toFirst() ; it.current() ; ++it )
-      if ( !(*it)->matches( aStr, msg ) )
-	return false;
+      if ( !((*it)->requiresBody() && ignoreBody) )
+        if ( !(*it)->matches( aStr, msg ) )
+          return false;
     return true;
   case OpOr:  // at least one rule must match
     for ( it.toFirst() ; it.current() ; ++it )
-      if ( (*it)->matches( aStr, msg ) )
-	return true;
+      if ( !((*it)->requiresBody() && ignoreBody) )
+        if ( (*it)->matches( aStr, msg ) )
+          return true;
     // fall through
   default:
     return false;
   }
 }
 
-bool KMSearchPattern::matches( Q_UINT32 serNum ) const
+bool KMSearchPattern::matches( Q_UINT32 serNum, bool ignoreBody ) const
 {
   if ( isEmpty() )
     return true;
@@ -747,14 +770,14 @@ bool KMSearchPattern::matches( Q_UINT32 
   if ( !opened )
     folder->open();
   KMMsgBase *msgBase = folder->getMsgBase(idx);
-  if (requiresBody()) {
+  if (requiresBody() && !ignoreBody) {
     bool unGet = !msgBase->isMessage();
     KMMessage *msg = folder->getMsg(idx);
-    res = matches( msg );
+    res = matches( msg, ignoreBody );
     if (unGet)
       folder->unGetMsg(idx);
   } else {
-    res = matches( folder->getDwString(idx) );
+    res = matches( folder->getDwString(idx), ignoreBody );
   }
   if ( !opened )
     folder->close();
@@ -882,6 +905,22 @@ QString KMSearchPattern::asString() cons
   return result;
 }
 
+QString KMSearchPattern::asImapString() const {
+  QStringList parts;
+  QString result;
+
+  for ( QPtrListIterator<KMSearchRule> it( *this ) ; it.current() ; ++it )
+    if ( !(*it)->asImapString().isEmpty() )
+      parts += (*it)->asImapString();
+  
+  if ( mOperator == OpOr )
+    result = "(OR " + parts.join(" ") + ")";
+  else
+    result = parts.join(" ");
+
+  return result;
+}
+
 const KMSearchPattern & KMSearchPattern::operator=( const KMSearchPattern & other ) {
   if ( this == &other )
     return *this;
Index: kmsearchpattern.h
===================================================================
RCS file: /home/kde/kdepim/kmail/kmsearchpattern.h,v
retrieving revision 1.27
diff -u -3 -p -r1.27 kmsearchpattern.h
--- kmsearchpattern.h	31 Jul 2004 20:55:49 -0000	1.27
+++ kmsearchpattern.h	3 Sep 2004 19:30:40 -0000
@@ -138,6 +138,9 @@ public:
   /** Returns the rule as string. For debugging.*/
   const QString asString() const;
 
+  /** Returns an imap search command */
+  QString asImapString() const;
+
 private:
   static Function configValueToFunc( const char * str );
   static QString functionToString( Function function );
@@ -308,9 +311,9 @@ public:
 
       @return TRUE if the match was successful, FALSE otherwise.
   */
-  bool matches( const KMMessage * msg ) const;
-  bool matches( const DwString & str ) const;
-  bool matches( Q_UINT32 sernum ) const;
+  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 */
@@ -359,6 +362,9 @@ public:
   /** Returns the pattern as string. For debugging.*/
   QString asString() const;
 
+  /** Returns an imap search command */
+  QString asImapString() const;
+
   /** Overloaded assignment operator. Makes a deep copy. */
   const KMSearchPattern & operator=( const KMSearchPattern & aPattern );
 

[Attachment #8 (application/pgp-signature)]

_______________________________________________
KMail developers mailing list
KMail-devel@kde.org
https://mail.kde.org/mailman/listinfo/kmail-devel


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic