fix 462581, problems going between grouped and threaded/unthreaded views in saved search folders, r=standard8, sr=neil
This commit is contained in:
Родитель
1cf9d862e5
Коммит
9e0e634ee6
|
@ -4636,11 +4636,7 @@ nsMsgViewIndex nsMsgDBView::GetInsertIndexHelper(nsIMsgDBHdr *msgHdr, nsTArray<n
|
|||
EntryInfo2.folder = folders ? folders->ObjectAt(tryIndex) : m_folder.get();
|
||||
|
||||
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));
|
||||
EntryInfo2.folder->GetMessageHeader(EntryInfo2.id, getter_AddRefs(tryHdr));
|
||||
if (!tryHdr)
|
||||
break;
|
||||
if (fieldType == kCollationKey)
|
||||
|
@ -6823,6 +6819,11 @@ NS_IMETHODIMP nsMsgDBView::nsMsgViewHdrEnumerator::GetNext(nsISupports **aItem)
|
|||
if (m_curHdrIndex >= m_view->GetSize())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// Ignore dummy header. We won't have empty groups, so
|
||||
// we know the view index is good.
|
||||
if (m_view->m_flags[m_curHdrIndex] & MSG_VIEW_FLAG_DUMMY)
|
||||
++m_curHdrIndex;
|
||||
|
||||
nsCOMPtr<nsIMsgDBHdr> nextHdr;
|
||||
|
||||
nsresult rv = m_view->GetMsgHdrForViewIndex(m_curHdrIndex++, getter_AddRefs(nextHdr));
|
||||
|
|
|
@ -79,6 +79,7 @@ NS_IMETHODIMP nsMsgGroupView::Open(nsIMsgFolder *aFolder, nsMsgViewSortTypeValue
|
|||
|
||||
void nsMsgGroupView::InternalClose()
|
||||
{
|
||||
m_groupsTable.Clear();
|
||||
// nothing to do if we're not grouped.
|
||||
if (!(m_viewFlags & nsMsgViewFlagsType::kGroupBySort))
|
||||
return;
|
||||
|
@ -114,7 +115,6 @@ void nsMsgGroupView::InternalClose()
|
|||
dbFolderInfo->SetUint32Property("dateGroupFlags", expandFlags);
|
||||
}
|
||||
}
|
||||
m_groupsTable.Clear();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgGroupView::Close()
|
||||
|
@ -436,8 +436,35 @@ NS_IMETHODIMP nsMsgGroupView::GetViewType(nsMsgViewTypeValue *aViewType)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
PLDHashOperator
|
||||
nsMsgGroupView::GroupTableCloner(const nsAString &aKey, nsIMsgThread* aGroupThread, void* aArg)
|
||||
{
|
||||
nsMsgGroupView* view = static_cast<nsMsgGroupView*>(aArg);
|
||||
nsresult rv = view->m_groupsTable.Put(aKey, aGroupThread);
|
||||
return NS_SUCCEEDED(rv) ? PL_DHASH_NEXT : PL_DHASH_STOP;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMsgGroupView::CopyDBView(nsMsgDBView *aNewMsgDBView, nsIMessenger *aMessengerInstance,
|
||||
nsIMsgWindow *aMsgWindow, nsIMsgDBViewCommandUpdater *aCmdUpdater)
|
||||
{
|
||||
nsMsgDBView::CopyDBView(aNewMsgDBView, aMessengerInstance, aMsgWindow, aCmdUpdater);
|
||||
nsMsgGroupView* newMsgDBView = (nsMsgGroupView *) aNewMsgDBView;
|
||||
|
||||
// If grouped, we need to clone the group thread hash table.
|
||||
if (m_viewFlags & nsMsgViewFlagsType::kGroupBySort)
|
||||
m_groupsTable.EnumerateRead(GroupTableCloner, newMsgDBView);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// E.g., if the day has changed, we need to close and re-open the view.
|
||||
nsresult nsMsgGroupView::RebuildView()
|
||||
// Or, if we're switching between grouping and threading in a cross-folder
|
||||
// saved search. In that case, we needed to build an enumerator based on the
|
||||
// old view type, and internally close the view based on its old type, but
|
||||
// rebuild the new view based on the new view type. So we pass the new
|
||||
// view flags to OpenWithHdrs.
|
||||
nsresult nsMsgGroupView::RebuildView(nsMsgViewFlagsTypeValue newFlags)
|
||||
{
|
||||
nsCOMPtr <nsISimpleEnumerator> headers;
|
||||
if (NS_SUCCEEDED(GetMessageEnumerator(getter_AddRefs(headers))))
|
||||
|
@ -460,7 +487,7 @@ nsresult nsMsgGroupView::RebuildView()
|
|||
if (mTree)
|
||||
mTree->RowCountChanged(0, -oldSize);
|
||||
DisableChangeUpdates();
|
||||
nsresult rv = OpenWithHdrs(headers, m_sortType, m_sortOrder, m_viewFlags, &count);
|
||||
nsresult rv = OpenWithHdrs(headers, m_sortType, m_sortOrder, newFlags, &count);
|
||||
EnableChangeUpdates();
|
||||
if (mTree)
|
||||
mTree->RowCountChanged(0, GetSize());
|
||||
|
@ -484,7 +511,7 @@ nsresult nsMsgGroupView::OnNewHeader(nsIMsgDBHdr *newHdr, nsMsgKey aParentKey, P
|
|||
// check if we're adding a header, and the current day has changed. If it has, we're just going to
|
||||
// close and re-open the view so things will be correctly categorized.
|
||||
if (m_dayChanged)
|
||||
return RebuildView();
|
||||
return RebuildView(m_viewFlags);
|
||||
|
||||
PRBool newThread;
|
||||
nsMsgGroupThread *thread = AddHdrToThread(newHdr, &newThread);
|
||||
|
@ -564,7 +591,7 @@ NS_IMETHODIMP nsMsgGroupView::OnHdrFlagsChanged(nsIMsgDBHdr *aHdrChanged, PRUint
|
|||
// check if we're adding a header, and the current day has changed. If it has, we're just going to
|
||||
// close and re-open the view so things will be correctly categorized.
|
||||
if (m_dayChanged)
|
||||
return RebuildView();
|
||||
return RebuildView(m_viewFlags);
|
||||
|
||||
nsresult rv = GetThreadContainingMsgHdr(aHdrChanged, getter_AddRefs(thread));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
@ -584,7 +611,7 @@ NS_IMETHODIMP nsMsgGroupView::OnHdrDeleted(nsIMsgDBHdr *aHdrDeleted, nsMsgKey aP
|
|||
// check if we're adding a header, and the current day has changed. If it has, we're just going to
|
||||
// close and re-open the view so things will be correctly categorized.
|
||||
if (m_dayChanged)
|
||||
return RebuildView();
|
||||
return RebuildView(m_viewFlags);
|
||||
|
||||
nsCOMPtr <nsIMsgThread> thread;
|
||||
nsMsgKey keyDeleted;
|
||||
|
|
|
@ -59,6 +59,8 @@ public:
|
|||
nsMsgViewSortOrderValue aSortOrder, nsMsgViewFlagsTypeValue aViewFlags,
|
||||
PRInt32 *aCount);
|
||||
NS_IMETHOD GetViewType(nsMsgViewTypeValue *aViewType);
|
||||
NS_IMETHOD CopyDBView(nsMsgDBView *aNewMsgDBView, nsIMessenger *aMessengerInstance,
|
||||
nsIMsgWindow *aMsgWindow, nsIMsgDBViewCommandUpdater *aCmdUpdater);
|
||||
NS_IMETHOD Close();
|
||||
NS_IMETHOD OnHdrDeleted(nsIMsgDBHdr *aHdrDeleted, nsMsgKey aParentKey, PRInt32 aFlags,
|
||||
nsIDBChangeListener *aInstigator);
|
||||
|
@ -71,7 +73,7 @@ public:
|
|||
NS_IMETHOD GetCellText(PRInt32 aRow, nsITreeColumn* aCol, nsAString& aValue);
|
||||
|
||||
protected:
|
||||
void InternalClose();
|
||||
virtual void InternalClose();
|
||||
nsMsgGroupThread *AddHdrToThread(nsIMsgDBHdr *msgHdr, PRBool *pNewThread);
|
||||
nsresult HashHdr(nsIMsgDBHdr *msgHdr, nsString& aHashKey);
|
||||
nsresult GetAgeBucketValue(nsIMsgDBHdr *aMsgHdr, PRUint32 * aAgeBucket, PRBool rcvDate = PR_FALSE); // helper function to get the age bucket for a hdr, useful when grouped by date
|
||||
|
@ -84,8 +86,11 @@ protected:
|
|||
PRUint32 *pFlags = NULL);
|
||||
|
||||
PRBool GroupViewUsesDummyRow(); // returns true if we are grouped by a sort attribute that uses a dummy row
|
||||
virtual nsresult RebuildView();
|
||||
virtual nsresult RebuildView(nsMsgViewFlagsTypeValue newFlags);
|
||||
virtual nsMsgGroupThread *CreateGroupThread(nsIMsgDatabase *db);
|
||||
PR_STATIC_CALLBACK(PLDHashOperator) GroupTableCloner(const nsAString &aKey,
|
||||
nsIMsgThread* aGroupThread,
|
||||
void* aArg);
|
||||
|
||||
nsInterfaceHashtable <nsStringHashKey, nsIMsgThread> m_groupsTable;
|
||||
PRExplodedTime m_lastCurExplodedTime;
|
||||
|
|
|
@ -123,9 +123,20 @@ NS_IMETHODIMP nsMsgQuickSearchDBView::GetViewType(nsMsgViewTypeValue *aViewType)
|
|||
|
||||
nsresult nsMsgQuickSearchDBView::AddHdr(nsIMsgDBHdr *msgHdr, nsMsgViewIndex *resultIndex)
|
||||
{
|
||||
return (m_viewFlags & nsMsgViewFlagsType::kGroupBySort)
|
||||
? nsMsgGroupView::OnNewHeader(msgHdr, nsMsgKey_None, PR_TRUE)
|
||||
: nsMsgDBView::AddHdr(msgHdr, resultIndex);
|
||||
nsMsgKey msgKey;
|
||||
msgHdr->GetMessageKey(&msgKey);
|
||||
nsMsgViewIndex insertIndex = GetInsertIndexHelper(msgHdr, m_origKeys, nsnull,
|
||||
nsMsgViewSortOrder::ascending, nsMsgViewSortType::byId);
|
||||
m_origKeys.InsertElementAt(insertIndex, msgKey);
|
||||
if (m_viewFlags & (nsMsgViewFlagsType::kGroupBySort|
|
||||
nsMsgViewFlagsType::kThreadedDisplay))
|
||||
{
|
||||
nsMsgKey parentKey;
|
||||
msgHdr->GetThreadParent(&parentKey);
|
||||
return nsMsgThreadedDBView::OnNewHeader(msgHdr, parentKey, PR_TRUE);
|
||||
}
|
||||
else
|
||||
return nsMsgDBView::AddHdr(msgHdr, resultIndex);
|
||||
}
|
||||
|
||||
nsresult nsMsgQuickSearchDBView::OnNewHeader(nsIMsgDBHdr *newHdr, nsMsgKey aParentKey, PRBool ensureListed)
|
||||
|
@ -478,7 +489,6 @@ nsresult nsMsgQuickSearchDBView::SortThreads(nsMsgViewSortTypeValue sortType, ns
|
|||
threadRootIds.InsertElementAt(threadRootIndex, rootKey);
|
||||
}
|
||||
}
|
||||
m_origKeys.SwapElements(m_keys);
|
||||
// need to sort the top level threads now by sort order, if it's not by id.
|
||||
if (sortType != nsMsgViewSortType::byId)
|
||||
{
|
||||
|
@ -519,7 +529,6 @@ nsresult nsMsgQuickSearchDBView::SortThreads(nsMsgViewSortTypeValue sortType, ns
|
|||
}
|
||||
}
|
||||
}
|
||||
NS_ASSERTION(m_origKeys.Length() == m_keys.Length(), "problem threading quick search");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -628,12 +637,12 @@ nsMsgQuickSearchDBView::OpenWithHdrs(nsISimpleEnumerator *aHeaders,
|
|||
|
||||
NS_IMETHODIMP nsMsgQuickSearchDBView::SetViewFlags(nsMsgViewFlagsTypeValue aViewFlags)
|
||||
{
|
||||
nsMsgViewFlagsTypeValue saveViewFlags = m_viewFlags;
|
||||
nsresult rv = nsMsgDBView::SetViewFlags(aViewFlags);
|
||||
nsresult rv = NS_OK;
|
||||
// if the grouping has changed, rebuild the view
|
||||
if (saveViewFlags & nsMsgViewFlagsType::kGroupBySort ^
|
||||
if (m_viewFlags & nsMsgViewFlagsType::kGroupBySort ^
|
||||
(aViewFlags & nsMsgViewFlagsType::kGroupBySort))
|
||||
RebuildView();
|
||||
rv = RebuildView(aViewFlags);
|
||||
nsMsgDBView::SetViewFlags(aViewFlags);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
|
|
@ -158,6 +158,13 @@ NS_IMETHODIMP nsMsgSearchDBView::Close()
|
|||
return nsMsgGroupView::Close();
|
||||
}
|
||||
|
||||
void nsMsgSearchDBView::InternalClose()
|
||||
{
|
||||
m_threadsTable.Clear();
|
||||
m_hdrsTable.Clear();
|
||||
return nsMsgGroupView::InternalClose();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgSearchDBView::GetCellText(PRInt32 aRow, nsITreeColumn* aCol, nsAString& aValue)
|
||||
{
|
||||
const PRUnichar* colID;
|
||||
|
@ -972,7 +979,7 @@ NS_IMETHODIMP nsMsgSearchDBView::Sort(nsMsgViewSortTypeValue sortType, nsMsgView
|
|||
// since it rebuilds the thread objects.
|
||||
m_sortType = sortType;
|
||||
m_sortOrder = sortOrder;
|
||||
return RebuildView();
|
||||
return RebuildView(m_viewFlags);
|
||||
}
|
||||
|
||||
nsMsgKey preservedKey;
|
||||
|
@ -1259,47 +1266,3 @@ nsMsgSearchDBView::ListIdsInThread(nsIMsgThread *threadHdr,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsMsgSearchDBView::RebuildView()
|
||||
{
|
||||
if (m_viewFlags & nsMsgViewFlagsType::kGroupBySort)
|
||||
return nsMsgGroupView::RebuildView();
|
||||
|
||||
nsCOMPtr<nsISimpleEnumerator> headers;
|
||||
if (NS_SUCCEEDED(GetMessageEnumerator(getter_AddRefs(headers))))
|
||||
{
|
||||
PRInt32 count;
|
||||
// ### we need to be remembering headers, not keys.
|
||||
nsAutoTArray<nsMsgKey, 1> preservedSelection;
|
||||
nsMsgKey curSelectedKey;
|
||||
SaveAndClearSelection(&curSelectedKey, preservedSelection);
|
||||
InternalClose();
|
||||
PRInt32 oldSize = GetSize();
|
||||
// this is important, because the tree will ask us for our
|
||||
// row count, which get determine from the number of keys.
|
||||
m_keys.Clear();
|
||||
// be consistent
|
||||
m_flags.Clear();
|
||||
m_levels.Clear();
|
||||
m_folders.Clear();
|
||||
m_threadsTable.Clear();
|
||||
m_hdrsTable.Clear();
|
||||
|
||||
// this needs to happen after we remove all the keys, since RowCountChanged() will call our GetRowCount()
|
||||
if (mTree)
|
||||
mTree->RowCountChanged(0, -oldSize);
|
||||
DisableChangeUpdates();
|
||||
nsresult rv = OpenWithHdrs(headers, m_sortType, m_sortOrder, m_viewFlags, &count);
|
||||
EnableChangeUpdates();
|
||||
if (mTree)
|
||||
mTree->RowCountChanged(0, GetSize());
|
||||
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
// now, restore our desired selection
|
||||
nsAutoTArray<nsMsgKey, 1> keyArray;
|
||||
keyArray.AppendElement(curSelectedKey);
|
||||
|
||||
return RestoreSelection(curSelectedKey, keyArray);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -79,7 +79,6 @@ public:
|
|||
virtual nsresult GetMsgHdrForViewIndex(nsMsgViewIndex index, nsIMsgDBHdr **msgHdr);
|
||||
virtual nsresult OnNewHeader(nsIMsgDBHdr *newHdr, nsMsgKey parentKey, PRBool ensureListed);
|
||||
NS_IMETHOD GetFolderForViewIndex(nsMsgViewIndex index, nsIMsgFolder **folder);
|
||||
virtual nsresult RebuildView();
|
||||
|
||||
NS_IMETHOD OnAnnouncerGoingAway(nsIDBChangeAnnouncer *instigator);
|
||||
|
||||
|
@ -87,6 +86,7 @@ public:
|
|||
virtual nsresult GetFolderFromMsgURI(const char *aMsgURI, nsIMsgFolder **aFolder);
|
||||
|
||||
protected:
|
||||
virtual void InternalClose();
|
||||
virtual nsresult ListIdsInThread(nsIMsgThread *threadHdr,
|
||||
nsMsgViewIndex startOfThreadViewIndex,
|
||||
PRUint32 *pNumListed);
|
||||
|
|
|
@ -746,7 +746,9 @@ void nsMsgThreadedDBView::MoveThreadAt(nsMsgViewIndex threadIndex)
|
|||
// reload the current message.
|
||||
// We also need to invalidate the range between where the thread was
|
||||
// and where it ended up.
|
||||
DisableChangeUpdates();
|
||||
PRBool changesDisabled = mSuppressChangeNotification;
|
||||
if (!changesDisabled)
|
||||
DisableChangeUpdates();
|
||||
|
||||
nsCOMPtr <nsIMsgDBHdr> threadHdr;
|
||||
|
||||
|
@ -797,7 +799,8 @@ void nsMsgThreadedDBView::MoveThreadAt(nsMsgViewIndex threadIndex)
|
|||
// unfreeze selection.
|
||||
RestoreSelection(preservedKey, preservedSelection);
|
||||
|
||||
EnableChangeUpdates();
|
||||
if (!changesDisabled)
|
||||
EnableChangeUpdates();
|
||||
nsMsgViewIndex lowIndex = threadIndex < newIndex ? threadIndex : newIndex;
|
||||
nsMsgViewIndex highIndex = lowIndex == threadIndex ? newIndex : threadIndex;
|
||||
NoteChange(lowIndex, highIndex - lowIndex + childCount,
|
||||
|
@ -813,7 +816,7 @@ nsresult nsMsgThreadedDBView::AddMsgToThreadNotInView(nsIMsgThread *threadHdr, n
|
|||
PRBool msgKilled;
|
||||
msgHdr->GetIsKilled(&msgKilled);
|
||||
if (!msgKilled)
|
||||
rv = AddHdr(msgHdr);
|
||||
rv = nsMsgDBView::AddHdr(msgHdr);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
|
|
@ -494,15 +494,14 @@ NS_IMETHODIMP nsMsgXFVirtualFolderDBView::GetMsgFolder(nsIMsgFolder **aMsgFolder
|
|||
|
||||
NS_IMETHODIMP nsMsgXFVirtualFolderDBView::SetViewFlags(nsMsgViewFlagsTypeValue aViewFlags)
|
||||
{
|
||||
nsMsgViewFlagsTypeValue saveViewFlags = m_viewFlags;
|
||||
nsresult rv = nsMsgDBView::SetViewFlags(aViewFlags);
|
||||
nsresult rv = NS_OK;
|
||||
// if the grouping/threading has changed, rebuild the view
|
||||
if ((saveViewFlags & (nsMsgViewFlagsType::kGroupBySort |
|
||||
if ((m_viewFlags & (nsMsgViewFlagsType::kGroupBySort |
|
||||
nsMsgViewFlagsType::kThreadedDisplay)) !=
|
||||
(aViewFlags & (nsMsgViewFlagsType::kGroupBySort |
|
||||
nsMsgViewFlagsType::kThreadedDisplay)))
|
||||
RebuildView();
|
||||
|
||||
rv = RebuildView(aViewFlags);
|
||||
nsMsgDBView::SetViewFlags(aViewFlags);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче