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

List:       kmail-devel
Subject:    Re: [Patch] Improved threading (by references and subject)
From:       Till Adam <till () adam-lilienthal ! de>
Date:       2003-03-09 9:11:39
[Download RAW message or body]

On Sunday 09 March 2003 09:38, Till Adam wrote:

> Do you want me to regenerate a patch with this in, no tabs, and p, or can
> you manage with what you have?

What the hell. Attached. :)

Till
["ImprovedThreadingRC1.diff" (text/x-diff)]

Index: kmfoldermaildir.cpp
===================================================================
RCS file: /home/kde/kdepim/kmail/kmfoldermaildir.cpp,v
retrieving revision 1.50
diff -u -3 -p -w -r1.50 kmfoldermaildir.cpp
--- kmfoldermaildir.cpp 27 Feb 2003 10:39:48 -0000      1.50
+++ kmfoldermaildir.cpp 9 Mar 2003 08:58:50 -0000
@@ -558,7 +558,7 @@ void KMFolderMaildir::readFileHeaderInte
 
   QCString dateStr, fromStr, toStr, subjStr;
   QCString xmarkStr, replyToIdStr, msgIdStr, referencesStr;
-  QCString statusStr;
+  QCString statusStr, replyToAuxIdStr;
 
   // iterate through this file until done
   while (!atEof)
@@ -574,7 +574,10 @@ void KMFolderMaildir::readFileHeaderInte
       if ((replyToIdStr.isEmpty() || (replyToIdStr[0] != '<'))  &&
           !referencesStr.isEmpty() && referencesStr[0] == '<')
       {
-        replyToIdStr = referencesStr;
+             // use the last reference, instead of missing In-Reply-To
+             int leftAngle = referencesStr.findRev( '<' );
+             if (leftAngle != -1)
+                     replyToIdStr = referencesStr.mid(leftAngle);
       }
 
       if (!statusStr.isEmpty())
@@ -594,8 +597,9 @@ void KMFolderMaildir::readFileHeaderInte
 
       KMMsgInfo *mi = new KMMsgInfo(this);
       mi->init(subjStr, fromStr, toStr, 0, status, xmarkStr, replyToIdStr, 
-              msgIdStr, file.local8Bit(), KMMsgEncryptionStateUnknown, 
-              KMMsgSignatureStateUnknown, KMMsgMDNStateUnknown, f.size());
+              replyToAuxIdStr, msgIdStr, file.local8Bit(), 
+              KMMsgEncryptionStateUnknown, KMMsgSignatureStateUnknown, 
+              KMMsgMDNStateUnknown, f.size());
       if (!dateStr.isEmpty())
         mi->setDate(dateStr);
       mi->setDirty(false);
@@ -658,12 +662,21 @@ void KMFolderMaildir::readFileHeaderInte
       referencesStr = QCString(line+12);
 
       leftAngle = referencesStr.findRev('<');
+      leftAngle = referencesStr.findRev( '<', leftAngle-1);
       if (leftAngle != -1)
         referencesStr = referencesStr.mid(leftAngle);
+      rightAngle = referencesStr.findRev( '>' );
+      if (rightAngle != -1)
+       referencesStr.truncate( rightAngle + 1 );
 
+      // Store the second to last reference in the replyToAuxIdStr
+      // It is a good candidate for threading the message below if the
+      // message In-Reply-To points to is not kept in this folder, 
+      // but e.g. in an Outbox
+      replyToAuxIdStr = referencesStr;
       rightAngle = referencesStr.find('>');
       if (rightAngle != -1)
-        referencesStr.truncate(rightAngle + 1);
+         replyToAuxIdStr.truncate( rightAngle + 1 );
     }
     else if (strncasecmp(line, "Message-Id:", 11) == 0 && isblank(line[11]))
     {
Index: kmfoldermbox.cpp
===================================================================
RCS file: /home/kde/kdepim/kmail/kmfoldermbox.cpp,v
retrieving revision 1.57
diff -u -3 -p -w -r1.57 kmfoldermbox.cpp
--- kmfoldermbox.cpp    26 Feb 2003 13:14:01 -0000      1.57
+++ kmfoldermbox.cpp    9 Mar 2003 08:58:52 -0000
@@ -527,7 +527,7 @@ int KMFolderMbox::createIndexFromContent
   char line[MAX_LINE];
   char status[8], xstatus[8];
   QCString subjStr, dateStr, fromStr, toStr, xmarkStr, *lastStr=0;
-  QCString replyToIdStr, referencesStr, msgIdStr;
+  QCString replyToIdStr, replyToAuxIdStr, referencesStr, msgIdStr;
   bool atEof = FALSE;
   bool inHeader = TRUE;
   KMMsgInfo* mi;
@@ -554,6 +554,8 @@ int KMFolderMbox::createIndexFromContent
   *xstatus = '\0';
   xmarkStr = "";
   replyToIdStr = "";
+  replyToAuxIdStr = "";
+  referencesStr = "";
   msgIdStr = "";
   needStatus = 3;
 
@@ -583,10 +585,15 @@ int KMFolderMbox::createIndexFromContent
        {
          if ((replyToIdStr.isEmpty() || (replyToIdStr[0] != '<'))  &&
              !referencesStr.isEmpty() && referencesStr[0] == '<') {
-           replyToIdStr = referencesStr;
+                 // use the last reference, instead of missing In-Reply-To
+                 int leftAngle = referencesStr.findRev( '<' );
+                 if (leftAngle != -1)
+                     replyToIdStr = referencesStr.mid(leftAngle);
          }
+        
          mi = new KMMsgInfo(this);
-         mi->init(subjStr, fromStr, toStr, 0, KMMsgStatusNew, xmarkStr, replyToIdStr, \
msgIdStr, +         mi->init(subjStr, fromStr, toStr, 0, KMMsgStatusNew, xmarkStr,
+                         replyToIdStr, replyToAuxIdStr, msgIdStr,
                   KMMsgEncryptionStateUnknown, KMMsgSignatureStateUnknown, 
                   KMMsgMDNStateUnknown, offs, size);
          mi->setStatus("RO","O");
@@ -599,6 +606,7 @@ int KMFolderMbox::createIndexFromContent
          needStatus = 3;
          xmarkStr = "";
          replyToIdStr = "";
+         replyToAuxIdStr = "";
          referencesStr = "";
          msgIdStr = "";
          dateStr = "";
@@ -658,11 +666,22 @@ int KMFolderMbox::createIndexFromContent
       int leftAngle, rightAngle;
       referencesStr = QCString(line+12);
       leftAngle = referencesStr.findRev( '<' );
+      leftAngle = referencesStr.findRev( '<', leftAngle-1);
       if (leftAngle != -1)
        referencesStr = referencesStr.mid( leftAngle );
-      rightAngle = referencesStr.find( '>' );
+      rightAngle = referencesStr.findRev( '>' );
       if (rightAngle != -1)
        referencesStr.truncate( rightAngle + 1 );
+
+      // Store the second to last reference in the replyToAuxIdStr
+      // It is a good candidate for threading the message below if the
+      // message In-Reply-To points to is not kept in this folder, 
+      // but e.g. in an Outbox
+      replyToAuxIdStr = referencesStr;
+      rightAngle = referencesStr.find( '>' );
+      if (rightAngle != -1)
+         replyToAuxIdStr.truncate( rightAngle + 1 );
+
     }
     else if (strncasecmp(line,"Message-Id:",11)==0 && isblank(line[11])) {
       int rightAngle;
Index: kmheaders.cpp
===================================================================
RCS file: /home/kde/kdepim/kmail/kmheaders.cpp,v
retrieving revision 1.484
diff -u -3 -p -w -r1.484 kmheaders.cpp
--- kmheaders.cpp       26 Feb 2003 13:14:01 -0000      1.484
+++ kmheaders.cpp       9 Mar 2003 08:58:57 -0000
@@ -2300,7 +2300,7 @@ void KMHeaders::setSorting( int column, 
 }
 
 //Flatten the list and write it to disk
-#define KMAIL_SORT_VERSION 1011
+#define KMAIL_SORT_VERSION 1012
 #define KMAIL_SORT_FILE(x) x->indexLocation() + ".sorted"
 #define KMAIL_SORT_HEADER "## KMail Sort V%04d\n\t"
 #define KMAIL_MAGIC_HEADER_OFFSET 21 //strlen(KMAIL_SORT_HEADER)
@@ -2385,32 +2385,77 @@ bool KMHeaders::writeSortOrder()
        }
       }
     }
-    KMMsgBase *kmb;
-    while(KMHeaderItem *i = items.pop()) {
-      kmb = mFolder->getMsgBase( i->mMsgId );
 
-      QString replymd5 = kmb->replyToIdMD5();
-      int parent_id = -2; //no parent, top level
-      if(!replymd5.isEmpty()) {
        if(mIdTree.isEmpty()) {
-         QString md5;
          for(int x = 0; x < mFolder->count(); x++) {
+           QString md5;
            if(mItems[x]) {
-             md5 = mFolder->getMsgBase(x)->msgIdMD5();
-             if(md5.isEmpty()) continue;
-             if(mIdTree[md5])
-                 ;
-             else
+               KMMsgBase *mb = mFolder->getMsgBase(x);
+               md5 = mb->msgIdMD5();
+               if (!md5.isEmpty() && !mIdTree[md5])
                  mIdTree.insert(md5, mItems[x]);
            }
          }
        }
-       KMHeaderItem *p = mIdTree[replymd5];
-       if(p)
+    QDict<KMHeaderItem> msgSubjects(mFolder->count()*2);
+    for(int x = 0; x < mFolder->count(); x++) {
+       if(mItems[x]) {
+           QString subjMD5;
+           KMMsgBase *mb = mFolder->getMsgBase(x);
+           subjMD5 = mb->strippedSubjectMD5();
+           if (subjMD5.isEmpty()) {
+               mb->initStrippedSubjectMD5();
+               subjMD5 = mb->strippedSubjectMD5();
+           }
+           if( !subjMD5.isEmpty() && !msgSubjects.find(subjMD5) ) {
+               QString replyToIdMD5 = mb->replyToIdMD5();
+               QString replyToAuxIdMD5 = mb->replyToAuxIdMD5();
+               if ( (replyToIdMD5.isEmpty() || !mIdTree[replyToIdMD5])
+               && (replyToAuxIdMD5.isEmpty() || !mIdTree[replyToAuxIdMD5]) )
+                   msgSubjects.insert(subjMD5, mItems[x]);
+           }
+       }
+    }
+
+    KMMsgBase *kmb;
+    while(KMHeaderItem *i = items.pop()) {
+      kmb = mFolder->getMsgBase( i->mMsgId );
+
+      QString replymd5 = kmb->replyToIdMD5();
+      int parent_id = -2; //no parent, top level
+      KMHeaderItem *p = NULL;
+      if(!replymd5.isEmpty())
+         p = mIdTree[replymd5];
+
+      if (!p) {
+         // If we dont have a replyToId, or if we have one and the
+         // corresponding message is not in this folder, as happens
+         // if you keep your outgoing messages in an OUTBOX, for
+         // example, try the list of references, because the second
+         // to last will likely be in this folder. replyToAuxIdMD5 ontains
+         // the second to last one.
+         QString  ref = kmb->replyToAuxIdMD5();
+         if (!ref.isEmpty())
+             p = mIdTree[ref];
+      }
+      // still no parent, let's try by subject
+      // Force unprefixed subjects that would be threaded by subject
+      // to the top level.
+      if (!p && kmb->subjectIsPrefixed()) {
+       
+       QString subjMD5 = kmb->strippedSubjectMD5();
+       if (!subjMD5.isEmpty()) {
+         p = msgSubjects[subjMD5];
+       }
+      }
+      if( p) {
          parent_id = p->mMsgId;
-       else
+       if (parent_id == i->mMsgId)
          parent_id = -1;
       }
+      else
+       parent_id = -1;
+
       internalWriteItem(sortStream, mFolder, i->mMsgId, parent_id,
                        i->key(mSortCol, !mSortDescending), FALSE);
       //double check for magic headers
@@ -2440,7 +2485,6 @@ bool KMHeaders::writeSortOrder()
   return TRUE;
 }
 
-
 void KMHeaders::appendUnsortedItem(KMHeaderItem *khi)
 {
   QString sortFile = KMAIL_SORT_FILE(mFolder);
@@ -2565,6 +2609,8 @@ static int compare_KMSortCacheItem(const
     return ret;
 }
 
+
+
 bool KMHeaders::readSortOrder(bool set_selection)
 {
     //all cases
@@ -2768,20 +2814,72 @@ bool KMHeaders::readSortOrder(bool set_s
     if (appended && threaded && !unparented.isEmpty()) {
        CREATE_TIMER(reparent);
        START_TIMER(reparent);
-       KMSortCacheItem *i;
+       // Build two dictionaries, one with all messages and their ids, and
+       // one with the md5 hashes of the subject stripped of prefixes such as
+       // Re: or similar.
        QDict<KMSortCacheItem> msgs(mFolder->count() * 2);
+       QDict<KMSortCacheItem> msgSubjects(mFolder->count() * 2);
        for(int x = 0; x < mFolder->count(); x++) {
-           QString md5 = mFolder->getMsgBase(x)->msgIdMD5();
-           if(md5.isEmpty()) continue;
+           KMMsgBase *mi = mFolder->getMsgBase(x);
+           QString md5 = mi->msgIdMD5();
+           if(!md5.isEmpty())
            msgs.insert(md5, sortCache[x]);
        }
+       for(int x = 0; x < mFolder->count(); x++) {
+           KMMsgBase *mi = mFolder->getMsgBase(x);
+           QString subjMD5 = mi->strippedSubjectMD5();
+           if (subjMD5.isEmpty()) {
+               mFolder->getMsgBase(x)->initStrippedSubjectMD5();
+               subjMD5 = mFolder->getMsgBase(x)->strippedSubjectMD5();
+           }
+           // The first message with a certain subject is where we want to
+           // thread the other messages with the same suject below. Only keep
+           // that in the dict. Also only accept messages which would not
+           // otherwise be threaded by IDs as top level messages to avoid 
+           // circular threading.
+           if( !subjMD5.isEmpty() && !msgSubjects.find(subjMD5) ) {
+               QString replyToIdMD5 = mi->replyToIdMD5();
+               QString replyToAuxIdMD5 = mi->replyToAuxIdMD5();
+               if ( (replyToIdMD5.isEmpty() || !msgs.find(replyToIdMD5))
+               && (replyToAuxIdMD5.isEmpty() || !msgs.find(replyToAuxIdMD5)) )
+                   msgSubjects.insert(subjMD5, sortCache[x]);
+           }
+       }
        for(QPtrListIterator<KMSortCacheItem> it(unparented); it.current(); ++it) {
-           replyToIdMD5 = mFolder->getMsgBase((*it)->id())->replyToIdMD5();
-           if(!replyToIdMD5.isEmpty() && (i = msgs[replyToIdMD5])) {
-               i->addUnsortedChild((*it));
+           KMSortCacheItem *parent=NULL;
+           KMMsgBase *msg =  mFolder->getMsgBase((*it)->id());
+           QString replyToIdMD5 = msg->replyToIdMD5();
+           if(!replyToIdMD5.isEmpty())
+               parent = msgs[replyToIdMD5];
+           if (!parent) {
+               // If we dont have a replyToId, or if we have one and the
+               // corresponding message is not in this folder, as happens
+               // if you keep your outgoing messages in an OUTBOX, for
+               // example, try the list of references, because the second
+               // to last will likely be in this folder. replyToAuxIdMD5
+               // contains the second to last one.
+               QString  ref = msg->replyToAuxIdMD5();
+               if (!ref.isEmpty())
+                   parent = msgs[ref];
+           }
+           if (!parent msg->subjectIsPrefixed()) {
+             // Still no parent, let's try by subject, but only if the
+             // subhect is prefixed. This is necessary to make for 
+             // example cvs commit mailing lists work as expected without 
+             // having to turn threading off alltogether.
+             // If we have a parent, make sure it's not ourselves
+             QString subjMD5 = msg->strippedSubjectMD5();
+             if (!subjMD5.isEmpty()) {
+               parent = msgSubjects[subjMD5];
+             }
+           }
+           // If we have a parent, make sure it's not ourselves.
+           if ( parent && (parent != (*it)) ) {
+               parent->addUnsortedChild((*it));
                if(sortStream)
                    (*it)->updateSortFile(sortStream, mFolder);
-           } else { //oh well we tried, to the root with you!
+           } else {
+               //oh well we tried, to the root with you!
                root.addUnsortedChild((*it));
            }
        }
@@ -2845,7 +2943,6 @@ bool KMHeaders::readSortOrder(bool set_s
     for (KMHeaderItem *khi=static_cast<KMHeaderItem*>(firstChild()); \
khi!=0;khi=static_cast<KMHeaderItem*>(khi->nextSibling()))  khi->setOpen(true);
 
-
     END_TIMER(header_creation);
     SHOW_TIMER(header_creation);
 
@@ -2911,6 +3008,7 @@ bool KMHeaders::readSortOrder(bool set_s
        fclose(sortStream);
     return TRUE;
 }
+
 
 
 //-----------------------------------------------------------------------------
Index: kmkernel.cpp
===================================================================
RCS file: /home/kde/kdepim/kmail/kmkernel.cpp,v
retrieving revision 1.164
diff -u -3 -p -w -r1.164 kmkernel.cpp
--- kmkernel.cpp        28 Feb 2003 04:42:49 -0000      1.164
+++ kmkernel.cpp        9 Mar 2003 08:59:00 -0000
@@ -691,13 +691,14 @@ void KMKernel::init()
   the_popFilterMgr     = new KMFilterMgr(true);
   the_filterActionDict = new KMFilterActionDict;
 
+  // moved up here because KMMessage::stripOffPrefixes is used below -ta
+  KMMessage::readConfig();
   initFolders(cfg);
   the_acctMgr->readConfig();
   the_filterMgr->readConfig();
   the_popFilterMgr->readConfig();
   cleanupImapFolders();
 
-  KMMessage::readConfig();
   the_msgSender = new KMSender;
   the_server_is_ready = true;
 
Index: kmmessage.cpp
===================================================================
RCS file: /home/kde/kdepim/kmail/kmmessage.cpp,v
retrieving revision 1.377
diff -u -3 -p -w -r1.377 kmmessage.cpp
--- kmmessage.cpp       26 Feb 2003 14:58:33 -0000      1.377
+++ kmmessage.cpp       9 Mar 2003 08:59:06 -0000
@@ -2136,6 +2136,54 @@ QString KMMessage::replyToIdMD5(void) co
   return result;
 }
 
+//-----------------------------------------------------------------------------
+QString KMMessage::references(void) const
+{
+    int leftAngle, rightAngle;
+    QString  references = headerField("References");
+
+    // keep the last two entries for threading
+    leftAngle = references.findRev( '<' );
+    leftAngle = references.findRev( '<', leftAngle-1 );
+    if (leftAngle != -1)
+       references = references.mid( leftAngle );
+    rightAngle = references.findRev( '>' );
+    if (rightAngle != -1)
+       references.truncate( rightAngle + 1 );
+
+    if (!references.isEmpty() && references[0] == '<')
+       return references;
+    else
+       return "";
+}
+
+//-----------------------------------------------------------------------------
+QString KMMessage::replyToAuxIdMD5(void) const
+{
+    int rightAngle;
+    QString  result = references();
+    // references contains two items, use the first one
+    // (the second to last reference)
+    rightAngle = result.find( '>' );
+    if (rightAngle != -1)
+       result.truncate (rightAngle+1);
+
+    return KMMessagePart::encodeBase64( result );
+}
+
+//-----------------------------------------------------------------------------
+QString KMMessage::strippedSubjectMD5(void) const
+{
+    QString  result = stripOffPrefixes(subject());
+    return KMMessagePart::encodeBase64( result );
+}
+
+//-----------------------------------------------------------------------------
+bool KMMessage::subjectIsPrefixed(void) const
+{
+    return !(strippedSubjectMD5() == KMMessagePart::encodeBase64(subject()));
+
+}
 
 //-----------------------------------------------------------------------------
 void KMMessage::setReplyToId(const QString& aStr)
Index: kmmessage.h
===================================================================
RCS file: /home/kde/kdepim/kmail/kmmessage.h,v
retrieving revision 1.128
diff -u -3 -p -w -r1.128 kmmessage.h
--- kmmessage.h 23 Feb 2003 19:12:09 -0000      1.128
+++ kmmessage.h 9 Mar 2003 08:59:08 -0000
@@ -333,6 +333,9 @@ public:
   virtual QString subject(void) const;
   virtual void setSubject(const QString& aStr);
 
+  /** Calculate strippedSubject */
+  virtual void initStrippedSubjectMD5() {};
+
   /** Check for prefixes @p prefixRegExps in @p str. If none
       is found, @p newPrefix + ' ' is prepended to @p str and the
       resulting string is returned. If @p replace is true, any
@@ -352,7 +355,7 @@ public:
       is found, @p newPrefix + ' ' is prepended to the subject and the
       resulting string is returned. If @p replace is true, any
       sequence of whitespace-delimited prefixes at the beginning of
-      @ref #subject() is replaced by @p newPrefix.
+      @ref #subject() is replaced by @p newPrefix
   **/
   QString cleanSubject(const QStringList& prefixRegExps, bool replace,
                       const QString& newPrefix) const;
@@ -376,12 +379,38 @@ public:
   virtual void setReplyToId(const QString& aStr);
   virtual QString replyToIdMD5(void) const;
 
+  /** Get the second to last id from the References header
+      field. If outgoing messages are not kept in the same
+      folder as incoming ones, this will be a good place to
+      thread the message beneath.
+      bob               <- second to last reference points to this
+       |_kmailuser      <- not in our folder, but Outbox
+           |_bob        <- In-Reply-To points to our mail above
+
+      Thread like this:
+      bob
+       |_bob
+
+      using replyToAuxIdMD5
+    */
+  virtual QString replyToAuxIdMD5(void) const;
+
+  /**
+    Get a hash of the subject with all prefixes such as Re: removed.
+    Used for threading.
+  */
+  virtual QString strippedSubjectMD5(void) const;
+
+  /** Is the subject prefixed by Re: or similar? */
+  virtual bool subjectIsPrefixed(void) const;
+  
   /** Get or set the 'Message-Id' header field */
   virtual QString msgId(void) const;
   virtual void setMsgId(const QString& aStr);
   virtual QString msgIdMD5(void) const;
 
-  /** Set the references for this message */
+  /** Get or set the references for this message */
+  virtual QString references(void) const;
   virtual void setReferences(const QCString& aStr);
 
   /** Returns the message ID, useful for followups */
Index: kmmsgbase.cpp
===================================================================
RCS file: /home/kde/kdepim/kmail/kmmsgbase.cpp,v
retrieving revision 1.137
diff -u -3 -p -w -r1.137 kmmsgbase.cpp
--- kmmsgbase.cpp       18 Feb 2003 03:26:17 -0000      1.137
+++ kmmsgbase.cpp       9 Mar 2003 08:59:10 -0000
@@ -1047,6 +1047,13 @@ const uchar *KMMsgBase::asIndexString(in
   STORE_DATA(MsgCryptoStatePart, tmp);
   tmp = mdnSentState();
   STORE_DATA(MsgMDNSentPart, tmp);
+
+  tmp_str = replyToAuxIdMD5().stripWhiteSpace();
+  STORE_DATA_LEN(MsgReplyToAuxIdMD5Part, tmp_str.unicode(), tmp_str.length() * 2, true);
+
+  tmp_str = strippedSubjectMD5().stripWhiteSpace();
+  STORE_DATA_LEN(MsgStrippedSubjectMD5Part, tmp_str.unicode(), tmp_str.length() * 2, true);
+
 #undef STORE_DATA_LEN
   return ret;
 }
Index: kmmsgbase.h
===================================================================
RCS file: /home/kde/kdepim/kmail/kmmsgbase.h,v
retrieving revision 1.52
diff -u -3 -p -w -r1.52 kmmsgbase.h
--- kmmsgbase.h 26 Dec 2002 10:18:15 -0000      1.52
+++ kmmsgbase.h 9 Mar 2003 08:59:10 -0000
@@ -148,6 +148,9 @@ public:
   virtual QString toStrip(void) const = 0;
   virtual QString replyToIdMD5(void) const = 0;
   virtual QString msgIdMD5(void) const = 0;
+  virtual QString replyToAuxIdMD5(void) const = 0;
+  virtual QString strippedSubjectMD5(void) const = 0;
+  virtual bool subjectIsPrefixed(void) const = 0;
   virtual time_t date(void) const = 0;
   virtual QString dateStr(void) const;
   virtual QString xmark(void) const = 0;
@@ -166,6 +169,9 @@ public:
   virtual void setSubject(const QString&) = 0;
   virtual void setXMark(const QString&) = 0;
 
+  /** Calculate strippedSubject */
+  virtual void initStrippedSubjectMD5() = 0;
+
   /** Return contents as index string. This string is of indexStringLength() size */
   const uchar *asIndexString(int &len) const;
 
@@ -284,7 +290,10 @@ public:
     MsgDatePart = 10,
     MsgFilePart = 11,
     MsgCryptoStatePart = 12,
-    MsgMDNSentPart = 13
+    MsgMDNSentPart = 13,
+    //another two unicode strings
+    MsgReplyToAuxIdMD5Part = 14,
+    MsgStrippedSubjectMD5Part = 15
   };
   /** access to long msgparts */
   off_t getLongPart(MsgPartType) const;
Index: kmmsginfo.cpp
===================================================================
RCS file: /home/kde/kdepim/kmail/kmmsginfo.cpp,v
retrieving revision 1.43
diff -u -3 -p -w -r1.43 kmmsginfo.cpp
--- kmmsginfo.cpp       26 Dec 2002 10:18:15 -0000      1.43
+++ kmmsginfo.cpp       9 Mar 2003 08:59:12 -0000
@@ -17,12 +17,13 @@ public:
        SUBJECT_SET = 0x01, TO_SET = 0x02, REPLYTO_SET = 0x04, MSGID_SET=0x08,
        DATE_SET = 0x10, OFFSET_SET = 0x20, SIZE_SET = 0x40,
        XMARK_SET=0x100, FROM_SET=0x200, FILE_SET=0x400, ENCRYPTION_SET=0x800,
-       SIGNATURE_SET=0x1000, MDN_SET=0x2000,
+       SIGNATURE_SET=0x1000, MDN_SET=0x2000, REPLYTOAUX_SET = 0x4000,
+       STRIPPEDSUBJECT_SET = 0x8000,
 
        ALL_SET = 0xFFFF, NONE_SET = 0x0000
     };
-    ushort modifiers;
-    QString subject, from, to, replyToIdMD5, msgIdMD5, xmark, file;
+    uint modifiers;
+    QString subject, from, to, replyToIdMD5, replyToAuxIdMD5, strippedSubjectMD5, msgIdMD5, \
xmark, file;  off_t folderOffset;
     size_t msgSize;
     time_t date;
@@ -37,6 +38,10 @@ public:
            modifiers |= SUBJECT_SET;
            subject = other.subject;
        }
+       if (other.modifiers & STRIPPEDSUBJECT_SET) {
+           modifiers |= STRIPPEDSUBJECT_SET;
+           strippedSubjectMD5 = other.strippedSubjectMD5;
+       }
        if (other.modifiers & FROM_SET) {
            modifiers |= FROM_SET;
            from = other.from;
@@ -53,6 +58,11 @@ public:
            modifiers |= REPLYTO_SET;
            replyToIdMD5 = other.replyToIdMD5;
        }
+       if (other.modifiers & REPLYTOAUX_SET) {
+           modifiers |= REPLYTOAUX_SET;
+           replyToAuxIdMD5 = other.replyToAuxIdMD5;
+       }
+
        if(other.modifiers & MSGID_SET) {
            modifiers |= MSGID_SET;
            msgIdMD5 = other.msgIdMD5;
@@ -143,6 +153,8 @@ KMMsgInfo& KMMsgInfo::operator=(const KM
     kd->from = msg.fromStrip();
     kd->to = msg.toStrip();
     kd->replyToIdMD5 = msg.replyToIdMD5();
+    kd->replyToAuxIdMD5 = msg.replyToAuxIdMD5();
+    kd->strippedSubjectMD5 = msg.strippedSubjectMD5();
     kd->msgIdMD5 = msg.msgIdMD5();
     kd->xmark = msg.xmark();
     mStatus = msg.status();
@@ -161,7 +173,8 @@ KMMsgInfo& KMMsgInfo::operator=(const KM
 void KMMsgInfo::init(const QCString& aSubject, const QCString& aFrom,
                      const QCString& aTo, time_t aDate,
                     KMMsgStatus aStatus, const QCString& aXMark,
-                    const QCString& replyToId, const QCString& msgId,
+                    const QCString& replyToId, const QCString& replyToAuxId,
+                    const QCString& msgId,
                     KMMsgEncryptionState encryptionState,
                     KMMsgSignatureState signatureState,
                     KMMsgMDNSentState mdnSentState,
@@ -176,6 +189,8 @@ void KMMsgInfo::init(const QCString& aSu
     kd->from = KMMessage::stripEmailAddr( decodeRFC2047String(aFrom) );
     kd->to = KMMessage::stripEmailAddr( decodeRFC2047String(aTo) );
     kd->replyToIdMD5 = KMMessagePart::encodeBase64( replyToId );
+    kd->replyToAuxIdMD5 = KMMessagePart::encodeBase64( replyToAuxId );
+    kd->strippedSubjectMD5 = KMMessagePart::encodeBase64( KMMessage::stripOffPrefixes( \
kd->subject ) );  kd->msgIdMD5 = KMMessagePart::encodeBase64( msgId );
     kd->xmark = aXMark;
     kd->folderOffset = aFolderOffset;
@@ -192,7 +207,8 @@ void KMMsgInfo::init(const QCString& aSu
 void KMMsgInfo::init(const QCString& aSubject, const QCString& aFrom,
                      const QCString& aTo, time_t aDate,
                     KMMsgStatus aStatus, const QCString& aXMark,
-                    const QCString& replyToId, const QCString& msgId,
+                    const QCString& replyToId, const QCString& replyToAuxId,
+                    const QCString& msgId,
                     const QCString& aFileName,
                     KMMsgEncryptionState encryptionState,
                     KMMsgSignatureState signatureState,
@@ -200,8 +216,9 @@ void KMMsgInfo::init(const QCString& aSu
                     unsigned long aMsgSize)
 {
   // use the "normal" init for most stuff
-  init(aSubject, aFrom, aTo, aDate, aStatus, aXMark, replyToId, msgId,
-       encryptionState, signatureState, mdnSentState, (unsigned long)0, aMsgSize);
+  init(aSubject, aFrom, aTo, aDate, aStatus, aXMark, replyToId, replyToAuxId,
+                 msgId, encryptionState, signatureState, mdnSentState,
+                 (unsigned long)0, aMsgSize);
   kd->file = aFileName;
 }
 
@@ -257,6 +274,28 @@ QString KMMsgInfo::replyToIdMD5(void) co
     return getStringPart(MsgReplyToIdMD5Part);
 }
 
+//-----------------------------------------------------------------------------
+QString KMMsgInfo::replyToAuxIdMD5(void) const
+{
+    if (kd && kd->modifiers & KMMsgInfoPrivate::REPLYTOAUX_SET)
+       return kd->replyToAuxIdMD5;
+    return getStringPart(MsgReplyToAuxIdMD5Part);
+}
+
+//-----------------------------------------------------------------------------
+QString KMMsgInfo::strippedSubjectMD5(void) const
+{
+    if (kd && kd->modifiers & KMMsgInfoPrivate::STRIPPEDSUBJECT_SET)
+       return kd->strippedSubjectMD5;
+    return getStringPart(MsgStrippedSubjectMD5Part);
+}
+
+
+//-----------------------------------------------------------------------------
+bool KMMsgInfo::subjectIsPrefixed(void) const
+{
+    return !(strippedSubjectMD5() == KMMessagePart::encodeBase64(subject()));
+}
 
 //-----------------------------------------------------------------------------
 QString KMMsgInfo::msgIdMD5(void) const
@@ -307,6 +346,36 @@ void KMMsgInfo::setReplyToIdMD5(const QS
     kd->replyToIdMD5 = aReplyToIdMD5;
     mDirty = TRUE;
 }
+
+//-----------------------------------------------------------------------------
+void KMMsgInfo::setReplyToAuxIdMD5(const QString& aReplyToAuxIdMD5)
+{
+    if (aReplyToAuxIdMD5 == replyToAuxIdMD5())
+       return;
+
+    if (!kd)
+       kd = new KMMsgInfoPrivate;
+    kd->modifiers |= KMMsgInfoPrivate::REPLYTOAUX_SET;
+    kd->replyToAuxIdMD5 = aReplyToAuxIdMD5;
+    mDirty = TRUE;
+}
+
+
+
+//-----------------------------------------------------------------------------
+void KMMsgInfo::initStrippedSubjectMD5()
+{
+    if (kd && kd->modifiers & KMMsgInfoPrivate::STRIPPEDSUBJECT_SET)
+       return;
+    QString rawSubject = KMMessage::stripOffPrefixes(subject());
+    QString subjectMD5 = KMMessagePart::encodeBase64(rawSubject);
+    if (!kd)
+       kd = new KMMsgInfoPrivate;
+    kd->modifiers |= KMMsgInfoPrivate::STRIPPEDSUBJECT_SET;
+    kd->strippedSubjectMD5 = subjectMD5;
+    mDirty = TRUE;
+}
+
 
 
 //-----------------------------------------------------------------------------
Index: kmmsginfo.h
===================================================================
RCS file: /home/kde/kdepim/kmail/kmmsginfo.h,v
retrieving revision 1.30
diff -u -3 -p -w -r1.30 kmmsginfo.h
--- kmmsginfo.h 26 Dec 2002 10:18:15 -0000      1.30
+++ kmmsginfo.h 9 Mar 2003 08:59:12 -0000
@@ -27,7 +27,9 @@ public:
   virtual void init(const QCString& subject, const QCString& from,
                     const QCString& to, time_t date,
                    KMMsgStatus status, const QCString& xmark,
-                   const QCString& replyToId, const QCString& msgId,
+                   const QCString& replyToId,
+                   const QCString& replyToAuxId,
+                   const QCString& msgId,
                    KMMsgEncryptionState encryptionState,
                    KMMsgSignatureState signatureState,
                    KMMsgMDNSentState mdnSentState,
@@ -37,7 +39,9 @@ public:
   virtual void init(const QCString& subject, const QCString& from,
                     const QCString& to, time_t date,
                    KMMsgStatus status, const QCString& xmark,
-                   const QCString& replyToId, const QCString& msgId,
+                   const QCString& replyToId,
+                   const QCString& replyToAuxId,
+                   const QCString& msgId,
                    const QCString& fileName,
                    KMMsgEncryptionState encryptionState,
                    KMMsgSignatureState signatureState,
@@ -50,6 +54,9 @@ public:
   virtual QString toStrip(void) const;
   virtual QString xmark(void) const;
   virtual QString replyToIdMD5(void) const;
+  virtual QString replyToAuxIdMD5(void) const;
+  virtual QString strippedSubjectMD5(void) const;
+  virtual bool subjectIsPrefixed(void) const;
   virtual QString msgIdMD5(void) const;
   virtual QString fileName(void) const;
   virtual KMMsgStatus status(void) const;
@@ -67,6 +74,8 @@ public:
   virtual void setSubject(const QString&);
   virtual void setXMark(const QString&);
   virtual void setReplyToIdMD5(const QString&);
+  virtual void setReplyToAuxIdMD5(const QString&);
+  virtual void initStrippedSubjectMD5();
   virtual void setMsgIdMD5(const QString&);
   virtual void setEncryptionState( const KMMsgEncryptionState, int idx = -1 );
   virtual void setSignatureState( const KMMsgSignatureState, int idx = -1 );


_______________________________________________
KMail Developers mailing list
kmail@mail.kde.org
http://mail.kde.org/mailman/listinfo/kmail

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

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