more work on db view NOT PART OF BUILD

This commit is contained in:
bienvenu%netscape.com 2001-02-08 17:46:54 +00:00
parent 1f195e3bf5
commit 5cf8693a6e
5 changed files with 244 additions and 12 deletions

View File

@ -28,6 +28,7 @@ interface nsIMsgDatabase;
typedef long nsMsgViewSortOrderValue;
typedef long nsMsgViewSortTypeValue;
typedef long nsMsgDBViewTypeValue;
typedef long nsMsgViewNotificationCodeValue;
[scriptable, uuid(682a18be-fd18-11d4-a5be-0060b0fc04b7)]
interface nsMsgViewSortOrder
@ -53,6 +54,60 @@ interface nsMsgViewSortType
const nsMsgViewSortTypeValue byRecipient = 0x1c;
};
[scriptable, uuid(255d1c1e-fde7-11d4-a5be-0060b0fc04b7)]
interface nsMsgViewNotificationCode
{
const nsMsgViewNotificationCodeValue none = 0;
/* No change; this call is just being used
to potentially nest other sets of calls
inside it. The "where" and "num" parameters
are unused. */
const nsMsgViewNotificationCodeValue insertOrDelete = 1;
/* Some lines have been inserted or deleted.
The "where" parameter will indicate
the first line that has been added or
removed; the "num" parameter will indicate
how many lines, and will be positive on
an insertion and negative on a deletion. */
const nsMsgViewNotificationCodeValue changed = 2;
/* Some lines have had their contents changed
(e.g., messages have been marked read
or something.) "where" indicates the
first line with a change; "num" indicates
how many chaged. */
const nsMsgViewNotificationCodeValue scramble = 3;
/* Everything changed. Probably means we
resorted the folder. We are still working
with the same set of items, or at least
have some overlap, but all the indices are
invalid. The "where" and "num" parameters
are unused. */
const nsMsgViewNotificationCodeValue all = 4; /* Everything changed. We're now not
displaying anything like what we were; we
probably opened a new folder or something.
The FE needs to forget anything it ever knew
about what was being displayed, and start
over. The "where" and "num" parameters are
unused. */
const nsMsgViewNotificationCodeValue totalContentChanged = 5;
/* Introduced for the address book to support
virtual list views. The total number of
entries on the LDAP directory has changed
and the FE must update its scrollbar. The
"num" parameter contains the total number of
entries on the LDAP server. */
const nsMsgViewNotificationCodeValue newTopIndex = 6;
/* Introduced for the address book to support
virtual list views. The virtual list view
cache data has changed and the FE view may
be out of date. The view should be updated
so that the first/top index in the view is
the index in the "where" parameter. The
scrollbar should be updated to match the new
position. */
};
[scriptable, uuid(4063bcf8-fd19-11d4-a5be-0060b0fc04b7)]
interface nsMsgDBViewType
{

View File

@ -23,6 +23,8 @@
#include "msgCore.h"
#include "nsMsgDBView.h"
#include "nsISupports.h"
#include "nsIMsgHdr.h"
/* Implementation file */
NS_IMPL_ISUPPORTS1(nsMsgDBView, nsIMsgDBView)
@ -30,6 +32,7 @@ NS_IMPL_ISUPPORTS1(nsMsgDBView, nsIMsgDBView)
nsMsgDBView::nsMsgDBView()
{
NS_INIT_ISUPPORTS();
m_viewType = nsMsgDBViewType::anyView;
/* member initializers and constructor code */
m_sortValid = PR_TRUE;
m_sortOrder = nsMsgViewSortOrder::none;
@ -41,7 +44,8 @@ nsMsgDBView::~nsMsgDBView()
/* destructor code */
}
NS_IMETHODIMP nsMsgDBView::Open(nsIMsgDatabase *msgDB, nsMsgViewSortType *viewType, PRInt32 *count)
/* void open (in nsIMsgDatabase msgDB, in nsMsgViewSortType viewType); */
NS_IMETHODIMP nsMsgDBView::Open(nsIMsgDatabase *msgDB, nsMsgViewSortType *viewType, PRInt32 *pCount)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
@ -66,3 +70,115 @@ NS_IMETHODIMP nsMsgDBView::Sort(nsMsgViewSortType *sortType, nsMsgViewSortOrder
return NS_ERROR_NOT_IMPLEMENTED;
}
nsresult nsMsgDBView::ExpandAll()
{
for (PRInt32 i = GetSize() - 1; i >= 0; i--)
{
PRUint32 numExpanded;
PRUint32 flags = m_flags[i];
if (flags & MSG_FLAG_ELIDED)
ExpandByIndex(i, &numExpanded);
}
return NS_OK;
}
nsresult nsMsgDBView::ExpandByIndex(nsMsgViewIndex index, PRUint32 *pNumExpanded)
{
int numListed;
char flags = m_flags[index];
nsMsgKey firstIdInThread, startMsg = nsMsgKey_None;
nsresult rv;
nsMsgViewIndex firstInsertIndex = index + 1;
nsMsgViewIndex insertIndex = firstInsertIndex;
uint32 numExpanded = 0;
nsMsgKeyArray tempIDArray;
nsByteArray tempFlagArray;
nsByteArray tempLevelArray;
nsByteArray unreadLevelArray;
NS_ASSERTION(flags & MSG_FLAG_ELIDED, "can't expand an already expanded thread");
flags &= ~MSG_FLAG_ELIDED;
if ((int) index > m_keys.GetSize())
return NS_MSG_MESSAGE_NOT_FOUND;
firstIdInThread = m_keys[index];
nsCOMPtr <nsIMsgDBHdr> msgHdr;
m_db->GetMsgHdrForKey(firstIdInThread, getter_AddRefs(msgHdr));
if (msgHdr == nsnull)
{
NS_ASSERTION(PR_FALSE, "couldn't find message to expand");
return NS_MSG_MESSAGE_NOT_FOUND;
}
m_flags[index] = flags;
NoteChange(index, 1, nsMsgViewNotificationCode::changed);
do
{
const int listChunk = 200;
nsMsgKey listIDs[listChunk];
char listFlags[listChunk];
char listLevels[listChunk];
#ifdef ON_BRANCH_YET
if (m_viewFlags & kUnreadOnly)
{
if (flags & MSG_FLAG_READ)
unreadLevelArray.Add(0); // keep top level hdr in thread, even though read.
nsMsgKey threadId;
msgHdr->GetThreadId(&threadId);
rv = m_db->ListUnreadIdsInThread(threadId, &startMsg, unreadLevelArray,
listChunk, listIDs, listFlags, listLevels, &numListed);
}
else
rv = m_db->ListIdsInThread(msgHdr, &startMsg, listChunk,
listIDs, listFlags, listLevels, &numListed);
// Don't add thread to view, it's already in.
for (int i = 0; i < numListed; i++)
{
if (listIDs[i] != firstIdInThread)
{
tempIDArray.Add(listIDs[i]);
tempFlagArray.Add(listFlags[i]);
tempLevelArray.Add(listLevels[i]);
insertIndex++;
}
}
#endif
if (numListed < listChunk || startMsg == nsMsgKey_None)
break;
}
while (NS_SUCCEEDED(rv));
numExpanded = (insertIndex - firstInsertIndex);
NoteStartChange(firstInsertIndex, numExpanded, nsMsgViewNotificationCode::insertOrDelete);
m_keys.InsertAt(firstInsertIndex, &tempIDArray);
#ifdef ON_BRANCH_YET
m_flags.InsertAt(firstInsertIndex, &tempFlagArray);
m_levels.InsertAt(firstInsertIndex, &tempLevelArray);
#endif
NoteEndChange(firstInsertIndex, numExpanded, nsMsgViewNotificationCode::insertOrDelete);
if (pNumExpanded != nsnull)
*pNumExpanded = numExpanded;
return rv;
}
void nsMsgDBView::EnableChangeUpdates()
{
}
void nsMsgDBView::DisableChangeUpdates()
{
}
void nsMsgDBView::NoteChange(nsMsgViewIndex firstlineChanged, PRInt32 numChanged,
nsMsgViewNotificationCodeValue changeType)
{
}
void nsMsgDBView::NoteStartChange(nsMsgViewIndex firstlineChanged, PRInt32 numChanged,
nsMsgViewNotificationCodeValue changeType)
{
}
void nsMsgDBView::NoteEndChange(nsMsgViewIndex firstlineChanged, PRInt32 numChanged,
nsMsgViewNotificationCodeValue changeType)
{
}

View File

@ -41,13 +41,31 @@ public:
NS_DECL_NSIMSGDBVIEW
protected:
nsresult ExpandByIndex(nsMsgViewIndex index, PRUint32 *pNumExpanded);
nsresult ExpandAll();
PRInt32 GetSize(void) {return(m_keys.GetSize());}
// notification api's
void EnableChangeUpdates();
void DisableChangeUpdates();
void NoteChange(nsMsgViewIndex firstlineChanged, PRInt32 numChanged,
nsMsgViewNotificationCodeValue changeType);
void NoteStartChange(nsMsgViewIndex firstlineChanged, PRInt32 numChanged,
nsMsgViewNotificationCodeValue changeType);
void NoteEndChange(nsMsgViewIndex firstlineChanged, PRInt32 numChanged,
nsMsgViewNotificationCodeValue changeType);
nsMsgKeyArray m_keys;
nsUInt32Array m_flags;
nsByteArray m_levels;
nsCOMPtr <nsIMsgDatabase> m_db;
PRBool m_sortValid;
nsMsgViewSortTypeValue m_sortType;
nsMsgViewSortOrderValue m_sortOrder;
nsMsgDBViewTypeValue m_viewType;
};
#endif

View File

@ -70,7 +70,7 @@ NS_IMETHODIMP nsMsgThreadedDBView::Init(PRInt32 *pCount)
sortType = m_sortType;
nsresult getSortrv = NS_OK; // ### TODO m_db->GetSortInfo(&sortType, &sortOrder);
#ifdef HAVE_BRANCH_YET
// list all the ids into m_idArray.
nsMsgKey startMsg = 0;
do
@ -96,7 +96,7 @@ NS_IMETHODIMP nsMsgThreadedDBView::Init(PRInt32 *pCount)
{
InitSort(sortType, sortOrder);
}
#endif
return rv;
#else
return NS_ERROR_NOT_IMPLEMENTED;
@ -145,6 +145,7 @@ nsresult nsMsgThreadedDBView::ListThreadIds(nsMsgKey *startMsg, PRBool unreadOnl
PRBool hasMore = PR_FALSE;
#ifdef HAVE_BRANCH_YET
while (NS_SUCCEEDED(rv = m_threadEnumerator->HasMoreElements(&hasMore)) && (hasMore == PR_TRUE))
{
nsCOMPtr <nsISupports> supports;
@ -157,8 +158,10 @@ nsresult nsMsgThreadedDBView::ListThreadIds(nsMsgKey *startMsg, PRBool unreadOnl
for (PRInt32 i = 0; i < numToList && threadHdr != nsnull; i++)
{
nsCOMPtr <nsIMsgDBHdr> msgHdr;
PRInt32 numChildren;
PRUint32 numChildren;
threadHdr->GetNumChildren(&numChildren);
PRUint32 threadFlags;
threadHdr->GetFlags(&threadFlags);
if (numChildren != 0) // not empty thread
{
if (pTotalHeaders)
@ -167,9 +170,6 @@ nsresult nsMsgThreadedDBView::ListThreadIds(nsMsgKey *startMsg, PRBool unreadOnl
// msgHdr = threadHdr->GetFirstUnreadChild(this);
// else
rv = threadHdr->GetChildAt(0, getter_AddRefs(msgHdr));
PRUint32 threadFlags;
threadHdr->GetFlags(&threadFlags);
if (msgHdr != NULL && WantsThisThread(threadHdr))
{
nsMsgKey msgKey;
@ -180,11 +180,11 @@ nsresult nsMsgThreadedDBView::ListThreadIds(nsMsgKey *startMsg, PRBool unreadOnl
// handle thread flags vs. message flags, if we do decide
// to make them different.
msgHdr->OrFlags(threadFlags & (kWatched | kIgnored));
PRBool isRead = FALSE;
PRBool isRead = PR_FALSE;
// make sure DB agrees with newsrc, if we're news.
IsRead(msgKey, &isRead);
MarkHdrRead(msgHdr, isRead, NULL);
MarkHdrRead(msgHdr, isRead, nsnull);
// try adding in kIsThread flag for unreadonly view.
pFlags[numListed] = msgHdr->m_flags | kIsThread | threadFlags;
if (NS_SUCCEEDED(GetThreadCount(threadHdr, &threadCount)) && threadCount > 1)
@ -193,7 +193,7 @@ nsresult nsMsgThreadedDBView::ListThreadIds(nsMsgKey *startMsg, PRBool unreadOnl
numListed++;
}
}
else if (threadsRemoved < 10 && !(threadHdr->GetFlags() & (kWatched | kIgnored)))
else if (threadsRemoved < 10 && !(threadFlags & (MSG_FLAG_WATCHED | MSG_FLAG_IGNORED)))
{
// ### remove thread.
threadsRemoved++; // don't want to remove all empty threads first time
@ -204,7 +204,7 @@ nsresult nsMsgThreadedDBView::ListThreadIds(nsMsgKey *startMsg, PRBool unreadOnl
}
threadHdr = nextThreadHdr;
}
}
}
if (threadHdr != NULL)
{
@ -215,10 +215,51 @@ nsresult nsMsgThreadedDBView::ListThreadIds(nsMsgKey *startMsg, PRBool unreadOnl
*startMsg = nsMsgKey_None;
m_threadEnumerator = nsnull;
}
*pNumListed = numListed;
#endif // HAVE_BRANCH_YET
*pNumListed = numListed;
return rv;
#else
return NS_ERROR_NOT_IMPLEMENTED;
#endif
}
nsresult nsMsgThreadedDBView::ExpandAll()
{
nsresult rv = NS_OK;
// go through expanding in place
for (PRUint32 i = 0; i < m_keys.GetSize(); i++)
{
PRUint32 numExpanded;
PRUint32 flags = m_flags[i];
#ifdef HAVE_BRANCH_YET
if (flags & kHasChildren && (flags & MSG_FLAG_ELIDED))
{
rv = ExpandByIndex(i, &numExpanded);
i += numExpanded;
NS_ENSURE_SUCCESS(rv, rv);
}
#endif
}
return rv;
}
nsresult nsMsgThreadedDBView::InitSort(nsMsgViewSortType sortType, nsMsgViewSortOrder sortOrder)
{
#ifdef HAVE_BRANCH_YET
if (sortType == nsMsgViewSortType::byThread)
{
SortInternal(nsMsgViewSortType::byId, sortOrder); // sort top level threads by id.
m_sortType = nsMsgViewSortType::byThread;
m_db->SetSortInfo(m_sortType, sortOrder);
}
if ((m_viewFlags & kUnreadOnly) && m_sortType == nsMsgViewSortType::byThread)
ExpandAll();
m_sortValid = PR_TRUE;
Sort(sortType, sortOrder);
if (sortType != SortByThread) // forget prev view, since it has everything expanded.
ClearPrevIdArray();
#endif
return NS_OK;
}

View File

@ -43,6 +43,8 @@ public:
protected:
nsresult ListThreadIds(nsMsgKey *startMsg, PRBool unreadOnly, nsMsgKey *pOutput, PRInt32 *pFlags, char *pLevels,
PRInt32 numToList, PRInt32 *pNumListed, PRInt32 *pTotalHeaders);
nsresult InitSort(nsMsgViewSortType sortType, nsMsgViewSortOrder sortOrder);
nsresult ExpandAll();
// these are used to save off the previous view so that bopping back and forth
// between two views is quick (e.g., threaded and flat sorted by date).
PRBool m_havePrevView;