add subject attribute, add threading fixes

This commit is contained in:
bienvenu%netscape.com 1999-06-30 19:45:32 +00:00
parent 35d805638d
commit 15edba34e6
4 changed files with 120 additions and 27 deletions

View File

@ -233,10 +233,11 @@ protected:
nsresult GetBoolPref(const char *prefName, PRBool *result);
// retrieval methods
nsMsgThread * GetThreadForReference(nsString2 &msgID);
nsMsgThread * GetThreadForSubject(const char * subject);
nsMsgThread * GetThreadForSubject(nsString2 &subject);
nsMsgThread * GetThreadForThreadId(nsMsgKey threadId);
nsMsgHdr * GetMsgHdrForReference(nsString2 &reference);
nsIMsgDBHdr * GetMsgHdrForMessageID(nsString2 &msgID);
nsIMsgDBHdr * GetMsgHdrForSubject(nsString2 &msgID);
nsMsgThread * GetThreadContainingMsgHdr(nsMsgHdr *msgHdr);
// threading interfaces
virtual nsresult CreateNewThread(nsMsgKey key, nsMsgThread **newThread);
@ -308,6 +309,7 @@ protected:
mdb_token m_threadChildrenColumnToken;
mdb_token m_threadUnreadChildrenColumnToken;
mdb_token m_messageThreadIdColumnToken;
mdb_token m_threadSubjectColumnToken;
mdb_token m_numReferencesColumnToken;
mdb_token m_messageCharSetColumnToken;
nsIMsgHeaderParser *m_HeaderParser;

View File

@ -40,6 +40,8 @@ public:
NS_IMETHOD GetThreadKey(nsMsgKey *result);
NS_IMETHOD GetFlags(PRUint32 *result);
NS_IMETHOD SetFlags(PRUint32 flags);
NS_IMETHOD SetSubject(char *subject);
NS_IMETHOD GetSubject(char **result);
NS_IMETHOD GetNumChildren(PRUint32 *result);
NS_IMETHOD GetNumUnreadChildren (PRUint32 *result);
NS_IMETHOD AddChild(nsIMsgDBHdr *child, PRBool threadInThread);
@ -47,7 +49,7 @@ public:
NS_IMETHOD GetChild(nsMsgKey msgKey, nsIMsgDBHdr **result);
NS_IMETHOD GetChildHdrAt(PRInt32 index, nsIMsgDBHdr **result);
NS_IMETHOD RemoveChildAt(PRInt32 index);
NS_IMETHOD RemoveChild(nsMsgKey msgKey);
NS_IMETHOD RemoveChildHdr(nsIMsgDBHdr *child);
NS_IMETHOD MarkChildRead(PRBool bRead);
NS_IMETHOD EnumerateMessages(nsMsgKey parent, nsIEnumerator* *result);
@ -63,6 +65,7 @@ protected:
virtual nsresult InitCachedValues();
nsresult ChangeChildCount(PRInt32 delta);
nsresult ChangeUnreadChildCount(PRInt32 delta);
nsresult RemoveChild(nsMsgKey msgKey);
nsMsgKey m_threadKey;
PRUint32 m_numChildren;
@ -72,8 +75,6 @@ protected:
nsIMdbRow *m_metaRow;
PRBool m_cachedValuesInitialized;
};
#endif

View File

@ -312,6 +312,7 @@ nsMsgDatabase::nsMsgDatabase()
m_threadIdColumnToken(0),
m_threadChildrenColumnToken(0),
m_threadUnreadChildrenColumnToken(0),
m_threadSubjectColumnToken(0),
m_messageThreadIdColumnToken(0),
m_numReferencesColumnToken(0),
m_messageCharSetColumnToken(0),
@ -738,6 +739,7 @@ const char *kThreadFlagsColumnName = "threadFlags";
const char *kThreadIdColumnName = "threadId";
const char *kThreadChildrenColumnName = "children";
const char *kThreadUnreadChildrenColumnName = "unreadChildren";
const char *kThreadSubjectColumnName = "threadSubject";
const char *kMessageCharSetColumnName = "msgCharSet";
struct mdbOid gAllMsgHdrsTableOID;
@ -829,6 +831,7 @@ nsresult nsMsgDatabase::InitMDBInfo()
GetStore()->StringToToken(GetEnv(), kThreadFlagsColumnName, &m_threadFlagsColumnToken);
GetStore()->StringToToken(GetEnv(), kThreadChildrenColumnName, &m_threadChildrenColumnToken);
GetStore()->StringToToken(GetEnv(), kThreadUnreadChildrenColumnName, &m_threadUnreadChildrenColumnToken);
GetStore()->StringToToken(GetEnv(), kThreadSubjectColumnName, &m_threadSubjectColumnToken);
GetStore()->StringToToken(GetEnv(), kNumReferencesColumnName, &m_numReferencesColumnToken);
GetStore()->StringToToken(GetEnv(), kMessageCharSetColumnName, &m_messageCharSetColumnToken);
err = GetStore()->StringToToken(GetEnv(), kMsgHdrsTableKind, &m_hdrTableKindToken);
@ -998,13 +1001,7 @@ nsresult nsMsgDatabase::RemoveHeaderFromDB(nsMsgHdr *msgHdr)
nsCOMPtr <nsIMsgThread> thread ;
ret = GetThreadContainingMsgHdr(msgHdr, getter_AddRefs(thread));
if (NS_SUCCEEDED(ret))
{
nsMsgKey msgKey;
ret = msgHdr->GetMessageKey(&msgKey);
if (NS_SUCCEEDED(ret))
ret = thread->RemoveChild(msgKey);
}
ret = thread->RemoveChildHdr(msgHdr);
else
NS_ASSERTION(PR_FALSE, "couldn't find thread containing deleted message");
// even if we couldn't find the thread,we should try to remove the header.
@ -1762,7 +1759,8 @@ NS_IMETHODIMP nsMsgDBThreadEnumerator::Next(void)
nsresult rv;
nsIMdbTable *table = nsnull;
do {
while (PR_TRUE)
{
NS_IF_RELEASE(mResultThread);
mResultThread = nsnull;
rv = mTableCursor->NextTable(mDB->GetEnv(), &table);
@ -1782,8 +1780,19 @@ NS_IMETHODIMP nsMsgDBThreadEnumerator::Next(void)
mResultThread = new nsMsgThread(mDB, table);
if(mResultThread)
{
PRUint32 numChildren = 0;
NS_ADDREF(mResultThread);
} while (mFilter && mFilter(mResultThread, mClosure) != NS_OK);
mResultThread->GetNumChildren(&numChildren);
// we've got empty thread; don't tell caller about it.
if (numChildren == 0)
continue;
}
if (mFilter && mFilter(mResultThread, mClosure) != NS_OK)
continue;
else
break;
}
return rv;
}
@ -1900,13 +1909,19 @@ NS_IMETHODIMP nsMsgDatabase::CreateNewHdr(nsMsgKey key, nsIMsgDBHdr **pnewHdr)
NS_IMETHODIMP nsMsgDatabase::AddNewHdrToDB(nsIMsgDBHdr *newHdr, PRBool notify)
{
nsMsgHdr* hdr = NS_STATIC_CAST(nsMsgHdr*, newHdr); // closed system, cast ok
nsresult err = m_mdbAllMsgHeadersTable->AddRow(GetEnv(), hdr->GetMDBRow());
PRBool newThread;
nsresult err = ThreadNewHdr(hdr, newThread);
// we thread header before we add it to the all headers table
// so that subject threading will work (otherwise, when we try
// to find the first header with the same subject, we get the
// new header!
if (NS_SUCCEEDED(err))
{
nsMsgKey key;
PRUint32 flags;
newHdr->GetMessageKey(&key);
newHdr->GetMessageKey(&key);
newHdr->GetFlags(&flags);
if (flags & MSG_FLAG_NEW)
{
@ -1921,9 +1936,7 @@ NS_IMETHODIMP nsMsgDatabase::AddNewHdrToDB(nsIMsgDBHdr *newHdr, PRBool notify)
if (! (flags & MSG_FLAG_READ))
m_dbFolderInfo->ChangeNumNewMessages(1);
}
PRBool newThread;
err = ThreadNewHdr(hdr, newThread);
err = m_mdbAllMsgHeadersTable->AddRow(GetEnv(), hdr->GetMDBRow());
if (notify)
{
NotifyKeyAddedAll(key, flags, NULL);
@ -2210,10 +2223,25 @@ nsMsgThread *nsMsgDatabase::GetThreadForReference(nsString2 &msgID)
return thread;
}
nsMsgThread * nsMsgDatabase::GetThreadForSubject(const char * subject)
nsMsgThread * nsMsgDatabase::GetThreadForSubject(nsString2 &subject)
{
// NS_ASSERTION(PR_FALSE, "not implemented yet.");
return nsnull;
nsMsgThread *thread = NULL;
// just find some msg hdr with this subject and use it's thread
// as the containng thread,
nsIMsgDBHdr *msgHdr = GetMsgHdrForSubject(subject);
if (msgHdr != NULL)
{
nsMsgKey threadId;
if (NS_SUCCEEDED(msgHdr->GetThreadId(&threadId)))
{
// find thread header for header whose message id we matched.
thread = GetThreadForThreadId(threadId);
}
msgHdr->Release();
}
return thread;
}
nsresult nsMsgDatabase::ThreadNewHdr(nsMsgHdr* newHdr, PRBool &newThread)
@ -2260,7 +2288,7 @@ nsresult nsMsgDatabase::ThreadNewHdr(nsMsgHdr* newHdr, PRBool &newThread)
newHdr->GetSubject(subject);
if ((ThreadBySubjectWithoutRe() || (newHdrFlags & MSG_FLAG_HAS_RE)) && (!thread))
{
thread = getter_AddRefs(GetThreadForSubject(subject.GetBuffer()));
thread = getter_AddRefs(GetThreadForSubject(subject));
if(thread)
{
thread->GetThreadKey(&threadId);
@ -2326,6 +2354,34 @@ nsIMsgDBHdr *nsMsgDatabase::GetMsgHdrForMessageID(nsString2 &msgID)
return msgHdr;
}
nsIMsgDBHdr *nsMsgDatabase::GetMsgHdrForSubject(nsString2 &subject)
{
nsIMsgDBHdr *msgHdr = nsnull;
nsresult rv = NS_OK;
mdbYarn subjectYarn;
subjectYarn.mYarn_Buf = (void*)subject.GetBuffer();
subjectYarn.mYarn_Fill = PL_strlen(subject.GetBuffer());
subjectYarn.mYarn_Form = 0;
subjectYarn.mYarn_Size = subjectYarn.mYarn_Fill;
nsIMdbRow *hdrRow;
mdbOid outRowId;
mdb_err result = GetStore()->FindRow(GetEnv(), m_hdrRowScopeToken,
m_subjectColumnToken, &subjectYarn, &outRowId,
&hdrRow);
if (NS_SUCCEEDED(result) && hdrRow)
{
//Get key from row
mdbOid outOid;
nsMsgKey key=0;
if (hdrRow->GetOid(GetEnv(), &outOid) == NS_OK)
key = outOid.mOid_Id;
rv = CreateMsgHdr(hdrRow, key, &msgHdr);
}
return msgHdr;
}
NS_IMETHODIMP nsMsgDatabase::GetThreadContainingMsgHdr(nsIMsgDBHdr *msgHdr, nsIMsgThread **result)
{
nsresult ret = NS_OK;
@ -2338,7 +2394,7 @@ NS_IMETHODIMP nsMsgDatabase::GetThreadContainingMsgHdr(nsIMsgDBHdr *msgHdr, nsIM
if (threadId != nsMsgKey_None)
*result = GetThreadForThreadId(threadId);
return ret;
return (*result) ? NS_OK : NS_ERROR_FAILURE;
}

View File

@ -130,6 +130,17 @@ NS_IMETHODIMP nsMsgThread::SetFlags(PRUint32 flags)
return ret;
}
NS_IMETHODIMP nsMsgThread::SetSubject(char *subject)
{
return NS_OK;
}
NS_IMETHODIMP nsMsgThread::GetSubject(char **result)
{
if (!result)
return NS_ERROR_NULL_POINTER;
return NS_OK;
}
NS_IMETHODIMP nsMsgThread::GetNumChildren(PRUint32 *result)
{
@ -249,7 +260,7 @@ NS_IMETHODIMP nsMsgThread::RemoveChildAt(PRInt32 aIndex)
}
NS_IMETHODIMP nsMsgThread::RemoveChild(nsMsgKey msgKey)
nsresult nsMsgThread::RemoveChild(nsMsgKey msgKey)
{
nsresult ret = NS_OK;
mdbOid rowObjectId;
@ -259,6 +270,22 @@ NS_IMETHODIMP nsMsgThread::RemoveChild(nsMsgKey msgKey)
return ret;
}
NS_IMETHODIMP nsMsgThread::RemoveChildHdr(nsIMsgDBHdr *child)
{
PRUint32 flags;
nsMsgKey key;
if (!child)
return NS_ERROR_NULL_POINTER;
child->GetFlags(&flags);
child->GetMessageKey(&key);
if (!(flags & MSG_FLAG_READ))
ChangeUnreadChildCount(-1);
ChangeChildCount(-1);
return RemoveChild(key);
}
NS_IMETHODIMP nsMsgThread::MarkChildRead(PRBool bRead)
{
@ -277,12 +304,15 @@ PRBool nsMsgThread::TryReferenceThreading(nsIMsgDBHdr *newHeader)
for (int32 refIndex = newHeader->GetNumReferences() - 1; !done && refIndex >= 0; refIndex--)
{
nsCOMPtr <nsIMsgDBHdr> refHdr;
refHdr = messageDB->GetNeoMessageHdrForHashMessageID(newHeader->GetReferenceId(refIndex));
nsString2 referenceStr;
newHeader->GetStringReference(refIndex, referenceStr);
refHdr = m_mdbDB->GetMsgHdrForMessageID(referenceStr);
if (refHdr)
{
// position iterator at child pos.
childIterator.reset();
while (TRUE)
while (PR_TRUE)
{
MessageKey curMsgId = childIterator.currentID();
if (curMsgId == 0)
@ -391,6 +421,8 @@ nsMsgThreadEnumerator::nsMsgThreadEnumerator(nsMsgThread *thread, nsMsgKey start
mResultHdr = nsnull;
}
else
NS_ASSERTION(PR_FALSE, "couldn't get child from thread");
mChildIndex = 1;
}
NS_ADDREF(thread);
@ -405,12 +437,14 @@ NS_IMPL_ISUPPORTS(nsMsgThreadEnumerator, nsIEnumerator::GetIID())
NS_IMETHODIMP nsMsgThreadEnumerator::First(void)
{
//nsresult rv = NS_OK;
nsresult rv = NS_OK;
if (!mThread)
return NS_ERROR_NULL_POINTER;
return Next();
rv = Next();
NS_ASSERTION(mCurKey != nsMsgKey_None || NS_SUCCEEDED(rv), "first failed, can't have that");
return rv;
}
NS_IMETHODIMP nsMsgThreadEnumerator::Next(void)