#73840 fix crashers caused by a missing and addref on the db in one case, one extra one in another.

#72256 Msg selection needs to hold when expanding threads of other msgs
#72264 sorting by thread doesn't restore selection properly
#72284 Get Msg selects new message instead of leaving thread pane selection on current selected message
#74068 scroll to selected message after the sort
sr=bienvenu
This commit is contained in:
sspitzer%netscape.com 2001-03-31 04:59:03 +00:00
Родитель ccc3c72626
Коммит 94deb79b59
5 изменённых файлов: 89 добавлений и 61 удалений

Просмотреть файл

@ -522,9 +522,6 @@ function CreateBareDBView(msgFolder, viewType, viewFlags, sortType, sortOrder)
// news defaults to threaded mode
viewFlags = nsMsgViewFlagsType.kThreadedDisplay;
}
else {
viewFlags &= nsMsgViewFlagsType.kThreadedDisplay;
}
}
if (!sortType) {

Просмотреть файл

@ -865,8 +865,10 @@ nsresult nsMsgDBView::GetFolderForViewIndex(nsMsgViewIndex index, nsIMsgFolder *
nsresult nsMsgDBView::GetDBForViewIndex(nsMsgViewIndex index, nsIMsgDatabase **db)
{
*db = m_db;
NS_IF_ADDREF(*db);
return NS_OK;
}
NS_IMETHODIMP nsMsgDBView::GetCellText(PRInt32 aRow, const PRUnichar * aColID, PRUnichar ** aValue)
{
nsresult rv = NS_OK;
@ -2852,8 +2854,7 @@ nsMsgViewIndex nsMsgDBView::GetIndexForThread(nsIMsgDBHdr *hdr)
// and put new header before found header, or at end.
for (PRInt32 i = GetSize() - 1; i >= 0; i--)
{
char level = m_levels[i];
if (level == 0)
if (m_levels[i])
{
if (insertKey < m_keys.GetAt(i))
prevInsertIndex = i;
@ -2884,8 +2885,7 @@ nsMsgViewIndex nsMsgDBView::GetIndexForThread(nsIMsgDBHdr *hdr)
// new header before found header, or at beginning.
for (PRInt32 i = 0; i < GetSize(); i++)
{
char level = m_levels[i];
if (level == 0)
if (m_levels[i])
{
if (insertKey > m_keys.GetAt(i))
{
@ -3042,13 +3042,13 @@ nsMsgViewIndex nsMsgDBView::GetInsertIndex(nsIMsgDBHdr *msgHdr)
nsresult nsMsgDBView::AddHdr(nsIMsgDBHdr *msgHdr)
{
PRUint32 flags = 0;
PRUint32 flags = 0;
#ifdef DEBUG_bienvenu
NS_ASSERTION((int) m_keys.GetSize() == m_flags.GetSize() && (int) m_keys.GetSize() == m_levels.GetSize(), "view arrays out of sync!");
NS_ASSERTION((int) m_keys.GetSize() == m_flags.GetSize() && (int) m_keys.GetSize() == m_levels.GetSize(), "view arrays out of sync!");
#endif
msgHdr->GetFlags(&flags);
if (flags & MSG_FLAG_IGNORED && !GetShowingIgnored())
return NS_OK;
if (flags & MSG_FLAG_IGNORED && !GetShowingIgnored())
return NS_OK;
nsMsgKey msgKey, threadId;
nsMsgKey threadParent;
@ -3057,40 +3057,52 @@ nsresult nsMsgDBView::AddHdr(nsIMsgDBHdr *msgHdr)
msgHdr->GetThreadParent(&threadParent);
// ### this isn't quite right, is it? Should be checking that our thread parent key is none?
if (threadParent == nsMsgKey_None)
flags |= MSG_VIEW_FLAG_ISTHREAD;
nsMsgViewIndex insertIndex = GetInsertIndex(msgHdr);
if (insertIndex == nsMsgViewIndex_None)
{
// if unreadonly, level is 0 because we must be the only msg in the thread.
char levelToAdd = 0; // ### TODO ((m_viewFlags & nsMsgViewFlagsType::kUnreadOnly) != 0) ? 0 : msgHdr->GetLevel();
if (threadParent == nsMsgKey_None)
flags |= MSG_VIEW_FLAG_ISTHREAD;
nsMsgViewIndex insertIndex = GetInsertIndex(msgHdr);
if (insertIndex == nsMsgViewIndex_None)
{
// if unreadonly, level is 0 because we must be the only msg in the thread.
PRInt32 levelToAdd = 0;
#if 0
if (!(m_viewFlags & nsMsgViewFlagsType::kUnreadOnly))
{
levelToAdd = FindLevelInThread(msgHdr, insertIndex);
}
#endif
if (m_sortOrder == nsMsgViewSortOrder::ascending)
{
m_keys.Add(msgKey);
m_flags.Add(flags);
m_levels.Add(levelToAdd);
NoteChange(m_keys.GetSize() - 1, 1, nsMsgViewNotificationCode::insertOrDelete);
}
else
{
m_keys.InsertAt(0, msgKey);
m_flags.InsertAt(0, flags);
m_levels.InsertAt(0, levelToAdd);
NoteChange(0, 1, nsMsgViewNotificationCode::insertOrDelete);
}
m_sortValid = PR_FALSE;
{
m_keys.Add(msgKey);
m_flags.Add(flags);
m_levels.Add(levelToAdd);
NoteChange(m_keys.GetSize() - 1, 1, nsMsgViewNotificationCode::insertOrDelete);
}
else
{
m_keys.InsertAt(insertIndex, msgKey);
m_flags.InsertAt(insertIndex, flags);
char level = 0; // ### TODO (m_sortType == nsMsgViewSortType::byThread) ? 0 : msgHdr->GetLevel();
m_levels.InsertAt(insertIndex, level);
NoteChange(insertIndex, 1, nsMsgViewNotificationCode::insertOrDelete);
m_keys.InsertAt(0, msgKey);
m_flags.InsertAt(0, flags);
m_levels.InsertAt(0, levelToAdd);
NoteChange(0, 1, nsMsgViewNotificationCode::insertOrDelete);
}
OnHeaderAddedOrDeleted();
return NS_OK;
m_sortValid = PR_FALSE;
}
else
{
m_keys.InsertAt(insertIndex, msgKey);
m_flags.InsertAt(insertIndex, flags);
PRInt32 level = 0;
#if 0
if (m_viewFlags & nsMsgViewFlagsType::kThreadedDisplay)
{
level = FindLevelInThread(msgHdr, insertIndex);
}
#endif
m_levels.InsertAt(insertIndex, level);
NoteChange(insertIndex, 1, nsMsgViewNotificationCode::insertOrDelete);
}
OnHeaderAddedOrDeleted();
return NS_OK;
}
nsresult nsMsgDBView::InsertHdrAt(nsIMsgDBHdr *msgHdr, nsMsgViewIndex insertIndex)
@ -3103,7 +3115,13 @@ nsresult nsMsgDBView::InsertHdrAt(nsIMsgDBHdr *msgHdr, nsMsgViewIndex insertInde
NoteStartChange(insertIndex, 1, nsMsgViewNotificationCode::changed);
m_keys.SetAt(insertIndex, msgKey);
m_flags.SetAt(insertIndex, flags);
char level = 0; // ### TODO (m_sortType == nsMsgViewSortType::byThread) ? 0 : msgHdr->GetLevel()
PRInt32 level = 0;
#if 0
if (m_viewFlags & nsMsgViewFlagsType::kThreadedDisplay)
{
level = FindLevelInThread(msgHdr, insertIndex);
}
#endif
m_levels.SetAt(insertIndex, level);
NoteEndChange(insertIndex, 1, nsMsgViewNotificationCode::changed);
OnHeaderAddedOrDeleted();
@ -3116,7 +3134,7 @@ PRBool nsMsgDBView::WantsThisThread(nsIMsgThread * /*threadHdr*/)
return PR_TRUE; // default is to want all threads.
}
PRInt32 nsMsgDBView::FindLevelInThread(nsIMsgDBHdr *msgHdr, nsMsgKey msgKey, nsMsgViewIndex startOfThreadViewIndex)
PRInt32 nsMsgDBView::FindLevelInThread(nsIMsgDBHdr *msgHdr, nsMsgViewIndex startOfThreadViewIndex)
{
nsMsgKey threadParent;
msgHdr->GetThreadParent(&threadParent);
@ -3164,7 +3182,7 @@ nsresult nsMsgDBView::ListIdsInThread(nsIMsgThread *threadHdr, nsMsgViewIndex st
// ### TODO - how about hasChildren flag?
m_flags.InsertAt(viewIndex, msgFlags & ~MSG_VIEW_FLAGS);
// ### TODO this is going to be tricky - might use enumerators
PRInt32 level = FindLevelInThread(msgHdr, msgKey, startOfThreadViewIndex);
PRInt32 level = FindLevelInThread(msgHdr, startOfThreadViewIndex);
m_levels.InsertAt(viewIndex, level);
// turn off thread or elided bit if they got turned on (maybe from new only view?)
if (i > 0)
@ -3361,7 +3379,7 @@ NS_IMETHODIMP nsMsgDBView::OnAnnouncerGoingAway(nsIDBChangeAnnouncer *instigator
// this will force the outliner to ask for the cell values
// since we don't have a db and we don't have any keys,
// the thread pane goes blank
mOutliner->Invalidate();
if (mOutliner) mOutliner->Invalidate();
return NS_OK;
}
@ -4256,3 +4274,14 @@ nsresult nsMsgDBView::GetFolders(nsISupportsArray **aFolders)
return NS_OK;
}
nsresult nsMsgDBView::AdjustRowCount(PRInt32 rowCountBeforeSort, PRInt32 rowCountAfterSort)
{
PRInt32 rowChange = rowCountBeforeSort - rowCountAfterSort;
if (rowChange) {
// this is not safe to use when you have a selection
// RowCountChanged() will call AdjustSelection()
if (mOutliner) mOutliner->RowCountChanged(0, rowChange);
}
return NS_OK;
}

Просмотреть файл

@ -126,6 +126,12 @@ protected:
nsresult SaveSelection(nsMsgKeyArray * aMsgKeyArray);
nsresult RestoreSelection(nsMsgKeyArray * aMsgKeyArray);
// this is not safe to use when you have a selection
// RowCountChanged() will call AdjustSelection()
// it should be called after SaveSelection() and before
// RestoreSelection()
nsresult AdjustRowCount(PRInt32 rowCountBeforeSort, PRInt32 rowCountAfterSort);
nsresult GetSelectedIndices(nsUInt32Array *selection);
nsresult GenerateURIForMsgKey(nsMsgKey aMsgKey, nsIMsgFolder *folder, char ** aURI);
// routines used in building up view
@ -172,7 +178,7 @@ protected:
nsresult ListIdsInThread(nsIMsgThread *threadHdr, nsMsgViewIndex viewIndex, PRUint32 *pNumListed);
nsresult ListUnreadIdsInThread(nsIMsgThread *threadHdr, nsMsgViewIndex startOfThreadViewIndex, PRUint32 *pNumListed);
PRInt32 FindLevelInThread(nsIMsgDBHdr *msgHdr, nsMsgKey msgKey, nsMsgViewIndex startOfThreadViewIndex);
PRInt32 FindLevelInThread(nsIMsgDBHdr *msgHdr, nsMsgViewIndex startOfThreadViewIndex);
PRInt32 GetSize(void) {return(m_keys.GetSize());}
// notification api's

Просмотреть файл

@ -139,7 +139,7 @@ nsresult nsMsgSearchDBView::GetDBForViewIndex(nsMsgViewIndex index, nsIMsgDataba
nsCOMPtr <nsIMsgFolder> aFolder;
GetFolderForViewIndex(index, getter_AddRefs(aFolder));
if (aFolder)
return aFolder->GetMsgDatabase(nsnull, getter_AddRefs(db));
return aFolder->GetMsgDatabase(nsnull, db);
else
return NS_MSG_INVALID_DBVIEW_INDEX;
}
@ -531,10 +531,9 @@ NS_IMETHODIMP nsMsgSearchDBView::Sort(nsMsgViewSortTypeValue sortType, nsMsgView
// the sort may have changed the number of rows
// before we restore the selection, tell the outliner
PRInt32 rowCountAfterSort = GetSize();
if (rowCountBeforeSort != rowCountAfterSort) {
mOutliner->RowCountChanged(rowCountBeforeSort, rowCountBeforeSort - rowCountAfterSort);
}
// do this before we call restore selection
// this is safe when there is no selection.
rv = AdjustRowCount(rowCountBeforeSort, GetSize());
RestoreSelection(&preservedSelection);
if (mOutliner) mOutliner->Invalidate();

Просмотреть файл

@ -155,10 +155,9 @@ NS_IMETHODIMP nsMsgThreadedDBView::Sort(nsMsgViewSortTypeValue sortType, nsMsgVi
// the sort may have changed the number of rows
// before we restore the selection, tell the outliner
PRInt32 rowCountAfterSort = GetSize();
if (rowCountBeforeSort != rowCountAfterSort) {
mOutliner->RowCountChanged(rowCountBeforeSort, rowCountBeforeSort - rowCountAfterSort);
}
// do this before we call restore selection
// this is safe when there is no selection.
rv = AdjustRowCount(rowCountBeforeSort, GetSize());
RestoreSelection(&preservedSelection);
if (mOutliner) mOutliner->Invalidate();
@ -173,10 +172,9 @@ NS_IMETHODIMP nsMsgThreadedDBView::Sort(nsMsgViewSortTypeValue sortType, nsMsgVi
// the sort may have changed the number of rows
// before we update the selection, tell the outliner
PRInt32 rowCountAfterSort = GetSize();
if (rowCountBeforeSort != rowCountAfterSort) {
mOutliner->RowCountChanged(rowCountBeforeSort, rowCountBeforeSort - rowCountAfterSort);
}
// do this before we call restore selection
// this is safe when there is no selection.
rv = AdjustRowCount(rowCountBeforeSort, GetSize());
RestoreSelection(&preservedSelection);
if (mOutliner) mOutliner->Invalidate();
@ -204,10 +202,9 @@ NS_IMETHODIMP nsMsgThreadedDBView::Sort(nsMsgViewSortTypeValue sortType, nsMsgVi
// the sort may have changed the number of rows
// before we restore the selection, tell the outliner
PRInt32 rowCountAfterSort = GetSize();
if (rowCountBeforeSort != rowCountAfterSort) {
mOutliner->RowCountChanged(rowCountBeforeSort, rowCountBeforeSort - rowCountAfterSort);
}
// do this before we call restore selection
// this is safe when there is no selection.
rv = AdjustRowCount(rowCountBeforeSort, GetSize());
RestoreSelection(&preservedSelection);
if (mOutliner) mOutliner->Invalidate();