NS_IMETHODIMP nsMsgXFVirtualFolderDBView::OnNewSearch() { PRInt32 oldSize = GetSize(); RemovePendingDBListeners(); m_doingSearch = PR_TRUE; m_folders->Clear(); m_keys.Clear(); m_levels.Clear(); m_flags.Clear(); // needs to happen after we remove the keys, since RowCountChanged() will call our GetRowCount() if (mTree) mTree->RowCountChanged(0, -oldSize); // to use the search results cache, we'll need to iterate over the scopes in the // search session, calling getNthSearchScope for i = 0; i < searchSession.countSearchScopes; i++ // and for each folder, then open the db and pull out the cached hits, add them to the view. // For each hit in a new folder, we'll then clean up the stale hits from the previous folder(s). PRInt32 scopeCount; nsCOMPtr <nsIMsgSearchSession> searchSession = do_QueryReferent(m_searchSession); nsCOMPtr<nsIMsgDBService> msgDBService = do_GetService(NS_MSGDB_SERVICE_CONTRACTID); searchSession->CountSearchScopes(&scopeCount); if (mTree) mTree->BeginUpdateBatch(); for (PRInt32 i = 0; i < scopeCount; i++) { nsMsgSearchScopeValue scopeId; nsCOMPtr<nsIMsgFolder> searchFolder; searchSession->GetNthSearchScope(i, &scopeId, getter_AddRefs(searchFolder)); if (searchFolder) { nsCOMPtr<nsISimpleEnumerator> cachedHits; nsCOMPtr<nsIMsgDatabase> searchDB; nsCString searchUri; m_viewFolder->GetURI(searchUri); nsresult rv = searchFolder->GetMsgDatabase(nsnull, getter_AddRefs(searchDB)); if (NS_SUCCEEDED(rv) && searchDB) { if (msgDBService) msgDBService->RegisterPendingListener(searchFolder, this); m_foldersSearchingOver.AppendObject(searchFolder); searchDB->GetCachedHits(searchUri.get(), getter_AddRefs(cachedHits)); PRBool hasMore; if (cachedHits) { cachedHits->HasMoreElements(&hasMore); if (hasMore) { nsMsgKey prevKey = nsMsgKey_None; while (hasMore) { nsCOMPtr <nsIMsgDBHdr> pHeader; nsresult rv = cachedHits->GetNext(getter_AddRefs(pHeader)); NS_ASSERTION(NS_SUCCEEDED(rv), "nsMsgDBEnumerator broken"); if (pHeader && NS_SUCCEEDED(rv)) { nsMsgKey msgKey; pHeader->GetMessageKey(&msgKey); NS_ASSERTION(prevKey == nsMsgKey_None || msgKey > prevKey, "cached Hits not sorted"); prevKey = msgKey; AddHdrFromFolder(pHeader, searchFolder); // need to QI to nsISupports? } else break; cachedHits->HasMoreElements(&hasMore); } } } } } } if (mTree) mTree->EndUpdateBatch(); m_curFolderStartKeyIndex = 0; m_curFolderGettingHits = nsnull; m_curFolderHasCachedHits = PR_FALSE; // if we have cached hits, sort them. if (GetSize() > 0) { if (m_sortType != nsMsgViewSortType::byThread) { m_sortValid = PR_FALSE; //sort the results Sort(m_sortType, m_sortOrder); } } // mSearchResults->Clear(); return NS_OK; }
NS_IMETHODIMP nsMsgXFVirtualFolderDBView::Close() { RemovePendingDBListeners(); return nsMsgSearchDBView::Close(); }
NS_IMETHODIMP nsMsgXFVirtualFolderDBView::OnNewSearch() { int32_t oldSize = GetSize(); RemovePendingDBListeners(); m_doingSearch = true; m_totalMessagesInView = 0; m_folders.Clear(); m_keys.Clear(); m_levels.Clear(); m_flags.Clear(); // needs to happen after we remove the keys, since RowCountChanged() will call our GetRowCount() if (mTree) mTree->RowCountChanged(0, -oldSize); // to use the search results cache, we'll need to iterate over the scopes in the // search session, calling getNthSearchScope for i = 0; i < searchSession.countSearchScopes; i++ // and for each folder, then open the db and pull out the cached hits, add them to the view. // For each hit in a new folder, we'll then clean up the stale hits from the previous folder(s). int32_t scopeCount; nsCOMPtr<nsIMsgSearchSession> searchSession = do_QueryReferent(m_searchSession); NS_ENSURE_TRUE(searchSession, NS_OK); // just ignore nsCOMPtr<nsIMsgDBService> msgDBService = do_GetService(NS_MSGDB_SERVICE_CONTRACTID); searchSession->CountSearchScopes(&scopeCount); // Figure out how many search terms the virtual folder has. nsCOMPtr<nsIMsgDatabase> virtDatabase; nsCOMPtr<nsIDBFolderInfo> dbFolderInfo; nsresult rv = m_viewFolder->GetDBFolderInfoAndDB(getter_AddRefs(dbFolderInfo), getter_AddRefs(virtDatabase)); NS_ENSURE_SUCCESS(rv, rv); nsCString terms; dbFolderInfo->GetCharProperty("searchStr", terms); nsCOMPtr<nsISupportsArray> searchTerms; rv = searchSession->GetSearchTerms(getter_AddRefs(searchTerms)); NS_ENSURE_SUCCESS(rv, rv); nsCString curSearchAsString; rv = MsgTermListToString(searchTerms, curSearchAsString); // Trim off the initial AND/OR, which is irrelevant and inconsistent between // what searchSpec.js generates, and what's in virtualFolders.dat. curSearchAsString.Cut(0, StringBeginsWith(curSearchAsString, NS_LITERAL_CSTRING("AND")) ? 3 : 2); terms.Cut(0, StringBeginsWith(terms, NS_LITERAL_CSTRING("AND")) ? 3 : 2); NS_ENSURE_SUCCESS(rv, rv); // If the search session search string doesn't match the vf search str, then we're doing // quick search, which means we don't want to invalidate cached results, or // used cached results. m_doingQuickSearch = !curSearchAsString.Equals(terms); if (mTree && !m_doingQuickSearch) mTree->BeginUpdateBatch(); for (int32_t i = 0; i < scopeCount; i++) { nsMsgSearchScopeValue scopeId; nsCOMPtr<nsIMsgFolder> searchFolder; searchSession->GetNthSearchScope(i, &scopeId, getter_AddRefs(searchFolder)); if (searchFolder) { nsCOMPtr<nsISimpleEnumerator> cachedHits; nsCOMPtr<nsIMsgDatabase> searchDB; nsCString searchUri; m_viewFolder->GetURI(searchUri); nsresult rv = searchFolder->GetMsgDatabase(getter_AddRefs(searchDB)); if (NS_SUCCEEDED(rv) && searchDB) { if (msgDBService) msgDBService->RegisterPendingListener(searchFolder, this); m_foldersSearchingOver.AppendObject(searchFolder); if (m_doingQuickSearch) // ignore cached hits in quick search case. continue; searchDB->GetCachedHits(searchUri.get(), getter_AddRefs(cachedHits)); bool hasMore; if (cachedHits) { cachedHits->HasMoreElements(&hasMore); if (hasMore) { nsMsgKey prevKey = nsMsgKey_None; while (hasMore) { nsCOMPtr <nsIMsgDBHdr> pHeader; nsresult rv = cachedHits->GetNext(getter_AddRefs(pHeader)); NS_ASSERTION(NS_SUCCEEDED(rv), "nsMsgDBEnumerator broken"); if (pHeader && NS_SUCCEEDED(rv)) { nsMsgKey msgKey; pHeader->GetMessageKey(&msgKey); NS_ASSERTION(prevKey == nsMsgKey_None || msgKey > prevKey, "cached Hits not sorted"); prevKey = msgKey; AddHdrFromFolder(pHeader, searchFolder); } else break; cachedHits->HasMoreElements(&hasMore); } } } } } } if (mTree && !m_doingQuickSearch) mTree->EndUpdateBatch(); m_curFolderStartKeyIndex = 0; m_curFolderGettingHits = nullptr; m_curFolderHasCachedHits = false; // if we have cached hits, sort them. if (GetSize() > 0) { // currently, we keep threaded views sorted while we build them. if (m_sortType != nsMsgViewSortType::byThread && !(m_viewFlags & nsMsgViewFlagsType::kThreadedDisplay)) { m_sortValid = false; //sort the results Sort(m_sortType, m_sortOrder); } } return NS_OK; }