NS_IMETHODIMP nsMsgSearchDBView::OpenWithHdrs(nsISimpleEnumerator *aHeaders, nsMsgViewSortTypeValue aSortType, nsMsgViewSortOrderValue aSortOrder, nsMsgViewFlagsTypeValue aViewFlags, int32_t *aCount) { if (aViewFlags & nsMsgViewFlagsType::kGroupBySort) return nsMsgGroupView::OpenWithHdrs(aHeaders, aSortType, aSortOrder, aViewFlags, aCount); m_sortType = aSortType; m_sortOrder = aSortOrder; m_viewFlags = aViewFlags; SaveSortInfo(m_sortType, m_sortOrder); bool hasMore; nsCOMPtr<nsISupports> supports; nsCOMPtr<nsIMsgDBHdr> msgHdr; nsCOMPtr<nsIMsgFolder> folder; nsresult rv = NS_OK; while (NS_SUCCEEDED(rv) && NS_SUCCEEDED(rv = aHeaders->HasMoreElements(&hasMore)) && hasMore) { rv = aHeaders->GetNext(getter_AddRefs(supports)); if (NS_SUCCEEDED(rv) && supports) { msgHdr = do_QueryInterface(supports); msgHdr->GetFolder(getter_AddRefs(folder)); AddHdrFromFolder(msgHdr, folder); } } *aCount = m_keys.Length(); return rv; }
nsresult nsMsgThreadedDBView::InitThreadedView(PRInt32 *pCount) { nsresult rv; m_keys.Clear(); m_flags.Clear(); m_levels.Clear(); m_prevKeys.Clear(); m_prevFlags.Clear(); m_prevLevels.Clear(); m_havePrevView = false; nsresult getSortrv = NS_OK; // ### TODO m_db->GetSortInfo(&sortType, &sortOrder); // list all the ids into m_keys. nsMsgKey startMsg = 0; do { const PRInt32 kIdChunkSize = 400; PRInt32 numListed = 0; nsMsgKey idArray[kIdChunkSize]; PRInt32 flagArray[kIdChunkSize]; char levelArray[kIdChunkSize]; rv = ListThreadIds(&startMsg, (m_viewFlags & nsMsgViewFlagsType::kUnreadOnly) != 0, idArray, flagArray, levelArray, kIdChunkSize, &numListed, nsnull); if (NS_SUCCEEDED(rv)) { PRInt32 numAdded = AddKeys(idArray, flagArray, levelArray, m_sortType, numListed); if (pCount) *pCount += numAdded; } } while (NS_SUCCEEDED(rv) && startMsg != nsMsgKey_None); if (NS_SUCCEEDED(getSortrv)) { rv = InitSort(m_sortType, m_sortOrder); SaveSortInfo(m_sortType, m_sortOrder); } return rv; }
NS_IMETHODIMP nsMsgGroupView::OpenWithHdrs(nsISimpleEnumerator *aHeaders, nsMsgViewSortTypeValue aSortType, nsMsgViewSortOrderValue aSortOrder, nsMsgViewFlagsTypeValue aViewFlags, int32_t *aCount) { nsresult rv = NS_OK; m_groupsTable.Clear(); if (aSortType == nsMsgViewSortType::byThread || aSortType == nsMsgViewSortType::byId || aSortType == nsMsgViewSortType::byNone || aSortType == nsMsgViewSortType::bySize) return NS_ERROR_INVALID_ARG; m_sortType = aSortType; m_sortOrder = aSortOrder; m_viewFlags = aViewFlags | nsMsgViewFlagsType::kThreadedDisplay | nsMsgViewFlagsType::kGroupBySort; SaveSortInfo(m_sortType, m_sortOrder); bool hasMore; nsCOMPtr <nsISupports> supports; nsCOMPtr <nsIMsgDBHdr> msgHdr; while (NS_SUCCEEDED(rv) && NS_SUCCEEDED(rv = aHeaders->HasMoreElements(&hasMore)) && hasMore) { rv = aHeaders->GetNext(getter_AddRefs(supports)); if (NS_SUCCEEDED(rv) && supports) { bool notUsed; msgHdr = do_QueryInterface(supports); AddHdrToThread(msgHdr, ¬Used); } } uint32_t expandFlags = 0; bool expandAll = m_viewFlags & nsMsgViewFlagsType::kExpandAll; uint32_t viewFlag = (m_sortType == nsMsgViewSortType::byDate) ? MSG_VIEW_FLAG_DUMMY : 0; if (viewFlag && m_db) { nsCOMPtr <nsIDBFolderInfo> dbFolderInfo; nsresult rv = m_db->GetDBFolderInfo(getter_AddRefs(dbFolderInfo)); NS_ENSURE_SUCCESS(rv, rv); if (dbFolderInfo) dbFolderInfo->GetUint32Property("dateGroupFlags", 0, &expandFlags); } // go through the view updating the flags for threads with more than one message... // and if grouped by date, expanding threads that were expanded before. for (uint32_t viewIndex = 0; viewIndex < m_keys.Length(); viewIndex++) { nsCOMPtr <nsIMsgThread> thread; GetThreadContainingIndex(viewIndex, getter_AddRefs(thread)); if (thread) { uint32_t numChildren; thread->GetNumChildren(&numChildren); if (numChildren > 1 || viewFlag) OrExtraFlag(viewIndex, viewFlag | MSG_VIEW_FLAG_HASCHILDREN); if (expandAll || expandFlags) { nsMsgGroupThread *groupThread = static_cast<nsMsgGroupThread *>((nsIMsgThread *) thread); if (expandAll || expandFlags & (1 << groupThread->m_threadKey)) { uint32_t numExpanded; ExpandByIndex(viewIndex, &numExpanded); viewIndex += numExpanded; } } } } *aCount = m_keys.Length(); return rv; }
NS_IMETHODIMP nsMsgThreadedDBView::Sort(nsMsgViewSortTypeValue sortType, nsMsgViewSortOrderValue sortOrder) { nsresult rv; PRInt32 rowCountBeforeSort = GetSize(); if (!rowCountBeforeSort) { // still need to setup our flags even when no articles - bug 98183. m_sortType = sortType; if (sortType == nsMsgViewSortType::byThread && ! (m_viewFlags & nsMsgViewFlagsType::kThreadedDisplay)) SetViewFlags(m_viewFlags | nsMsgViewFlagsType::kThreadedDisplay); SaveSortInfo(sortType, sortOrder); return NS_OK; } // sort threads by sort order bool sortThreads = m_viewFlags & (nsMsgViewFlagsType::kThreadedDisplay | nsMsgViewFlagsType::kGroupBySort); // if sort type is by thread, and we're already threaded, change sort type to byId if (sortType == nsMsgViewSortType::byThread && (m_viewFlags & nsMsgViewFlagsType::kThreadedDisplay) != 0) sortType = nsMsgViewSortType::byId; nsMsgKey preservedKey; nsAutoTArray<nsMsgKey, 1> preservedSelection; SaveAndClearSelection(&preservedKey, preservedSelection); // if the client wants us to forget our cached id arrays, they // should build a new view. If this isn't good enough, we // need a method to do that. if (sortType != m_sortType || !m_sortValid || sortThreads) { SaveSortInfo(sortType, sortOrder); if (sortType == nsMsgViewSortType::byThread) { m_sortType = sortType; m_viewFlags |= nsMsgViewFlagsType::kThreadedDisplay; m_viewFlags &= nsMsgViewFlagsType::kGroupBySort; if ( m_havePrevView) { // restore saved id array and flags array m_keys = m_prevKeys; m_flags = m_prevFlags; m_levels = m_prevLevels; m_sortValid = true; // the sort may have changed the number of rows // before we restore the selection, tell the tree // do this before we call restore selection // this is safe when there is no selection. rv = AdjustRowCount(rowCountBeforeSort, GetSize()); RestoreSelection(preservedKey, preservedSelection); if (mTree) mTree->Invalidate(); return NS_OK; } else { // set sort info in anticipation of what Init will do. InitThreadedView(nsnull); // build up thread list. if (sortOrder != nsMsgViewSortOrder::ascending) Sort(sortType, sortOrder); // the sort may have changed the number of rows // before we update the selection, tell the tree // do this before we call restore selection // this is safe when there is no selection. rv = AdjustRowCount(rowCountBeforeSort, GetSize()); RestoreSelection(preservedKey, preservedSelection); if (mTree) mTree->Invalidate(); return NS_OK; } } else if (sortType != nsMsgViewSortType::byThread && (m_sortType == nsMsgViewSortType::byThread || sortThreads)/* && !m_havePrevView*/) { if (sortThreads) { SortThreads(sortType, sortOrder); sortType = nsMsgViewSortType::byThread; // hack so base class won't do anything } else { // going from SortByThread to non-thread sort - must build new key, level,and flags arrays m_prevKeys = m_keys; m_prevFlags = m_flags; m_prevLevels = m_levels; // do this before we sort, so that we'll use the cheap method // of expanding. m_viewFlags &= ~(nsMsgViewFlagsType::kThreadedDisplay | nsMsgViewFlagsType::kGroupBySort); ExpandAll(); // m_idArray.RemoveAll(); // m_flags.Clear(); m_havePrevView = true; } } } else if (m_sortOrder != sortOrder)// check for toggling the sort { nsMsgDBView::Sort(sortType, sortOrder); } if (!sortThreads) { // call the base class in case we're not sorting by thread rv = nsMsgDBView::Sort(sortType, sortOrder); SaveSortInfo(sortType, sortOrder); } // the sort may have changed the number of rows // before we restore the selection, tell the tree // do this before we call restore selection // this is safe when there is no selection. rv = AdjustRowCount(rowCountBeforeSort, GetSize()); RestoreSelection(preservedKey, preservedSelection); if (mTree) mTree->Invalidate(); NS_ENSURE_SUCCESS(rv,rv); return NS_OK; }