fix 262319, new msg arriving in thread doesn't resort, when sorted by date, r=standard8, sr=neil
This commit is contained in:
Родитель
abe8f65901
Коммит
1ce2bd7835
|
@ -3225,7 +3225,7 @@ struct IdDWord
|
||||||
nsMsgKey id;
|
nsMsgKey id;
|
||||||
PRUint32 bits;
|
PRUint32 bits;
|
||||||
PRUint32 dword;
|
PRUint32 dword;
|
||||||
nsISupports* folder;
|
nsIMsgFolder* folder;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct IdKey : public IdDWord
|
struct IdKey : public IdDWord
|
||||||
|
@ -3959,8 +3959,7 @@ NS_IMETHODIMP nsMsgDBView::Sort(nsMsgViewSortTypeValue sortType, nsMsgViewSortOr
|
||||||
|
|
||||||
if (folders)
|
if (folders)
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsISupports> curFolder;
|
nsCOMPtr<nsIMsgFolder> curFolder = do_QueryElementAt(folders, numSoFar);
|
||||||
folders->GetElementAt(numSoFar, getter_AddRefs(curFolder));
|
|
||||||
info->folder = curFolder;
|
info->folder = curFolder;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -4487,61 +4486,122 @@ nsresult nsMsgDBView::GetThreadContainingIndex(nsMsgViewIndex index, nsIMsgThrea
|
||||||
return GetThreadContainingMsgHdr(msgHdr, resultThread);
|
return GetThreadContainingMsgHdr(msgHdr, resultThread);
|
||||||
}
|
}
|
||||||
|
|
||||||
nsMsgViewIndex nsMsgDBView::GetIndexForThread(nsIMsgDBHdr *hdr)
|
nsMsgViewIndex
|
||||||
|
nsMsgDBView::GetIndexForThread(nsIMsgDBHdr *msgHdr)
|
||||||
{
|
{
|
||||||
nsMsgViewIndex retIndex = nsMsgViewIndex_None;
|
// Take advantage of the fact that we're already sorted
|
||||||
nsMsgViewIndex prevInsertIndex = nsMsgViewIndex_None;
|
// and find the insert index via a binary search, though expanded threads
|
||||||
nsMsgKey insertKey;
|
// make that tricky.
|
||||||
hdr->GetMessageKey(&insertKey);
|
|
||||||
|
|
||||||
if (m_sortOrder == nsMsgViewSortOrder::ascending)
|
nsMsgViewIndex highIndex = m_keys.Length();
|
||||||
|
nsMsgViewIndex lowIndex = 0;
|
||||||
|
IdKeyPtr EntryInfo1, EntryInfo2;
|
||||||
|
EntryInfo1.key = nsnull;
|
||||||
|
EntryInfo2.key = nsnull;
|
||||||
|
|
||||||
|
nsresult rv;
|
||||||
|
PRUint16 maxLen;
|
||||||
|
eFieldType fieldType;
|
||||||
|
rv = GetFieldTypeAndLenForSort(m_sortType, &maxLen, &fieldType);
|
||||||
|
const void *pValue1 = &EntryInfo1, *pValue2 = &EntryInfo2;
|
||||||
|
|
||||||
|
int retStatus = 0;
|
||||||
|
msgHdr->GetMessageKey(&EntryInfo1.id);
|
||||||
|
msgHdr->GetFolder(&EntryInfo1.folder);
|
||||||
|
EntryInfo1.folder->Release();
|
||||||
|
//check if a custom column handler exists. If it does then grab it and pass it in
|
||||||
|
//to either GetCollationKey or GetLongField
|
||||||
|
nsIMsgCustomColumnHandler* colHandler = GetCurColumnHandlerFromDBInfo();
|
||||||
|
|
||||||
|
viewSortInfo comparisonContext;
|
||||||
|
comparisonContext.view = this;
|
||||||
|
comparisonContext.isSecondarySort = PR_FALSE;
|
||||||
|
comparisonContext.ascendingSort = (m_sortOrder == nsMsgViewSortOrder::ascending);
|
||||||
|
nsCOMPtr <nsIMsgDatabase> hdrDB;
|
||||||
|
EntryInfo1.folder->GetMsgDatabase(nsnull, getter_AddRefs(hdrDB));
|
||||||
|
comparisonContext.db = hdrDB.get();
|
||||||
|
switch (fieldType)
|
||||||
{
|
{
|
||||||
// loop backwards looking for top level message with id > id of header we're inserting
|
case kCollationKey:
|
||||||
// and put new header before found header, or at end.
|
rv = GetCollationKey(msgHdr, m_sortType, &EntryInfo1.key, &EntryInfo1.dword, colHandler);
|
||||||
for (PRInt32 i = GetSize() - 1; i >= 0; i--)
|
NS_ASSERTION(NS_SUCCEEDED(rv),"failed to create collation key");
|
||||||
{
|
break;
|
||||||
if (m_levels[i] == 0)
|
case kU32:
|
||||||
{
|
if (m_sortType == nsMsgViewSortType::byId)
|
||||||
if (insertKey < m_keys[i])
|
EntryInfo1.dword = EntryInfo1.id;
|
||||||
prevInsertIndex = i;
|
else
|
||||||
else if (insertKey >= m_keys[i])
|
GetLongField(msgHdr, m_sortType, &EntryInfo1.dword, colHandler);
|
||||||
{
|
break;
|
||||||
retIndex = (prevInsertIndex == nsMsgViewIndex_None) ? nsMsgViewIndex_None : i + 1;
|
default:
|
||||||
if (prevInsertIndex == nsMsgViewIndex_None)
|
return highIndex;
|
||||||
{
|
}
|
||||||
retIndex = nsMsgViewIndex_None;
|
while (highIndex > lowIndex)
|
||||||
}
|
{
|
||||||
else
|
nsMsgViewIndex tryIndex = (lowIndex + highIndex) / 2;
|
||||||
{
|
// need to adjust tryIndex if it's not a thread.
|
||||||
for (retIndex = i + 1; retIndex < (nsMsgViewIndex)GetSize(); retIndex++)
|
while (m_levels[tryIndex] && tryIndex)
|
||||||
{
|
tryIndex--;
|
||||||
if (m_levels[retIndex] == 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
if (tryIndex < lowIndex)
|
||||||
|
{
|
||||||
|
NS_ERROR("try index shouldn't be less than low index");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
EntryInfo2.id = m_keys[tryIndex];
|
||||||
|
GetFolderForViewIndex(tryIndex, &EntryInfo2.folder);
|
||||||
|
EntryInfo2.folder->Release();
|
||||||
|
|
||||||
|
nsCOMPtr <nsIMsgDBHdr> tryHdr;
|
||||||
|
nsCOMPtr <nsIMsgDatabase> db;
|
||||||
|
// ### this should get the db from the folder...
|
||||||
|
GetDBForViewIndex(tryIndex, getter_AddRefs(db));
|
||||||
|
if (db)
|
||||||
|
rv = db->GetMsgHdrForKey(EntryInfo2.id, getter_AddRefs(tryHdr));
|
||||||
|
if (!tryHdr)
|
||||||
|
break;
|
||||||
|
if (tryHdr == msgHdr)
|
||||||
|
{
|
||||||
|
NS_WARNING("didn't expect header to already be in view");
|
||||||
|
highIndex = tryIndex;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (fieldType == kCollationKey)
|
||||||
|
{
|
||||||
|
PR_FREEIF(EntryInfo2.key);
|
||||||
|
rv = GetCollationKey(tryHdr, m_sortType, &EntryInfo2.key, &EntryInfo2.dword, colHandler);
|
||||||
|
NS_ASSERTION(NS_SUCCEEDED(rv),"failed to create collation key");
|
||||||
|
retStatus = FnSortIdKeyPtr(&pValue1, &pValue2, &comparisonContext);
|
||||||
|
}
|
||||||
|
else if (fieldType == kU32)
|
||||||
|
{
|
||||||
|
if (m_sortType == nsMsgViewSortType::byId)
|
||||||
|
EntryInfo2.dword = EntryInfo2.id;
|
||||||
|
else
|
||||||
|
GetLongField(tryHdr, m_sortType, &EntryInfo2.dword, colHandler);
|
||||||
|
retStatus = FnSortIdDWord(&pValue1, &pValue2, &comparisonContext);
|
||||||
|
}
|
||||||
|
if (retStatus == 0)
|
||||||
|
{
|
||||||
|
highIndex = tryIndex;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (retStatus < 0)
|
||||||
|
{
|
||||||
|
highIndex = tryIndex;
|
||||||
|
// we already made sure tryIndex was at a thread at the top of the loop.
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lowIndex = tryIndex + 1;
|
||||||
|
while (lowIndex < GetSize() && m_levels[lowIndex])
|
||||||
|
lowIndex++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
PR_Free(EntryInfo1.key);
|
||||||
// loop forwards looking for top level message with id < id of header we're inserting and put
|
PR_Free(EntryInfo2.key);
|
||||||
// new header before found header, or at beginning.
|
return highIndex;
|
||||||
for (PRInt32 i = 0; i < GetSize(); i++)
|
|
||||||
{
|
|
||||||
if (!m_levels[i])
|
|
||||||
{
|
|
||||||
if (insertKey > m_keys[i])
|
|
||||||
{
|
|
||||||
retIndex = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return retIndex;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nsMsgViewIndex nsMsgDBView::GetInsertIndexHelper(nsIMsgDBHdr *msgHdr, nsTArray<nsMsgKey> &keys,
|
nsMsgViewIndex nsMsgDBView::GetInsertIndexHelper(nsIMsgDBHdr *msgHdr, nsTArray<nsMsgKey> &keys,
|
||||||
|
@ -4599,9 +4659,8 @@ nsMsgViewIndex nsMsgDBView::GetInsertIndexHelper(nsIMsgDBHdr *msgHdr, nsTArray<n
|
||||||
EntryInfo2.id = keys[tryIndex];
|
EntryInfo2.id = keys[tryIndex];
|
||||||
if (folders)
|
if (folders)
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsISupports> curFolder;
|
nsCOMPtr<nsIMsgFolder> curFolder = do_QueryElementAt(folders, tryIndex);
|
||||||
folders->GetElementAt(tryIndex, getter_AddRefs(curFolder));
|
EntryInfo2.folder = curFolder;
|
||||||
EntryInfo2.folder = curFolder;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
EntryInfo2.folder = m_folder;
|
EntryInfo2.folder = m_folder;
|
||||||
|
@ -4663,13 +4722,16 @@ nsMsgViewIndex nsMsgDBView::GetInsertIndex(nsIMsgDBHdr *msgHdr)
|
||||||
return GetInsertIndexHelper(msgHdr, m_keys, m_sortOrder, m_sortType);
|
return GetInsertIndexHelper(msgHdr, m_keys, m_sortOrder, m_sortType);
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult nsMsgDBView::AddHdr(nsIMsgDBHdr *msgHdr)
|
nsresult nsMsgDBView::AddHdr(nsIMsgDBHdr *msgHdr, nsMsgViewIndex *resultIndex)
|
||||||
{
|
{
|
||||||
PRUint32 flags = 0;
|
PRUint32 flags = 0;
|
||||||
#ifdef DEBUG_bienvenu
|
#ifdef DEBUG_bienvenu
|
||||||
NS_ASSERTION(m_keys.Length() == m_flags.Length() && (int) m_keys.Length() == m_levels.Length(), "view arrays out of sync!");
|
NS_ASSERTION(m_keys.Length() == m_flags.Length() && (int) m_keys.Length() == m_levels.Length(), "view arrays out of sync!");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (resultIndex)
|
||||||
|
*resultIndex = nsMsgViewIndex_None;
|
||||||
|
|
||||||
if (!GetShowingIgnored())
|
if (!GetShowingIgnored())
|
||||||
{
|
{
|
||||||
nsCOMPtr <nsIMsgThread> thread;
|
nsCOMPtr <nsIMsgThread> thread;
|
||||||
|
@ -4708,6 +4770,8 @@ nsresult nsMsgDBView::AddHdr(nsIMsgDBHdr *msgHdr)
|
||||||
m_keys.AppendElement(msgKey);
|
m_keys.AppendElement(msgKey);
|
||||||
m_flags.AppendElement(flags);
|
m_flags.AppendElement(flags);
|
||||||
m_levels.AppendElement(levelToAdd);
|
m_levels.AppendElement(levelToAdd);
|
||||||
|
if (resultIndex)
|
||||||
|
*resultIndex = GetSize() - 1;
|
||||||
|
|
||||||
// the call to NoteChange() has to happen after we add the key
|
// the call to NoteChange() has to happen after we add the key
|
||||||
// as NoteChange() will call RowCountChanged() which will call our GetRowCount()
|
// as NoteChange() will call RowCountChanged() which will call our GetRowCount()
|
||||||
|
@ -4718,6 +4782,8 @@ nsresult nsMsgDBView::AddHdr(nsIMsgDBHdr *msgHdr)
|
||||||
m_keys.InsertElementAt(0, msgKey);
|
m_keys.InsertElementAt(0, msgKey);
|
||||||
m_flags.InsertElementAt(0, flags);
|
m_flags.InsertElementAt(0, flags);
|
||||||
m_levels.InsertElementAt(0, levelToAdd);
|
m_levels.InsertElementAt(0, levelToAdd);
|
||||||
|
if (resultIndex)
|
||||||
|
*resultIndex = 0;
|
||||||
|
|
||||||
// the call to NoteChange() has to happen after we insert the key
|
// the call to NoteChange() has to happen after we insert the key
|
||||||
// as NoteChange() will call RowCountChanged() which will call our GetRowCount()
|
// as NoteChange() will call RowCountChanged() which will call our GetRowCount()
|
||||||
|
@ -4731,6 +4797,8 @@ nsresult nsMsgDBView::AddHdr(nsIMsgDBHdr *msgHdr)
|
||||||
m_flags.InsertElementAt(insertIndex, flags);
|
m_flags.InsertElementAt(insertIndex, flags);
|
||||||
PRInt32 level = 0;
|
PRInt32 level = 0;
|
||||||
m_levels.InsertElementAt(insertIndex, level);
|
m_levels.InsertElementAt(insertIndex, level);
|
||||||
|
if (resultIndex)
|
||||||
|
*resultIndex = insertIndex;
|
||||||
|
|
||||||
// the call to NoteChange() has to happen after we add the key
|
// the call to NoteChange() has to happen after we add the key
|
||||||
// as NoteChange() will call RowCountChanged() which will call our GetRowCount()
|
// as NoteChange() will call RowCountChanged() which will call our GetRowCount()
|
||||||
|
|
|
@ -220,13 +220,14 @@ protected:
|
||||||
nsresult GenerateURIForMsgKey(nsMsgKey aMsgKey, nsIMsgFolder *folder, nsACString &aURI);
|
nsresult GenerateURIForMsgKey(nsMsgKey aMsgKey, nsIMsgFolder *folder, nsACString &aURI);
|
||||||
// routines used in building up view
|
// routines used in building up view
|
||||||
virtual PRBool WantsThisThread(nsIMsgThread * thread);
|
virtual PRBool WantsThisThread(nsIMsgThread * thread);
|
||||||
virtual nsresult AddHdr(nsIMsgDBHdr *msgHdr);
|
virtual nsresult AddHdr(nsIMsgDBHdr *msgHdr, nsMsgViewIndex *resultIndex = nsnull);
|
||||||
PRBool GetShowingIgnored() {return (m_viewFlags & nsMsgViewFlagsType::kShowIgnored) != 0;}
|
PRBool GetShowingIgnored() {return (m_viewFlags & nsMsgViewFlagsType::kShowIgnored) != 0;}
|
||||||
virtual nsresult OnNewHeader(nsIMsgDBHdr *aNewHdr, nsMsgKey parentKey, PRBool ensureListed);
|
virtual nsresult OnNewHeader(nsIMsgDBHdr *aNewHdr, nsMsgKey parentKey, PRBool ensureListed);
|
||||||
virtual nsMsgViewIndex GetInsertIndex(nsIMsgDBHdr *msgHdr);
|
virtual nsMsgViewIndex GetInsertIndex(nsIMsgDBHdr *msgHdr);
|
||||||
nsMsgViewIndex GetIndexForThread(nsIMsgDBHdr *hdr);
|
nsMsgViewIndex GetIndexForThread(nsIMsgDBHdr *hdr);
|
||||||
virtual nsresult GetThreadContainingIndex(nsMsgViewIndex index, nsIMsgThread **thread);
|
virtual nsresult GetThreadContainingIndex(nsMsgViewIndex index, nsIMsgThread **thread);
|
||||||
virtual nsresult GetMsgHdrForViewIndex(nsMsgViewIndex index, nsIMsgDBHdr **msgHdr);
|
virtual nsresult GetMsgHdrForViewIndex(nsMsgViewIndex index, nsIMsgDBHdr **msgHdr);
|
||||||
|
nsMsgViewIndex FindIndexForThread(nsIMsgDBHdr *msgHdr, PRBool newThread);
|
||||||
|
|
||||||
nsresult ToggleExpansion(nsMsgViewIndex index, PRUint32 *numChanged);
|
nsresult ToggleExpansion(nsMsgViewIndex index, PRUint32 *numChanged);
|
||||||
nsresult ExpandByIndex(nsMsgViewIndex index, PRUint32 *pNumExpanded);
|
nsresult ExpandByIndex(nsMsgViewIndex index, PRUint32 *pNumExpanded);
|
||||||
|
|
|
@ -607,7 +607,17 @@ nsresult nsMsgThreadedDBView::OnNewHeader(nsIMsgDBHdr *newHdr, nsMsgKey aParentK
|
||||||
{ // Fix flags on thread header.
|
{ // Fix flags on thread header.
|
||||||
PRInt32 threadCount;
|
PRInt32 threadCount;
|
||||||
PRUint32 threadFlags;
|
PRUint32 threadFlags;
|
||||||
|
PRBool moveThread = PR_FALSE;
|
||||||
nsMsgViewIndex threadIndex = ThreadIndexOfMsg(newKey, nsMsgViewIndex_None, &threadCount, &threadFlags);
|
nsMsgViewIndex threadIndex = ThreadIndexOfMsg(newKey, nsMsgViewIndex_None, &threadCount, &threadFlags);
|
||||||
|
nsCOMPtr <nsIMsgThread> threadHdr;
|
||||||
|
m_db->GetThreadContainingMsgHdr(newHdr, getter_AddRefs(threadHdr));
|
||||||
|
if (threadHdr && m_sortType == nsMsgViewSortType::byDate)
|
||||||
|
{
|
||||||
|
PRUint32 newestMsgInThread = 0, msgDate = 0;
|
||||||
|
threadHdr->GetNewestMsgDate(&newestMsgInThread);
|
||||||
|
newHdr->GetDateInSeconds(&msgDate);
|
||||||
|
moveThread = (msgDate == newestMsgInThread);
|
||||||
|
}
|
||||||
if (threadIndex != nsMsgViewIndex_None)
|
if (threadIndex != nsMsgViewIndex_None)
|
||||||
{
|
{
|
||||||
PRUint32 flags = m_flags[threadIndex];
|
PRUint32 flags = m_flags[threadIndex];
|
||||||
|
@ -658,13 +668,14 @@ nsresult nsMsgThreadedDBView::OnNewHeader(nsIMsgDBHdr *newHdr, nsMsgKey aParentK
|
||||||
// top of thread, change the keys array.
|
// top of thread, change the keys array.
|
||||||
m_keys[threadIndex] = newKey;
|
m_keys[threadIndex] = newKey;
|
||||||
}
|
}
|
||||||
|
if (moveThread)
|
||||||
|
MoveThreadAt(threadIndex);
|
||||||
|
else
|
||||||
// note change, to update the parent thread's unread and total counts
|
// note change, to update the parent thread's unread and total counts
|
||||||
NoteChange(threadIndex, 1, nsMsgViewNotificationCode::changed);
|
NoteChange(threadIndex, 1, nsMsgViewNotificationCode::changed);
|
||||||
}
|
}
|
||||||
else // adding msg to thread that's not in view.
|
else // adding msg to thread that's not in view.
|
||||||
{
|
{
|
||||||
nsCOMPtr <nsIMsgThread> threadHdr;
|
|
||||||
m_db->GetThreadContainingMsgHdr(newHdr, getter_AddRefs(threadHdr));
|
|
||||||
if (threadHdr)
|
if (threadHdr)
|
||||||
{
|
{
|
||||||
AddMsgToThreadNotInView(threadHdr, newHdr, ensureListed);
|
AddMsgToThreadNotInView(threadHdr, newHdr, ensureListed);
|
||||||
|
@ -722,6 +733,73 @@ nsMsgViewIndex nsMsgThreadedDBView::GetInsertInfoForNewHdr(nsIMsgDBHdr *newHdr,
|
||||||
return parentIndex;
|
return parentIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This method removes the thread at threadIndex from the view
|
||||||
|
// and puts it back in its new position, determined by the sort order.
|
||||||
|
// And, if the selection is affected, save and restore the selection.
|
||||||
|
void nsMsgThreadedDBView::MoveThreadAt(nsMsgViewIndex threadIndex)
|
||||||
|
{
|
||||||
|
// we need to check if the thread is collapsed or not...
|
||||||
|
// We want to turn off tree notifications so that we don't
|
||||||
|
// reload the current message.
|
||||||
|
// We also need to invalidate the range between where the thread was
|
||||||
|
// and where it ended up.
|
||||||
|
DisableChangeUpdates();
|
||||||
|
|
||||||
|
nsCOMPtr <nsIMsgDBHdr> threadHdr;
|
||||||
|
|
||||||
|
GetMsgHdrForViewIndex(threadIndex, getter_AddRefs(threadHdr));
|
||||||
|
PRInt32 childCount = 0;
|
||||||
|
|
||||||
|
nsMsgKey preservedKey;
|
||||||
|
nsAutoTArray<nsMsgKey, 1> preservedSelection;
|
||||||
|
SaveAndClearSelection(&preservedKey, preservedSelection);
|
||||||
|
PRUint32 saveFlags = m_flags[threadIndex];
|
||||||
|
PRBool threadIsExpanded = !(saveFlags & MSG_FLAG_ELIDED);
|
||||||
|
|
||||||
|
if (threadIsExpanded)
|
||||||
|
{
|
||||||
|
ExpansionDelta(threadIndex, &childCount);
|
||||||
|
childCount = -childCount;
|
||||||
|
}
|
||||||
|
nsTArray<nsMsgKey> threadKeys;
|
||||||
|
nsTArray<PRUint32> threadFlags;
|
||||||
|
nsTArray<PRUint8> threadLevels;
|
||||||
|
|
||||||
|
if (threadIsExpanded)
|
||||||
|
{
|
||||||
|
threadKeys.SetCapacity(childCount);
|
||||||
|
threadFlags.SetCapacity(childCount);
|
||||||
|
threadLevels.SetCapacity(childCount);
|
||||||
|
for (nsMsgViewIndex index = threadIndex + 1;
|
||||||
|
index < GetSize() && m_levels[index]; index++)
|
||||||
|
{
|
||||||
|
threadKeys.AppendElement(m_keys[index]);
|
||||||
|
threadFlags.AppendElement(m_flags[index]);
|
||||||
|
threadLevels.AppendElement(m_levels[index]);
|
||||||
|
}
|
||||||
|
PRUint32 collapseCount;
|
||||||
|
CollapseByIndex(threadIndex, &collapseCount);
|
||||||
|
}
|
||||||
|
nsMsgDBView::RemoveByIndex(threadIndex);
|
||||||
|
nsMsgViewIndex newIndex;
|
||||||
|
AddHdr(threadHdr, &newIndex);
|
||||||
|
|
||||||
|
if (threadIsExpanded)
|
||||||
|
{
|
||||||
|
m_keys.InsertElementsAt(newIndex + 1, threadKeys);
|
||||||
|
m_flags.InsertElementsAt(newIndex + 1, threadFlags);
|
||||||
|
m_levels.InsertElementsAt(newIndex + 1, threadLevels);
|
||||||
|
}
|
||||||
|
m_flags[newIndex] = saveFlags;
|
||||||
|
// unfreeze selection.
|
||||||
|
RestoreSelection(preservedKey, preservedSelection);
|
||||||
|
|
||||||
|
EnableChangeUpdates();
|
||||||
|
nsMsgViewIndex lowIndex = threadIndex < newIndex ? threadIndex : newIndex;
|
||||||
|
nsMsgViewIndex highIndex = lowIndex == threadIndex ? newIndex : threadIndex;
|
||||||
|
NoteChange(lowIndex, highIndex - lowIndex + childCount,
|
||||||
|
nsMsgViewNotificationCode::changed);
|
||||||
|
}
|
||||||
nsresult nsMsgThreadedDBView::AddMsgToThreadNotInView(nsIMsgThread *threadHdr, nsIMsgDBHdr *msgHdr, PRBool ensureListed)
|
nsresult nsMsgThreadedDBView::AddMsgToThreadNotInView(nsIMsgThread *threadHdr, nsIMsgDBHdr *msgHdr, PRBool ensureListed)
|
||||||
{
|
{
|
||||||
nsresult rv = NS_OK;
|
nsresult rv = NS_OK;
|
||||||
|
|
|
@ -73,6 +73,7 @@ protected:
|
||||||
void ClearPrevIdArray();
|
void ClearPrevIdArray();
|
||||||
virtual nsresult RemoveByIndex(nsMsgViewIndex index);
|
virtual nsresult RemoveByIndex(nsMsgViewIndex index);
|
||||||
nsMsgViewIndex GetInsertInfoForNewHdr(nsIMsgDBHdr *newHdr, nsMsgViewIndex threadIndex, PRInt32 targetLevel);
|
nsMsgViewIndex GetInsertInfoForNewHdr(nsIMsgDBHdr *newHdr, nsMsgViewIndex threadIndex, PRInt32 targetLevel);
|
||||||
|
void MoveThreadAt(nsMsgViewIndex threadIndex);
|
||||||
|
|
||||||
// these are used to save off the previous view so that bopping back and forth
|
// 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).
|
// between two views is quick (e.g., threaded and flat sorted by date).
|
||||||
|
|
Загрузка…
Ссылка в новой задаче