diff --git a/mozilla/mailnews/base/public/nsIMsgDBView.idl b/mozilla/mailnews/base/public/nsIMsgDBView.idl index e8fd557ccdf..11d2fc0ac83 100644 --- a/mozilla/mailnews/base/public/nsIMsgDBView.idl +++ b/mozilla/mailnews/base/public/nsIMsgDBView.idl @@ -65,6 +65,7 @@ interface nsMsgViewType { const nsMsgViewTypeValue eShowThreadsWithUnread = 2; const nsMsgViewTypeValue eShowWatchedThreadsWithUnread = 3; const nsMsgViewTypeValue eShowQuickSearchResults = 4; + const nsMsgViewtypeValue eShowVirtualFolderResults = 5; }; [scriptable, uuid(64852276-1dd2-11b2-8103-afe12002c053)] @@ -266,7 +267,7 @@ interface nsIMsgDBView : nsISupports readonly attribute nsMsgViewSortTypeValue sortType; readonly attribute nsMsgViewSortOrderValue sortOrder; readonly attribute nsMsgKey keyForFirstSelectedMessage; - + readonly attribute nsMsgViewIndex viewIndexForFirstSelectedMsg; /** * this method will automatically expand the destination thread, * if needs be. @@ -290,6 +291,7 @@ interface nsIMsgDBView : nsISupports readonly attribute string URIForFirstSelectedMessage; readonly attribute nsIMsgDBHdr hdrForFirstSelectedMessage; void loadMessageByMsgKey(in nsMsgKey aMsgKey); + void loadMessageByViewIndex(in nsMsgViewIndex aIndex); void loadMessageByUrl(in string aUrl); void reloadMessage(); void reloadMessageWithAllParts(); diff --git a/mozilla/mailnews/base/src/Makefile.in b/mozilla/mailnews/base/src/Makefile.in index b425851a603..29d9ce5f716 100644 --- a/mozilla/mailnews/base/src/Makefile.in +++ b/mozilla/mailnews/base/src/Makefile.in @@ -114,6 +114,7 @@ CPPSRCS = \ nsMsgSpecialViews.cpp \ nsMsgQuickSearchDBView.cpp \ nsMsgSearchDBView.cpp \ + nsMsgXFVirtualFolderDBView.cpp \ nsMsgOfflineManager.cpp \ nsMsgProgress.cpp \ nsMessengerContentHandler.cpp \ diff --git a/mozilla/mailnews/base/src/nsMsgAccountManager.cpp b/mozilla/mailnews/base/src/nsMsgAccountManager.cpp index e40d23c2c15..b9bee765bb9 100644 --- a/mozilla/mailnews/base/src/nsMsgAccountManager.cpp +++ b/mozilla/mailnews/base/src/nsMsgAccountManager.cpp @@ -95,6 +95,8 @@ #include "nsIMsgHdr.h" #include "nsILineInputStream.h" #include "nsNetUtil.h" +#include "nsEscape.h" + #define PREF_MAIL_ACCOUNTMANAGER_ACCOUNTS "mail.accountmanager.accounts" #define PREF_MAIL_ACCOUNTMANAGER_DEFAULTACCOUNT "mail.accountmanager.defaultaccount" #define PREF_MAIL_ACCOUNTMANAGER_LOCALFOLDERSSERVER "mail.accountmanager.localfoldersserver" @@ -2632,30 +2634,32 @@ nsresult VirtualFolderChangeListener::Init() /** * nsIDBChangeListener */ -NS_IMETHODIMP VirtualFolderChangeListener::OnKeyChange(nsMsgKey aKeyChanged, PRUint32 aOldFlags, PRUint32 aNewFlags, nsIDBChangeListener *aInstigator) +NS_IMETHODIMP VirtualFolderChangeListener::OnHdrChange(nsIMsgDBHdr *aHdrChanged, PRUint32 aOldFlags, PRUint32 aNewFlags, nsIDBChangeListener *aInstigator) { nsCOMPtr msgDB; nsresult rv = m_folderWatching->GetMsgDatabase(nsnull, getter_AddRefs(msgDB)); - nsCOMPtr msgHdr; - rv = msgDB->GetMsgHdrForKey(aKeyChanged, getter_AddRefs(msgHdr)); - NS_ENSURE_SUCCESS(rv, rv); PRBool oldMatch = PR_FALSE, newMatch = PR_FALSE; - rv = m_searchSession->MatchHdr(msgHdr, msgDB, &newMatch); + rv = m_searchSession->MatchHdr(aHdrChanged, msgDB, &newMatch); NS_ENSURE_SUCCESS(rv, rv); if (m_searchOnMsgStatus) { // if status is a search criteria, check if the header matched before // it changed, in order to determine if we need to bump the counts. - msgHdr->SetFlags(aOldFlags); - rv = m_searchSession->MatchHdr(msgHdr, msgDB, &oldMatch); - msgHdr->SetFlags(aNewFlags); // restore new flags even on match failure. + aHdrChanged->SetFlags(aOldFlags); + rv = m_searchSession->MatchHdr(aHdrChanged, msgDB, &oldMatch); + aHdrChanged->SetFlags(aNewFlags); // restore new flags even on match failure. NS_ENSURE_SUCCESS(rv, rv); } else oldMatch = newMatch; // we don't want to change the total counts if this virtual folder is open in a view, - // because we won't remove the header from view while its open. + // because we won't remove the header from view while it's open. On the other hand, + // it's hard to fix the count when the user clicks away to another folder, w/o re-running + // the search, or setting some sort of pending count change. + // Maybe this needs to be handled in the view code...the view could do the same calculation + // and also keep track of the counts changed. Then, when the view was closed, if it's a virtual + // folder, it could update the counts for the db. if (oldMatch != newMatch || (oldMatch && (aOldFlags & MSG_FLAG_READ) != (aNewFlags & MSG_FLAG_READ))) { nsCOMPtr virtDatabase; @@ -2664,9 +2668,17 @@ NS_IMETHODIMP VirtualFolderChangeListener::OnKeyChange(nsMsgKey aKeyChanged, PRU rv = m_virtualFolder->GetDBFolderInfoAndDB(getter_AddRefs(dbFolderInfo), getter_AddRefs(virtDatabase)); PRInt32 totalDelta = 0, unreadDelta = 0; if (oldMatch != newMatch) - totalDelta = (oldMatch) ? -1 : 1; + { + // PRBool isOpen = PR_FALSE; +// nsCOMPtr mailSession = do_GetService(NS_MSGMAILSESSION_CONTRACTID); +// if (mailSession && aFolder) +// mailSession->IsFolderOpenInWindow(m_virtualFolder, &isOpen); + // we can't remove headers that no longer match - but we might add headers that newly match, someday. +// if (!isOpen) + totalDelta = (oldMatch) ? -1 : 1; + } PRBool msgHdrIsRead; - msgHdr->GetIsRead(&msgHdrIsRead); + aHdrChanged->GetIsRead(&msgHdrIsRead); if (oldMatch == newMatch) // read flag changed state unreadDelta = (msgHdrIsRead) ? -1 : 1; else if (oldMatch) // else header should removed @@ -2683,17 +2695,14 @@ NS_IMETHODIMP VirtualFolderChangeListener::OnKeyChange(nsMsgKey aKeyChanged, PRU return rv; } -NS_IMETHODIMP VirtualFolderChangeListener::OnKeyDeleted(nsMsgKey aKeyDeleted, nsMsgKey aParentKey, PRInt32 aFlags, nsIDBChangeListener *aInstigator) +NS_IMETHODIMP VirtualFolderChangeListener::OnHdrDeleted(nsIMsgDBHdr *aHdrDeleted, nsMsgKey aParentKey, PRInt32 aFlags, nsIDBChangeListener *aInstigator) { nsCOMPtr msgDB; nsresult rv = m_folderWatching->GetMsgDatabase(nsnull, getter_AddRefs(msgDB)); NS_ENSURE_SUCCESS(rv, rv); - nsCOMPtr msgHdr; - rv = msgDB->GetMsgHdrForKey(aKeyDeleted, getter_AddRefs(msgHdr)); - NS_ENSURE_SUCCESS(rv, rv); PRBool match = PR_FALSE; - rv = m_searchSession->MatchHdr(msgHdr, msgDB, &match); + rv = m_searchSession->MatchHdr(aHdrDeleted, msgDB, &match); if (match) { nsCOMPtr virtDatabase; @@ -2701,7 +2710,7 @@ NS_IMETHODIMP VirtualFolderChangeListener::OnKeyDeleted(nsMsgKey aKeyDeleted, ns nsresult rv = m_virtualFolder->GetDBFolderInfoAndDB(getter_AddRefs(dbFolderInfo), getter_AddRefs(virtDatabase)); PRBool msgHdrIsRead; - msgHdr->GetIsRead(&msgHdrIsRead); + aHdrDeleted->GetIsRead(&msgHdrIsRead); if (!msgHdrIsRead) dbFolderInfo->ChangeNumUnreadMessages(-1); dbFolderInfo->ChangeNumMessages(-1); @@ -2711,17 +2720,14 @@ NS_IMETHODIMP VirtualFolderChangeListener::OnKeyDeleted(nsMsgKey aKeyDeleted, ns return rv; } -NS_IMETHODIMP VirtualFolderChangeListener::OnKeyAdded(nsMsgKey aNewKey, nsMsgKey aParentKey, PRInt32 aFlags, nsIDBChangeListener *aInstigator) +NS_IMETHODIMP VirtualFolderChangeListener::OnHdrAdded(nsIMsgDBHdr *aNewHdr, nsMsgKey aParentKey, PRInt32 aFlags, nsIDBChangeListener *aInstigator) { nsCOMPtr msgDB; nsresult rv = m_folderWatching->GetMsgDatabase(nsnull, getter_AddRefs(msgDB)); NS_ENSURE_SUCCESS(rv, rv); - nsCOMPtr msgHdr; - rv = msgDB->GetMsgHdrForKey(aNewKey, getter_AddRefs(msgHdr)); - NS_ENSURE_SUCCESS(rv, rv); PRBool match = PR_FALSE; - rv = m_searchSession->MatchHdr(msgHdr, msgDB, &match); + rv = m_searchSession->MatchHdr(aNewHdr, msgDB, &match); if (match) { nsCOMPtr virtDatabase; @@ -2729,9 +2735,13 @@ NS_IMETHODIMP VirtualFolderChangeListener::OnKeyAdded(nsMsgKey aNewKey, nsMsgKey rv = m_virtualFolder->GetDBFolderInfoAndDB(getter_AddRefs(dbFolderInfo), getter_AddRefs(virtDatabase)); PRBool msgHdrIsRead; - msgHdr->GetIsRead(&msgHdrIsRead); + PRUint32 msgFlags; + aNewHdr->GetIsRead(&msgHdrIsRead); + aNewHdr->GetFlags(&msgFlags); if (!msgHdrIsRead) dbFolderInfo->ChangeNumUnreadMessages(1); + if (msgFlags & MSG_FLAG_NEW) + m_virtualFolder->SetHasNewMessages(PR_TRUE); dbFolderInfo->ChangeNumMessages(1); m_virtualFolder->UpdateSummaryTotals(true); // force update from db. virtDatabase->Commit(nsMsgDBCommitType::kLargeCommit); @@ -2746,11 +2756,10 @@ NS_IMETHODIMP VirtualFolderChangeListener::OnParentChanged(nsMsgKey aKeyChanged, NS_IMETHODIMP VirtualFolderChangeListener::OnAnnouncerGoingAway(nsIDBChangeAnnouncer *instigator) { - nsresult rv; - nsCOMPtr msgDBService = do_GetService(NS_MSGDB_SERVICE_CONTRACTID, &rv); - if (msgDBService) - msgDBService->UnregisterPendingListener(this); - return rv; + nsCOMPtr msgDB = do_QueryInterface(instigator); + if (msgDB) + msgDB->RemoveListener(this); + return NS_OK; } NS_IMETHODIMP VirtualFolderChangeListener::OnReadChanged(nsIDBChangeListener *aInstigator) @@ -2790,67 +2799,90 @@ nsresult nsMsgAccountManager::LoadVirtualFolders() nsCOMPtr fileStream = do_CreateInstance(NS_LOCALFILEINPUTSTREAM_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv, rv); - rv = fileStream->Init(file, PR_RDONLY, 0664, PR_FALSE); //just have to read the messages + rv = fileStream->Init(file, PR_RDONLY, 0664, PR_FALSE); nsCOMPtr lineInputStream(do_QueryInterface(fileStream)); PRBool isMore = PR_TRUE; nsCAutoString buffer; + PRInt32 version = -1; + nsCOMPtr virtualFolder; + nsCOMPtr dbFolderInfo; + nsCOMPtr resource; + nsCOMPtr rdf(do_GetService("@mozilla.org/rdf/rdf-service;1", &rv)); + NS_ENSURE_SUCCESS(rv, rv); while (isMore && NS_SUCCEEDED(lineInputStream->ReadLine(buffer, &isMore))) { if (buffer.Length() > 0) { - nsCOMPtr folder; - nsCOMPtr rdf(do_GetService("@mozilla.org/rdf/rdf-service;1", &rv)); - NS_ENSURE_SUCCESS(rv, rv); - - nsCOMPtr resource; - rv = rdf->GetResource(buffer, getter_AddRefs(resource)); - NS_ENSURE_SUCCESS(rv, rv); - - folder = do_QueryInterface(resource, &rv); - NS_ENSURE_SUCCESS(rv, rv); - if (folder) + if (version == -1) { - // need to add the folder as a sub-folder of its parent. - PRInt32 lastSlash = buffer.RFindChar('/'); - nsDependentCSubstring parentUri(buffer, 0, lastSlash); - rdf->GetResource(parentUri, getter_AddRefs(resource)); - nsCOMPtr parentFolder = do_QueryInterface(resource); - if (parentFolder) - { - nsCOMPtr childFolder; - nsAutoString currentFolderNameStr; - CopyUTF8toUTF16(Substring(buffer, lastSlash + 1, buffer.Length()), currentFolderNameStr); - rv = parentFolder->AddSubfolder(currentFolderNameStr, getter_AddRefs(childFolder)); - if (!childFolder) - childFolder = folder; // or just use folder? + buffer.Cut(0, 8); + PRInt32 irv; + version = buffer.ToInteger(&irv); + continue; + } + if (Substring(buffer, 0, 4).Equals("uri=")) + { + buffer.Cut(0, 4); - nsCOMPtr db; - childFolder->GetMsgDatabase(nsnull, getter_AddRefs(db)); // force db to get created. - nsCOMPtr dbFolderInfo; - rv = db->GetDBFolderInfo(getter_AddRefs(dbFolderInfo)); - childFolder->SetFlag(MSG_FOLDER_FLAG_VIRTUAL); - nsXPIDLCString realFolderUri; - dbFolderInfo->GetCharPtrProperty("searchFolderUri", getter_Copies(realFolderUri)); - // if we supported cross folder virtual folders, we'd have a list of folders uris, - // and we'd have to add a pending listener for each of them. - if (realFolderUri.Length()) + rv = rdf->GetResource(buffer, getter_AddRefs(resource)); + NS_ENSURE_SUCCESS(rv, rv); + + virtualFolder = do_QueryInterface(resource, &rv); + NS_ENSURE_SUCCESS(rv, rv); + if (virtualFolder) + { + // need to add the folder as a sub-folder of its parent. + PRInt32 lastSlash = buffer.RFindChar('/'); + nsDependentCSubstring parentUri(buffer, 0, lastSlash); + rdf->GetResource(parentUri, getter_AddRefs(resource)); + nsCOMPtr parentFolder = do_QueryInterface(resource); + if (parentFolder) { - // we need to load the db for the actual folder so that many hdrs to download - // will return false... - rdf->GetResource(realFolderUri, getter_AddRefs(resource)); + nsAutoString currentFolderNameStr; + nsCAutoString currentFolderNameCStr(Substring(buffer, lastSlash + 1, buffer.Length())); + nsUnescape(currentFolderNameCStr.BeginWriting()); + CopyUTF8toUTF16(currentFolderNameCStr, currentFolderNameStr); + nsCOMPtr childFolder; + rv = parentFolder->AddSubfolder(currentFolderNameStr, getter_AddRefs(childFolder)); + + nsCOMPtr db; + virtualFolder->GetMsgDatabase(nsnull, getter_AddRefs(db)); // force db to get created. + rv = db->GetDBFolderInfo(getter_AddRefs(dbFolderInfo)); + virtualFolder->SetFlag(MSG_FOLDER_FLAG_VIRTUAL); + } + } + } + else if (Substring(buffer, 0, 6).Equals("scope=")) + { + buffer.Cut(0, 6); + // if this is a cross folder virtual folder, we have a list of folders uris, + // and we have to add a pending listener for each of them. + if (buffer.Length()) + { + nsCStringArray folderUris; + dbFolderInfo->SetCharPtrProperty("searchFolderUri", buffer.get()); + folderUris.ParseString(buffer.get(), "|"); + for (PRInt32 i = 0; i < folderUris.Count(); i++) + { + rdf->GetResource(*(folderUris[i]), getter_AddRefs(resource)); nsCOMPtr realFolder = do_QueryInterface(resource); VirtualFolderChangeListener *dbListener = new VirtualFolderChangeListener(); m_virtualFolderListeners.AppendObject(dbListener); - dbListener->m_virtualFolder = childFolder; + dbListener->m_virtualFolder = virtualFolder; dbListener->m_folderWatching = realFolder; dbListener->Init(); msgDBService->RegisterPendingListener(realFolder, dbListener); } } } + else if (Substring(buffer, 0, 6).Equals("terms=")) + { + buffer.Cut(0, 6); + dbFolderInfo->SetCharPtrProperty("searchStr", buffer.get()); + } } } } @@ -2894,13 +2926,24 @@ NS_IMETHODIMP nsMsgAccountManager::SaveVirtualFolders() file, PR_CREATE_FILE | PR_WRONLY | PR_TRUNCATE, 0664); + NS_ENSURE_SUCCESS(rv, rv); + WriteLineToOutputStream("version=", "1", outputStream); + } nsCOMPtr folderRes (do_QueryElementAt(virtualFolders, folderIndex)); + nsCOMPtr msgFolder = do_QueryInterface(folderRes); const char *uri; + nsCOMPtr db; + nsCOMPtr dbFolderInfo; + rv = msgFolder->GetDBFolderInfoAndDB(getter_AddRefs(dbFolderInfo), getter_AddRefs(db)); // force db to get created. + nsXPIDLCString srchFolderUri; + nsXPIDLCString searchTerms; + dbFolderInfo->GetCharPtrProperty("searchFolderUri", getter_Copies(srchFolderUri)); + dbFolderInfo->GetCharPtrProperty("searchStr", getter_Copies(searchTerms)); folderRes->GetValueConst(&uri); - PRUint32 writeCount; - outputStream->Write(uri, strlen(uri), &writeCount); - outputStream->Write("\n", 1, &writeCount); + WriteLineToOutputStream("uri=", uri, outputStream); + WriteLineToOutputStream("scope=", srchFolderUri.get(), outputStream); + WriteLineToOutputStream("terms=", searchTerms.get(), outputStream); } } } @@ -2911,6 +2954,14 @@ NS_IMETHODIMP nsMsgAccountManager::SaveVirtualFolders() return rv; } +nsresult nsMsgAccountManager::WriteLineToOutputStream(const char *prefix, const char * line, nsIOutputStream *outputStream) +{ + PRUint32 writeCount; + outputStream->Write(prefix, strlen(prefix), &writeCount); + outputStream->Write(line, strlen(line), &writeCount); + outputStream->Write("\n", 1, &writeCount); + return NS_OK; +} NS_IMETHODIMP nsMsgAccountManager::OnItemAdded(nsIRDFResource *parentItem, nsISupports *item) { @@ -2933,7 +2984,6 @@ NS_IMETHODIMP nsMsgAccountManager::OnItemAdded(nsIRDFResource *parentItem, nsISu nsCOMPtr virtDatabase; nsCOMPtr dbFolderInfo; m_virtualFolderListeners.AppendObject(dbListener); - rv = folder->GetDBFolderInfoAndDB(getter_AddRefs(dbFolderInfo), getter_AddRefs(virtDatabase)); NS_ENSURE_SUCCESS(rv, rv); nsXPIDLCString srchFolderUri; @@ -2942,7 +2992,10 @@ NS_IMETHODIMP nsMsgAccountManager::OnItemAdded(nsIRDFResource *parentItem, nsISu // and we'd have to add a pending listener for each of them. rv = GetExistingFolder(srchFolderUri.get(), getter_AddRefs(dbListener->m_folderWatching)); if (dbListener->m_folderWatching) + { + dbListener->Init(); msgDBService->RegisterPendingListener(dbListener->m_folderWatching, dbListener); + } } rv = SaveVirtualFolders(); } diff --git a/mozilla/mailnews/base/src/nsMsgAccountManager.h b/mozilla/mailnews/base/src/nsMsgAccountManager.h index 0a87aff0c94..0eccbaf7397 100644 --- a/mozilla/mailnews/base/src/nsMsgAccountManager.h +++ b/mozilla/mailnews/base/src/nsMsgAccountManager.h @@ -204,6 +204,7 @@ private: // handle virtual folders nsresult GetVirtualFoldersFile(nsCOMPtr& file); nsresult LoadVirtualFolders(); + nsresult WriteLineToOutputStream(const char *prefix, const char * line, nsIOutputStream *outputStream); static void getUniqueKey(const char* prefix, nsHashtable *hashTable, diff --git a/mozilla/mailnews/base/src/nsMsgBaseCID.h b/mozilla/mailnews/base/src/nsMsgBaseCID.h index 4f4b06b752d..e048e3bcd27 100644 --- a/mozilla/mailnews/base/src/nsMsgBaseCID.h +++ b/mozilla/mailnews/base/src/nsMsgBaseCID.h @@ -406,6 +406,8 @@ #define NS_MSGQUICKSEARCHDBVIEW_CONTRACTID \ NS_MSGDBVIEW_CONTRACTID_PREFIX "quicksearch" +#define NS_MSGXFVFDBVIEW_CONTRACTID \ + NS_MSGDBVIEW_CONTRACTID_PREFIX "xfvf" /* 52f860e0-1dd2-11b2-aa72-bb751981bd00 */ #define NS_MSGTHREADEDDBVIEW_CID \ @@ -432,6 +434,10 @@ {0x2dd9d0fe, 0xb609, 0x11d6, \ {0xba, 0xcc, 0x00, 0x10, 0x83, 0x35, 0x74, 0x8d}} +/* 2af6e050-04f6-495a-8387-86b0aeb1863c */ +#define NS_MSG_XFVFDBVIEW_CID \ + {0x2af6e050, 0x04f6, 0x495a, \ + {0x83, 0x87, 0x86, 0xb0, 0xae, 0xb1, 0x86, 0x3c}} // // nsMsgAccountManager // diff --git a/mozilla/mailnews/base/src/nsMsgDBView.cpp b/mozilla/mailnews/base/src/nsMsgDBView.cpp index b4ee4911da6..c3d7f485c1c 100644 --- a/mozilla/mailnews/base/src/nsMsgDBView.cpp +++ b/mozilla/mailnews/base/src/nsMsgDBView.cpp @@ -134,6 +134,7 @@ nsMsgDBView::nsMsgDBView() m_viewFlags = nsMsgViewFlagsType::kNone; m_cachedMsgKey = nsMsgKey_None; m_currentlyDisplayedMsgKey = nsMsgKey_None; + m_currentlyDisplayedViewIndex = nsMsgViewIndex_None; mNumSelectedRows = 0; mSuppressMsgDisplay = PR_FALSE; mSuppressCommandUpdating = PR_FALSE; @@ -877,7 +878,7 @@ nsresult nsMsgDBView::RestoreSelection(nsMsgKey aCurrentMsgKey, nsMsgKeyArray *a nsresult nsMsgDBView::GenerateURIForMsgKey(nsMsgKey aMsgKey, nsIMsgFolder *folder, char ** aURI) { NS_ENSURE_ARG(folder); - return(folder->GenerateMessageURI(aMsgKey, aURI)); + return(folder->GenerateMessageURI(aMsgKey, aURI)); } nsresult nsMsgDBView::CycleThreadedColumn(nsIDOMElement * aElement) @@ -952,29 +953,32 @@ NS_IMETHODIMP nsMsgDBView::ReloadMessage() nsresult nsMsgDBView::ReloadMessageHelper(PRBool forceAllParts) { - if (!mSuppressMsgDisplay && m_currentlyDisplayedMsgKey != nsMsgKey_None) + if (!mSuppressMsgDisplay && m_currentlyDisplayedViewIndex != nsMsgViewIndex_None) { - nsMsgKey currentMsgToReload = m_currentlyDisplayedMsgKey; + nsMsgKey currentMsgToReload = m_currentlyDisplayedViewIndex; m_currentlyDisplayedMsgKey = nsMsgKey_None; - LoadMessageByMsgKeyHelper(currentMsgToReload, forceAllParts); + m_currentlyDisplayedViewIndex = nsMsgViewIndex_None; + LoadMessageByViewIndexHelper(m_currentlyDisplayedViewIndex, forceAllParts); } return NS_OK; } -nsresult nsMsgDBView::UpdateDisplayMessage(nsMsgKey aMsgKey) +nsresult nsMsgDBView::UpdateDisplayMessage(nsMsgViewIndex viewPosition) { nsresult rv; if (mCommandUpdater) { // get the subject and the folder for the message and inform the front end that // we changed the message we are currently displaying. - nsMsgViewIndex viewPosition = FindViewIndex(aMsgKey); if (viewPosition != nsMsgViewIndex_None) { nsCOMPtr msgHdr; rv = GetMsgHdrForViewIndex(viewPosition, getter_AddRefs(msgHdr)); NS_ENSURE_SUCCESS(rv,rv); + nsCOMPtr folder; + GetMsgFolder(getter_AddRefs(folder)); + nsXPIDLString subject; FetchSubject(msgHdr, m_flags[viewPosition], getter_Copies(subject)); @@ -982,11 +986,11 @@ nsresult nsMsgDBView::UpdateDisplayMessage(nsMsgKey aMsgKey) rv = msgHdr->GetStringProperty("keywords", getter_Copies(keywords)); NS_ENSURE_SUCCESS(rv,rv); - mCommandUpdater->DisplayMessageChanged(m_folder, subject, keywords); + mCommandUpdater->DisplayMessageChanged(folder, subject, keywords); if (m_folder) { - rv = m_folder->SetLastMessageLoaded(aMsgKey); + rv = m_folder->SetLastMessageLoaded(m_keys[viewPosition]); NS_ENSURE_SUCCESS(rv,rv); } } // if view position is valid @@ -997,26 +1001,46 @@ nsresult nsMsgDBView::UpdateDisplayMessage(nsMsgKey aMsgKey) // given a msg key, we will load the message for it. NS_IMETHODIMP nsMsgDBView::LoadMessageByMsgKey(nsMsgKey aMsgKey) { - return LoadMessageByMsgKeyHelper(aMsgKey, PR_FALSE); + return LoadMessageByViewIndexHelper(FindViewIndex(aMsgKey), PR_FALSE); } -nsresult nsMsgDBView::LoadMessageByMsgKeyHelper(nsMsgKey aMsgKey, PRBool forceAllParts) +NS_IMETHODIMP nsMsgDBView::LoadMessageByViewIndex(nsMsgViewIndex aViewIndex) { - NS_ASSERTION(aMsgKey != nsMsgKey_None,"trying to load nsMsgKey_None"); - if (aMsgKey == nsMsgKey_None) return NS_ERROR_UNEXPECTED; + NS_ASSERTION(aViewIndex != nsMsgViewIndex_None,"trying to load nsMsgViewIndex_None"); + if (aViewIndex == nsMsgViewIndex_None) return NS_ERROR_UNEXPECTED; - if (!mSuppressMsgDisplay && (m_currentlyDisplayedMsgKey != aMsgKey)) + nsXPIDLCString uri; + nsresult rv = GetURIForViewIndex(aViewIndex, getter_Copies(uri)); + if (!mSuppressMsgDisplay && !m_currentlyDisplayedMsgUri.Equals(uri)) + { + NS_ENSURE_SUCCESS(rv,rv); + + mMessengerInstance->OpenURL(uri); + m_currentlyDisplayedMsgKey = m_keys[aViewIndex]; + m_currentlyDisplayedMsgUri = uri; + m_currentlyDisplayedViewIndex = aViewIndex; + UpdateDisplayMessage(m_currentlyDisplayedViewIndex); + } + return NS_OK; +} + +nsresult nsMsgDBView::LoadMessageByViewIndexHelper(nsMsgViewIndex aViewIndex, PRBool forceAllParts) +{ + NS_ASSERTION(aViewIndex != nsMsgViewIndex_None,"trying to load nsMsgViewIndex_None"); + if (aViewIndex == nsMsgViewIndex_None) return NS_ERROR_UNEXPECTED; + + if (!mSuppressMsgDisplay && (m_currentlyDisplayedViewIndex != aViewIndex)) { nsXPIDLCString uri; - nsresult rv = GenerateURIForMsgKey(aMsgKey, m_folder, getter_Copies(uri)); + nsresult rv = GetURIForViewIndex(aViewIndex, getter_Copies(uri)); NS_ENSURE_SUCCESS(rv,rv); if (forceAllParts) - { uri.Append("?fetchCompleteMessage=true"); - } + mMessengerInstance->OpenURL(uri); - m_currentlyDisplayedMsgKey = aMsgKey; - UpdateDisplayMessage(aMsgKey); + m_currentlyDisplayedMsgKey = m_keys[aViewIndex]; + m_currentlyDisplayedViewIndex = aViewIndex; + UpdateDisplayMessage(aViewIndex); } return NS_OK; @@ -1061,14 +1085,12 @@ NS_IMETHODIMP nsMsgDBView::SelectionChanged() if (startRange >= 0 && startRange == endRange && startRange < GetSize()) { - // get the msgkey for the message - nsMsgKey msgkey = m_keys.GetAt(startRange); if (!mRemovingRow) { if (!mSuppressMsgDisplay) - LoadMessageByMsgKey(msgkey); + LoadMessageByViewIndex(startRange); else - UpdateDisplayMessage(msgkey); + UpdateDisplayMessage(startRange); } } else @@ -1857,6 +1879,7 @@ NS_IMETHODIMP nsMsgDBView::GetSuppressCommandUpdating(PRBool * aSuppressCommandU NS_IMETHODIMP nsMsgDBView::SetSuppressMsgDisplay(PRBool aSuppressDisplay) { + nsresult rv = NS_OK; PRBool forceDisplay = PR_FALSE; if (mSuppressMsgDisplay && (mSuppressMsgDisplay != aSuppressDisplay)) forceDisplay = PR_TRUE; @@ -1864,19 +1887,14 @@ NS_IMETHODIMP nsMsgDBView::SetSuppressMsgDisplay(PRBool aSuppressDisplay) mSuppressMsgDisplay = aSuppressDisplay; if (forceDisplay) { - // get the messae key for the currently selected message - nsMsgKey msgKey; - nsCOMPtr dbHdr; - GetHdrForFirstSelectedMessage(getter_AddRefs(dbHdr)); - if (dbHdr) - { - nsresult rv = dbHdr->GetMessageKey(&msgKey); - if (NS_SUCCEEDED(rv)) - LoadMessageByMsgKey(msgKey); - } + // get the view indexfor the currently selected message + nsMsgViewIndex viewIndex; + rv = GetViewIndexForFirstSelectedMsg(&viewIndex); + if (NS_SUCCEEDED(rv) && viewIndex != nsMsgViewIndex_None) + LoadMessageByViewIndex(viewIndex); } - return NS_OK; + return rv; } NS_IMETHODIMP nsMsgDBView::GetSuppressMsgDisplay(PRBool * aSuppressDisplay) @@ -1960,13 +1978,12 @@ NS_IMETHODIMP nsMsgDBView::GetURIForViewIndex(nsMsgViewIndex index, char **resul { nsresult rv; nsCOMPtr folder = m_folder; - if (!folder) { + if (!folder) + { rv = GetFolderForViewIndex(index, getter_AddRefs(folder)); NS_ENSURE_SUCCESS(rv,rv); } - rv = GenerateURIForMsgKey(m_keys[index], folder, result); - NS_ENSURE_SUCCESS(rv,rv); - return NS_OK; + return GenerateURIForMsgKey(m_keys[index], folder, result); } NS_IMETHODIMP nsMsgDBView::DoCommandWithFolder(nsMsgViewCommandTypeValue command, nsIMsgFolder *destFolder) @@ -2281,14 +2298,16 @@ nsMsgDBView::ApplyCommandToIndices(nsMsgViewCommandTypeValue command, nsMsgViewI if (numIndices == 0) return NS_OK; // return quietly, just in case + nsCOMPtr folder; + nsresult rv = GetFolderForViewIndex(indices[0], getter_AddRefs(folder)); + if (command == nsMsgViewCommandType::deleteMsg) return DeleteMessages(mMsgWindow, indices, numIndices, PR_FALSE); if (command == nsMsgViewCommandType::deleteNoTrash) return DeleteMessages(mMsgWindow, indices, numIndices, PR_TRUE); nsMsgKeyArray imapUids; - nsresult rv = NS_OK; - nsCOMPtr imapFolder = do_QueryInterface(m_folder); + nsCOMPtr imapFolder = do_QueryInterface(folder); PRBool thisIsImapFolder = (imapFolder != nsnull); nsCOMPtr junkPlugin; @@ -2302,8 +2321,6 @@ nsMsgDBView::ApplyCommandToIndices(nsMsgViewCommandTypeValue command, nsMsgViewI // more junk status column in the 'search messages' dialog // like in earlier versions...) // - nsCOMPtr folder; - rv = GetFolderForViewIndex(indices[0], getter_AddRefs(folder)); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr server; @@ -2345,7 +2362,7 @@ nsMsgDBView::ApplyCommandToIndices(nsMsgViewCommandTypeValue command, nsMsgViewI mNumMessagesRemainingInBatch += numIndices; } - m_folder->EnableNotifications(nsIMsgFolder::allMessageCountNotifications, PR_FALSE, PR_TRUE /*dbBatching*/); + folder->EnableNotifications(nsIMsgFolder::allMessageCountNotifications, PR_FALSE, PR_TRUE /*dbBatching*/); for (int32 i = 0; i < numIndices; i++) { @@ -2396,7 +2413,7 @@ nsMsgDBView::ApplyCommandToIndices(nsMsgViewCommandTypeValue command, nsMsgViewI } } - m_folder->EnableNotifications(nsIMsgFolder::allMessageCountNotifications, PR_TRUE, PR_TRUE /*dbBatching*/); + folder->EnableNotifications(nsIMsgFolder::allMessageCountNotifications, PR_TRUE, PR_TRUE /*dbBatching*/); if (thisIsImapFolder) { @@ -3793,6 +3810,13 @@ NS_IMETHODIMP nsMsgDBView::GetKeyAt(nsMsgViewIndex index, nsMsgKey *result) return NS_OK; } +nsMsgViewIndex nsMsgDBView::FindHdr(nsIMsgDBHdr *msgHdr) +{ + nsMsgKey msgKey; + msgHdr->GetMessageKey(&msgKey); + return FindViewIndex(msgKey); +} + nsMsgKey nsMsgDBView::GetAt(nsMsgViewIndex index) { if (index >= m_keys.GetSize() || index == nsMsgViewIndex_None) @@ -4094,20 +4118,14 @@ nsresult nsMsgDBView::CollapseByIndex(nsMsgViewIndex index, PRUint32 *pNumCollap return rv; } -nsresult nsMsgDBView::OnNewHeader(nsMsgKey newKey, nsMsgKey aParentKey, PRBool /*ensureListed*/) +nsresult nsMsgDBView::OnNewHeader(nsIMsgDBHdr *newHdr, nsMsgKey aParentKey, PRBool /*ensureListed*/) { - nsresult rv = NS_MSG_MESSAGE_NOT_FOUND; + nsresult rv = NS_OK; // views can override this behaviour, which is to append to view. // This is the mail behaviour, but threaded views will want // to insert in order... - nsCOMPtr msgHdr; - NS_ASSERTION(m_db, "m_db is null"); - if (m_db) - rv = m_db->GetMsgHdrForKey(newKey, getter_AddRefs(msgHdr)); - if (NS_SUCCEEDED(rv) && msgHdr != nsnull) - { - rv = AddHdr(msgHdr); - } + if (newHdr) + rv = AddHdr(newHdr); return rv; } @@ -4555,13 +4573,15 @@ nsresult nsMsgDBView::ListUnreadIdsInThread(nsIMsgThread *threadHdr, nsMsgViewIn return NS_OK; } -NS_IMETHODIMP nsMsgDBView::OnKeyChange(nsMsgKey aKeyChanged, PRUint32 aOldFlags, +NS_IMETHODIMP nsMsgDBView::OnHdrChange(nsIMsgDBHdr *aHdrChanged, PRUint32 aOldFlags, PRUint32 aNewFlags, nsIDBChangeListener *aInstigator) { // if we're not the instigator, update flags if this key is in our view if (aInstigator != this) { - nsMsgViewIndex index = FindViewIndex(aKeyChanged); + nsMsgKey msgKey; + aHdrChanged->GetMessageKey(&msgKey); + nsMsgViewIndex index = FindViewIndex(msgKey); if (index != nsMsgViewIndex_None) { PRUint32 viewOnlyFlags = m_flags[index] & (MSG_VIEW_FLAGS | MSG_FLAG_ELIDED); @@ -4578,30 +4598,30 @@ NS_IMETHODIMP nsMsgDBView::OnKeyChange(nsMsgKey aKeyChanged, PRUint32 aOldFlags, PRUint32 deltaFlags = (aOldFlags ^ aNewFlags); if (deltaFlags & (MSG_FLAG_READ | MSG_FLAG_NEW)) { - nsMsgViewIndex threadIndex = ThreadIndexOfMsg(aKeyChanged); + nsMsgViewIndex threadIndex = ThreadIndexOfMsg(msgKey); // may need to fix thread counts if (threadIndex != nsMsgViewIndex_None && threadIndex != index) NoteChange(threadIndex, 1, nsMsgViewNotificationCode::changed); } - } + } // don't need to propagate notifications, right? return NS_OK; } -NS_IMETHODIMP nsMsgDBView::OnKeyDeleted(nsMsgKey aKeyChanged, nsMsgKey aParentKey, PRInt32 aFlags, +NS_IMETHODIMP nsMsgDBView::OnHdrDeleted(nsIMsgDBHdr *aHdrChanged, nsMsgKey aParentKey, PRInt32 aFlags, nsIDBChangeListener *aInstigator) { - nsMsgViewIndex deletedIndex = m_keys.FindIndex(aKeyChanged); + nsMsgViewIndex deletedIndex = FindHdr(aHdrChanged); if (deletedIndex != nsMsgViewIndex_None) RemoveByIndex(deletedIndex); return NS_OK; } -NS_IMETHODIMP nsMsgDBView::OnKeyAdded(nsMsgKey aKeyChanged, nsMsgKey aParentKey, PRInt32 aFlags, +NS_IMETHODIMP nsMsgDBView::OnHdrAdded(nsIMsgDBHdr *aHdrChanged, nsMsgKey aParentKey, PRInt32 aFlags, nsIDBChangeListener *aInstigator) { - return OnNewHeader(aKeyChanged, aParentKey, PR_FALSE); + return OnNewHeader(aHdrChanged, aParentKey, PR_FALSE); // probably also want to pass that parent key in, since we went to the trouble // of figuring out what it is. } @@ -5575,14 +5595,12 @@ nsMsgDBView::GetURIForFirstSelectedMessage(char **uri) printf("inside GetURIForFirstSelectedMessage\n"); #endif nsresult rv; - nsMsgKey key; - rv = GetKeyForFirstSelectedMessage(&key); + nsMsgViewIndex viewIndex; + rv = GetViewIndexForFirstSelectedMsg(&viewIndex); // don't assert, it is legal for nothing to be selected if (NS_FAILED(rv)) return rv; - rv = GenerateURIForMsgKey(key, m_folder, uri); - NS_ENSURE_SUCCESS(rv,rv); - return NS_OK; + return GetURIForViewIndex(viewIndex, uri); } NS_IMETHODIMP @@ -5640,6 +5658,31 @@ PRBool nsMsgDBView::OfflineMsgSelected(nsMsgViewIndex * indices, PRInt32 numIndi return PR_FALSE; } +NS_IMETHODIMP nsMsgDBView::GetViewIndexForFirstSelectedMsg(nsMsgViewIndex *aViewIndex) +{ + NS_ENSURE_ARG_POINTER(aViewIndex); + // if we don't have an tree selection we must be in stand alone mode.... + if (!mTreeSelection) + { + *aViewIndex = m_currentlyDisplayedViewIndex; + return NS_OK; + } + + PRInt32 startRange; + PRInt32 endRange; + nsresult rv = mTreeSelection->GetRangeAt(0, &startRange, &endRange); + // don't assert, it is legal for nothing to be selected + if (NS_FAILED(rv)) + return rv; + + // check that the first index is valid, it may not be if nothing is selected + if (startRange >= 0 && startRange < GetSize()) + *aViewIndex = startRange; + else + return NS_ERROR_UNEXPECTED; + return NS_OK; +} + NS_IMETHODIMP nsMsgDBView::GetKeyForFirstSelectedMessage(nsMsgKey *key) { diff --git a/mozilla/mailnews/base/src/nsMsgDBView.h b/mozilla/mailnews/base/src/nsMsgDBView.h index 73b6bef2ca1..6f424a99320 100644 --- a/mozilla/mailnews/base/src/nsMsgDBView.h +++ b/mozilla/mailnews/base/src/nsMsgDBView.h @@ -189,7 +189,7 @@ protected: virtual PRBool WantsThisThread(nsIMsgThread * thread); virtual nsresult AddHdr(nsIMsgDBHdr *msgHdr); PRBool GetShowingIgnored() {return (m_viewFlags & nsMsgViewFlagsType::kShowIgnored) != 0;} - virtual nsresult OnNewHeader(nsMsgKey newKey, nsMsgKey parentKey, PRBool ensureListed); + virtual nsresult OnNewHeader(nsIMsgDBHdr *aNewHdr, nsMsgKey parentKey, PRBool ensureListed); virtual nsMsgViewIndex GetInsertIndex(nsIMsgDBHdr *msgHdr); nsMsgViewIndex GetIndexForThread(nsIMsgDBHdr *hdr); virtual nsresult GetThreadContainingIndex(nsMsgViewIndex index, nsIMsgThread **thread); @@ -207,9 +207,9 @@ protected: nsMsgViewIndex GetIndexOfFirstDisplayedKeyInThread(nsIMsgThread *threadHdr); nsresult GetFirstMessageHdrToDisplayInThread(nsIMsgThread *threadHdr, nsIMsgDBHdr **result); nsMsgViewIndex ThreadIndexOfMsg(nsMsgKey msgKey, - nsMsgViewIndex msgIndex = nsMsgViewIndex_None, - PRInt32 *pThreadCount = nsnull, - PRUint32 *pFlags = nsnull); + nsMsgViewIndex msgIndex = nsMsgViewIndex_None, + PRInt32 *pThreadCount = nsnull, + PRUint32 *pFlags = nsnull); nsMsgKey GetKeyOfFirstMsgInThread(nsMsgKey key); PRInt32 CountExpandedThread(nsMsgViewIndex index); nsresult ExpansionDelta(nsMsgViewIndex index, PRInt32 *expansionDelta); @@ -220,6 +220,7 @@ protected: nsMsgKey GetAt(nsMsgViewIndex index) ; nsMsgViewIndex FindViewIndex(nsMsgKey key) {return (nsMsgViewIndex) (m_keys.FindIndex(key));} + nsMsgViewIndex FindHdr(nsIMsgDBHdr *msgHdr); virtual nsMsgViewIndex FindKey(nsMsgKey key, PRBool expand); virtual nsresult GetDBForViewIndex(nsMsgViewIndex index, nsIMsgDatabase **db); virtual nsresult GetFolders(nsISupportsArray **folders); @@ -305,8 +306,8 @@ protected: void InitializeAtomsAndLiterals(); PRInt32 FindLevelInThread(nsIMsgDBHdr *msgHdr, nsMsgViewIndex startOfThread, nsMsgViewIndex viewIndex); nsresult GetImapDeleteModel(nsIMsgFolder *folder); - nsresult UpdateDisplayMessage(nsMsgKey aMsgKey); - nsresult LoadMessageByMsgKeyHelper(nsMsgKey aMsgKey, PRBool forceAllParts); + nsresult UpdateDisplayMessage(nsMsgViewIndex viewPosition); + nsresult LoadMessageByViewIndexHelper(nsMsgViewIndex aViewIndex, PRBool forceAllParts); nsresult ReloadMessageHelper(PRBool forceAllParts); PRBool AdjustReadFlag(nsIMsgDBHdr *msgHdr, PRUint32 *msgFlags); @@ -324,6 +325,8 @@ protected: // we need to store the message key for the message we are currenty displaying to ensure we // don't try to redisplay the same message just because the selection changed (i.e. after a sort) nsMsgKey m_currentlyDisplayedMsgKey; + nsCString m_currentlyDisplayedMsgUri; + nsMsgViewIndex m_currentlyDisplayedViewIndex; // if we're deleting messages, we want to hold off loading messages on selection changed until the delete is done // and we want to batch notifications. PRPackedBool m_deletingRows; diff --git a/mozilla/mailnews/base/src/nsMsgQuickSearchDBView.cpp b/mozilla/mailnews/base/src/nsMsgQuickSearchDBView.cpp index 34926bff666..2fe4df14821 100644 --- a/mozilla/mailnews/base/src/nsMsgQuickSearchDBView.cpp +++ b/mozilla/mailnews/base/src/nsMsgQuickSearchDBView.cpp @@ -89,40 +89,35 @@ NS_IMETHODIMP nsMsgQuickSearchDBView::GetViewType(nsMsgViewTypeValue *aViewType) return NS_OK; } -nsresult nsMsgQuickSearchDBView::OnNewHeader(nsMsgKey newKey, nsMsgKey aParentKey, PRBool ensureListed) +nsresult nsMsgQuickSearchDBView::OnNewHeader(nsIMsgDBHdr *newHdr, nsMsgKey aParentKey, PRBool ensureListed) { - nsresult rv; - nsCOMPtr msgHdr; - rv = m_db->GetMsgHdrForKey(newKey, getter_AddRefs(msgHdr)); - if (NS_SUCCEEDED(rv) && msgHdr != nsnull) + if (newHdr) { PRBool match=PR_FALSE; nsCOMPtr searchSession = do_QueryReferent(m_searchSession); if (searchSession) - searchSession->MatchHdr(msgHdr, m_db, &match); + searchSession->MatchHdr(newHdr, m_db, &match); if (match) - AddHdr(msgHdr); // do not add a new message if there isn't a match. + AddHdr(newHdr); // do not add a new message if there isn't a match. } return NS_OK; } -NS_IMETHODIMP nsMsgQuickSearchDBView::OnKeyChange(nsMsgKey aKeyChanged, PRUint32 aOldFlags, +NS_IMETHODIMP nsMsgQuickSearchDBView::OnHdrChange(nsIMsgDBHdr *aHdrChanged, PRUint32 aOldFlags, PRUint32 aNewFlags, nsIDBChangeListener *aInstigator) { - nsresult rv = nsMsgDBView::OnKeyChange(aKeyChanged, aOldFlags, aNewFlags, aInstigator); + nsresult rv = nsMsgDBView::OnHdrChange(aHdrChanged, aOldFlags, aNewFlags, aInstigator); // flags haven't really changed - check if the message is newly classified as junk if ((aOldFlags == aNewFlags) && (aOldFlags & MSG_FLAG_NEW)) { - nsCOMPtr msgHdr; - rv = m_db->GetMsgHdrForKey(aKeyChanged, getter_AddRefs(msgHdr)); - if (NS_SUCCEEDED(rv) && msgHdr != nsnull) + if (aHdrChanged) { nsXPIDLCString junkScoreStr; - (void) msgHdr->GetStringProperty("junkscore", getter_Copies(junkScoreStr)); + (void) aHdrChanged->GetStringProperty("junkscore", getter_Copies(junkScoreStr)); if (atoi(junkScoreStr.get()) > 50) { nsXPIDLCString originStr; - (void) msgHdr->GetStringProperty("junkscoreorigin", + (void) aHdrChanged->GetStringProperty("junkscoreorigin", getter_Copies(originStr)); // if this was classified by the plugin, see if we're supposed to @@ -132,11 +127,11 @@ NS_IMETHODIMP nsMsgQuickSearchDBView::OnKeyChange(nsMsgKey aKeyChanged, PRUint32 PRBool match=PR_FALSE; nsCOMPtr searchSession = do_QueryReferent(m_searchSession); if (searchSession) - searchSession->MatchHdr(msgHdr, m_db, &match); + searchSession->MatchHdr(aHdrChanged, m_db, &match); if (!match) { // remove hdr from view - nsMsgViewIndex deletedIndex = m_keys.FindIndex(aKeyChanged); + nsMsgViewIndex deletedIndex = FindHdr(aHdrChanged); if (deletedIndex != nsMsgViewIndex_None) RemoveByIndex(deletedIndex); } diff --git a/mozilla/mailnews/base/src/nsMsgQuickSearchDBView.h b/mozilla/mailnews/base/src/nsMsgQuickSearchDBView.h index a1b6d4f6c7a..b9b4a7d4d1e 100644 --- a/mozilla/mailnews/base/src/nsMsgQuickSearchDBView.h +++ b/mozilla/mailnews/base/src/nsMsgQuickSearchDBView.h @@ -58,12 +58,12 @@ public: NS_IMETHOD SetSearchSession(nsIMsgSearchSession *aSearchSession); NS_IMETHOD GetSearchSession(nsIMsgSearchSession* *aSearchSession); NS_IMETHOD Sort(nsMsgViewSortTypeValue sortType, nsMsgViewSortOrderValue sortOrder); - NS_IMETHOD OnKeyChange(nsMsgKey aKeyChanged, PRUint32 aOldFlags, + NS_IMETHOD OnHdrChange(nsIMsgDBHdr *aHdrChanged, PRUint32 aOldFlags, PRUint32 aNewFlags, nsIDBChangeListener *aInstigator); protected: nsWeakPtr m_searchSession; - virtual nsresult OnNewHeader(nsMsgKey newKey, nsMsgKey aParentKey, PRBool ensureListed); + virtual nsresult OnNewHeader(nsIMsgDBHdr *newHdr, nsMsgKey aParentKey, PRBool ensureListed); void SavePreSearchInfo(); void ClearPreSearchInfo(); diff --git a/mozilla/mailnews/base/src/nsMsgSearchDBView.cpp b/mozilla/mailnews/base/src/nsMsgSearchDBView.cpp index 514ff383ac2..a7612484d6d 100644 --- a/mozilla/mailnews/base/src/nsMsgSearchDBView.cpp +++ b/mozilla/mailnews/base/src/nsMsgSearchDBView.cpp @@ -72,6 +72,7 @@ NS_IMETHODIMP nsMsgSearchDBView::Open(nsIMsgFolder *folder, nsMsgViewSortTypeVal if (pCount) *pCount = 0; + m_folder = nsnull; return rv; } @@ -112,7 +113,7 @@ nsresult nsMsgSearchDBView::FetchLocation(PRInt32 aRow, PRUnichar ** aLocationSt return NS_OK; } -nsresult nsMsgSearchDBView::OnNewHeader(nsMsgKey newKey, nsMsgKey aParentKey, PRBool /*ensureListed*/) +nsresult nsMsgSearchDBView::OnNewHeader(nsIMsgDBHdr *newHdr, nsMsgKey aParentKey, PRBool /*ensureListed*/) { return NS_OK; } @@ -239,8 +240,32 @@ nsMsgSearchDBView::DoCommandWithFolder(nsMsgViewCommandTypeValue command, nsIMsg NS_IMETHODIMP nsMsgSearchDBView::DoCommand(nsMsgViewCommandTypeValue command) { - mCommand = command; + mCommand = command; + if (command == nsMsgViewCommandType::deleteMsg || command == nsMsgViewCommandType::deleteNoTrash + || command == nsMsgViewCommandType::selectAll) return nsMsgDBView::DoCommand(command); + nsresult rv = NS_OK; + nsUInt32Array selection; + GetSelectedIndices(&selection); + + nsMsgViewIndex *indices = selection.GetData(); + PRInt32 numIndices = selection.GetSize(); + + // we need to break apart the selection by folders, and then call + // ApplyCommandToIndices with the command and the indices in the + // selection that are from that folder. + + nsUInt32Array *indexArrays; + PRInt32 numArrays; + rv = PartitionSelectionByFolder(indices, numIndices, &indexArrays, &numArrays); + NS_ENSURE_SUCCESS(rv, rv); + for (PRInt32 folderIndex = 0; folderIndex < numArrays; folderIndex++) + { + rv = ApplyCommandToIndices(command, indexArrays[folderIndex].GetData(), indexArrays[folderIndex].GetSize()); + NS_ENSURE_SUCCESS(rv, rv); + } + + return rv; } // This method just removes the specified line from the view. It does @@ -258,7 +283,7 @@ nsresult nsMsgSearchDBView::RemoveByIndex(nsMsgViewIndex index) nsresult nsMsgSearchDBView::DeleteMessages(nsIMsgWindow *window, nsMsgViewIndex *indices, PRInt32 numIndices, PRBool deleteStorage) { nsresult rv; - InitializeGlobalsForDeleteAndFile(indices, numIndices); + GetFoldersAndHdrsForSelection(indices, numIndices); if (mDeleteModel != nsMsgImapDeleteModels::MoveToTrash) deleteStorage = PR_TRUE; if (!deleteStorage) @@ -272,7 +297,7 @@ nsresult nsMsgSearchDBView::CopyMessages(nsIMsgWindow *window, nsMsgViewIndex *indices, PRInt32 numIndices, PRBool isMove, nsIMsgFolder *destFolder) { nsresult rv; - InitializeGlobalsForDeleteAndFile(indices, numIndices); + GetFoldersAndHdrsForSelection(indices, numIndices); rv = ProcessRequestsInOneFolder(window); @@ -280,7 +305,43 @@ nsMsgSearchDBView::CopyMessages(nsIMsgWindow *window, nsMsgViewIndex *indices, P } nsresult -nsMsgSearchDBView::InitializeGlobalsForDeleteAndFile(nsMsgViewIndex *indices, PRInt32 numIndices) +nsMsgSearchDBView::PartitionSelectionByFolder(nsMsgViewIndex *indices, PRInt32 numIndices, nsUInt32Array **indexArrays, PRInt32 *numArrays) +{ + nsresult rv = NS_OK; + nsCOMPtr uniqueFoldersSelected = do_CreateInstance(NS_SUPPORTSARRAY_CONTRACTID, &rv); + mCurIndex = 0; + + //Build unique folder list based on headers selected by the user + for (nsMsgViewIndex i = 0; i < (nsMsgViewIndex) numIndices; i++) + { + nsCOMPtr curSupports = getter_AddRefs(m_folders->ElementAt(indices[i])); + if ( uniqueFoldersSelected->IndexOf(curSupports) < 0) + uniqueFoldersSelected->AppendElement(curSupports); + } + + PRUint32 numFolders =0; + rv = uniqueFoldersSelected->Count(&numFolders); //group the headers selected by each folder + *indexArrays = new nsUInt32Array[numFolders]; + *numArrays = numFolders; + NS_ENSURE_TRUE(*indexArrays, NS_ERROR_OUT_OF_MEMORY); + for (PRUint32 folderIndex=0; folderIndex < numFolders; folderIndex++) + { + nsCOMPtr curFolder = + do_QueryElementAt(uniqueFoldersSelected, folderIndex, &rv); + for (nsMsgViewIndex i = 0; i < (nsMsgViewIndex) numIndices; i++) + { + nsCOMPtr msgFolder = do_QueryElementAt(m_folders, + indices[i], &rv); + if (NS_SUCCEEDED(rv) && msgFolder && msgFolder == curFolder) + (*indexArrays)[folderIndex].Add(indices[i]); + } + } + return rv; + +} + +nsresult +nsMsgSearchDBView::GetFoldersAndHdrsForSelection(nsMsgViewIndex *indices, PRInt32 numIndices) { nsresult rv = NS_OK; mCurIndex = 0; diff --git a/mozilla/mailnews/base/src/nsMsgSearchDBView.h b/mozilla/mailnews/base/src/nsMsgSearchDBView.h index c7086062465..c82820ba58d 100644 --- a/mozilla/mailnews/base/src/nsMsgSearchDBView.h +++ b/mozilla/mailnews/base/src/nsMsgSearchDBView.h @@ -64,7 +64,7 @@ public: // override to get location NS_IMETHOD GetCellText(PRInt32 aRow, nsITreeColumn* aCol, nsAString& aValue); virtual nsresult GetMsgHdrForViewIndex(nsMsgViewIndex index, nsIMsgDBHdr **msgHdr); - virtual nsresult OnNewHeader(nsMsgKey newKey, nsMsgKey parentKey, PRBool ensureListed); + virtual nsresult OnNewHeader(nsIMsgDBHdr *newHdr, nsMsgKey parentKey, PRBool ensureListed); NS_IMETHOD GetFolderForViewIndex(nsMsgViewIndex index, nsIMsgFolder **folder); virtual nsresult GetFolders(nsISupportsArray **aFolders); @@ -76,8 +76,9 @@ protected: virtual nsresult RemoveByIndex(nsMsgViewIndex index); virtual nsresult CopyMessages(nsIMsgWindow *window, nsMsgViewIndex *indices, PRInt32 numIndices, PRBool isMove, nsIMsgFolder *destFolder); virtual nsresult DeleteMessages(nsIMsgWindow *window, nsMsgViewIndex *indices, PRInt32 numIndices, PRBool deleteStorage); - nsresult InitializeGlobalsForDeleteAndFile(nsMsgViewIndex *indices, PRInt32 numIndices); + nsresult GetFoldersAndHdrsForSelection(nsMsgViewIndex *indices, PRInt32 numIndices); nsresult GroupSearchResultsByFolder(); + nsresult PartitionSelectionByFolder(nsMsgViewIndex *indices, PRInt32 numIndices, nsUInt32Array **indexArrays, PRInt32 *numArrays); nsCOMPtr m_folders; // maybe we should store ranges, or the actual headers instead. nsCOMPtr m_hdrsForEachFolder; diff --git a/mozilla/mailnews/base/src/nsMsgThreadedDBView.cpp b/mozilla/mailnews/base/src/nsMsgThreadedDBView.cpp index 81d3db92b7f..d8ff4913d72 100644 --- a/mozilla/mailnews/base/src/nsMsgThreadedDBView.cpp +++ b/mozilla/mailnews/base/src/nsMsgThreadedDBView.cpp @@ -552,18 +552,19 @@ nsresult nsMsgThreadedDBView::InitSort(nsMsgViewSortTypeValue sortType, nsMsgVie return NS_OK; } -nsresult nsMsgThreadedDBView::OnNewHeader(nsMsgKey newKey, nsMsgKey aParentKey, PRBool ensureListed) +nsresult nsMsgThreadedDBView::OnNewHeader(nsIMsgDBHdr *newHdr, nsMsgKey aParentKey, PRBool ensureListed) { - nsresult rv; + nsresult rv = NS_OK; + nsMsgKey newKey; + newHdr->GetMessageKey(&newKey); + // views can override this behaviour, which is to append to view. // This is the mail behaviour, but threaded views want // to insert in order... - nsCOMPtr msgHdr; - rv = m_db->GetMsgHdrForKey(newKey, getter_AddRefs(msgHdr)); - if (NS_SUCCEEDED(rv) && msgHdr != nsnull) + if (newHdr) { PRUint32 msgFlags; - msgHdr->GetFlags(&msgFlags); + newHdr->GetFlags(&msgFlags); if ((m_viewFlags & nsMsgViewFlagsType::kUnreadOnly) && !ensureListed && (msgFlags & MSG_FLAG_READ)) return NS_OK; // Currently, we only add the header in a threaded view if it's a thread. @@ -572,7 +573,7 @@ nsresult nsMsgThreadedDBView::OnNewHeader(nsMsgKey newKey, nsMsgKey aParentKey, // for search view we don't support threaded display so just add it to the view. if (!(m_viewFlags & nsMsgViewFlagsType::kThreadedDisplay)) // || msgHdr->GetMessageKey() == m_messageDB->GetKeyOfFirstMsgInThread(msgHdr->GetMessageKey())) - rv = AddHdr(msgHdr); + rv = AddHdr(newHdr); else // need to find the thread we added this to so we can change the hasnew flag // added message to existing thread, but not to view { // Fix flags on thread header. @@ -585,13 +586,13 @@ nsresult nsMsgThreadedDBView::OnNewHeader(nsMsgKey newKey, nsMsgKey aParentKey, PRUint32 flags = m_flags[threadIndex]; // if we have a collapsed thread which just got a new // top of thread, change the keys array. - PRInt32 level = FindLevelInThread(msgHdr, threadIndex); + PRInt32 level = FindLevelInThread(newHdr, threadIndex); if (((flags & MSG_FLAG_ELIDED) || threadCount == 1) && (!(m_viewFlags & nsMsgViewFlagsType::kUnreadOnly) || !(msgFlags & MSG_FLAG_READ))) { if (level == 0) { nsMsgKey msgKey; - msgHdr->GetMessageKey(&msgKey); + newHdr->GetMessageKey(&msgKey); m_keys.SetAt(threadIndex, msgKey); } // note change, to update the parent thread's unread and total counts @@ -609,7 +610,7 @@ nsresult nsMsgThreadedDBView::OnNewHeader(nsMsgKey newKey, nsMsgKey aParentKey, { // insert child into thread // levels of other hdrs may have changed! PRUint32 newFlags = msgFlags; - nsMsgViewIndex insertIndex = GetInsertInfoForNewHdr(msgHdr, threadIndex, level); + nsMsgViewIndex insertIndex = GetInsertInfoForNewHdr(newHdr, threadIndex, level); // this header is the new king! try collapsing the existing thread, // removing it, installing this header as king, and expanding it. if (level == 0) @@ -638,10 +639,10 @@ nsresult nsMsgThreadedDBView::OnNewHeader(nsMsgKey newKey, nsMsgKey aParentKey, else // adding msg to thread that's not in view. { nsCOMPtr threadHdr; - m_db->GetThreadContainingMsgHdr(msgHdr, getter_AddRefs(threadHdr)); + m_db->GetThreadContainingMsgHdr(newHdr, getter_AddRefs(threadHdr)); if (threadHdr) { - AddMsgToThreadNotInView(threadHdr, msgHdr, ensureListed); + AddMsgToThreadNotInView(threadHdr, newHdr, ensureListed); } } } diff --git a/mozilla/mailnews/base/src/nsMsgThreadedDBView.h b/mozilla/mailnews/base/src/nsMsgThreadedDBView.h index db6f15ad35d..afb06e41fdc 100644 --- a/mozilla/mailnews/base/src/nsMsgThreadedDBView.h +++ b/mozilla/mailnews/base/src/nsMsgThreadedDBView.h @@ -62,7 +62,7 @@ public: protected: virtual const char * GetViewName(void) {return "ThreadedDBView"; } nsresult InitThreadedView(PRInt32 *pCount); - virtual nsresult OnNewHeader(nsMsgKey newKey, nsMsgKey aParentKey, PRBool ensureListed); + virtual nsresult OnNewHeader(nsIMsgDBHdr *newHdr, nsMsgKey aParentKey, PRBool ensureListed); virtual nsresult AddMsgToThreadNotInView(nsIMsgThread *threadHdr, nsIMsgDBHdr *msgHdr, PRBool ensureListed); nsresult ListThreadIds(nsMsgKey *startMsg, PRBool unreadOnly, nsMsgKey *pOutput, PRInt32 *pFlags, char *pLevels, PRInt32 numToList, PRInt32 *pNumListed, PRInt32 *pTotalHeaders); diff --git a/mozilla/mailnews/base/util/nsMsgDBFolder.cpp b/mozilla/mailnews/base/util/nsMsgDBFolder.cpp index 2ddfafd914a..396f3161c8b 100644 --- a/mozilla/mailnews/base/util/nsMsgDBFolder.cpp +++ b/mozilla/mailnews/base/util/nsMsgDBFolder.cpp @@ -788,15 +788,13 @@ nsMsgDBFolder::OnJunkScoreChanged(nsIDBChangeListener * aInstigator) // 1. When the status of a message changes. -NS_IMETHODIMP nsMsgDBFolder::OnKeyChange(nsMsgKey aKeyChanged, PRUint32 aOldFlags, PRUint32 aNewFlags, +NS_IMETHODIMP nsMsgDBFolder::OnHdrChange(nsIMsgDBHdr *aHdrChanged, PRUint32 aOldFlags, PRUint32 aNewFlags, nsIDBChangeListener * aInstigator) { - nsCOMPtr pMsgDBHdr; - nsresult rv = mDatabase->GetMsgHdrForKey(aKeyChanged, getter_AddRefs(pMsgDBHdr)); - if(NS_SUCCEEDED(rv) && pMsgDBHdr) + if(aHdrChanged) { - nsCOMPtr msgSupports(do_QueryInterface(pMsgDBHdr, &rv)); - if(NS_SUCCEEDED(rv)) + nsCOMPtr msgSupports(do_QueryInterface(aHdrChanged)); + if(msgSupports) SendFlagNotifications(msgSupports, aOldFlags, aNewFlags); UpdateSummaryTotals(PR_TRUE); } @@ -839,7 +837,7 @@ nsresult nsMsgDBFolder::CheckWithNewMessagesStatus(PRBool messageAdded) // 3. When a message gets deleted, we need to see if it was new // When we lose a new message we need to check if there are still new messages -NS_IMETHODIMP nsMsgDBFolder::OnKeyDeleted(nsMsgKey aKeyChanged, nsMsgKey aParentKey, PRInt32 aFlags, +NS_IMETHODIMP nsMsgDBFolder::OnHdrDeleted(nsIMsgDBHdr *aHdrChanged, nsMsgKey aParentKey, PRInt32 aFlags, nsIDBChangeListener * aInstigator) { // check to see if a new message is being deleted @@ -847,31 +845,26 @@ NS_IMETHODIMP nsMsgDBFolder::OnKeyDeleted(nsMsgKey aKeyChanged, nsMsgKey aParen // the folder newness has to be cleared. CheckWithNewMessagesStatus(PR_FALSE); - return OnKeyAddedOrDeleted(aKeyChanged, PR_FALSE); + return OnHdrAddedOrDeleted(aHdrChanged, PR_FALSE); } // 2. When a new messages gets added, we need to see if it's new. -NS_IMETHODIMP nsMsgDBFolder::OnKeyAdded(nsMsgKey aKeyChanged, nsMsgKey aParentKey , PRInt32 aFlags, +NS_IMETHODIMP nsMsgDBFolder::OnHdrAdded(nsIMsgDBHdr *aHdrChanged, nsMsgKey aParentKey , PRInt32 aFlags, nsIDBChangeListener * aInstigator) { if(aFlags & MSG_FLAG_NEW) CheckWithNewMessagesStatus(PR_TRUE); - return OnKeyAddedOrDeleted(aKeyChanged, PR_TRUE); + return OnHdrAddedOrDeleted(aHdrChanged, PR_TRUE); } -nsresult nsMsgDBFolder::OnKeyAddedOrDeleted(nsMsgKey aKeyChanged, PRBool added) +nsresult nsMsgDBFolder::OnHdrAddedOrDeleted(nsIMsgDBHdr *aHdrChanged, PRBool added) { - nsCOMPtr msgDBHdr; - nsresult rv = mDatabase->GetMsgHdrForKey(aKeyChanged, getter_AddRefs(msgDBHdr)); - if(NS_SUCCEEDED(rv) && msgDBHdr) - { - if(added) - NotifyItemAdded(msgDBHdr); - else - NotifyItemRemoved(msgDBHdr); - UpdateSummaryTotals(PR_TRUE); - } + if(added) + NotifyItemAdded(aHdrChanged); + else + NotifyItemRemoved(aHdrChanged); + UpdateSummaryTotals(PR_TRUE); return NS_OK; } @@ -880,13 +873,18 @@ nsresult nsMsgDBFolder::OnKeyAddedOrDeleted(nsMsgKey aKeyChanged, PRBool added) NS_IMETHODIMP nsMsgDBFolder::OnParentChanged(nsMsgKey aKeyChanged, nsMsgKey oldParent, nsMsgKey newParent, nsIDBChangeListener * aInstigator) { + nsCOMPtr hdrChanged; + mDatabase->GetMsgHdrForKey(aKeyChanged, getter_AddRefs(hdrChanged)); //In reality we probably want to just change the parent because otherwise we will lose things like //selection. - //First delete the child from the old threadParent - OnKeyAddedOrDeleted(aKeyChanged, PR_FALSE); - //Then add it to the new threadParent - OnKeyAddedOrDeleted(aKeyChanged, PR_TRUE); + if (hdrChanged) + { + //First delete the child from the old threadParent + OnHdrAddedOrDeleted(hdrChanged, PR_FALSE); + //Then add it to the new threadParent + OnHdrAddedOrDeleted(hdrChanged, PR_TRUE); + } return NS_OK; } diff --git a/mozilla/mailnews/base/util/nsMsgDBFolder.h b/mozilla/mailnews/base/util/nsMsgDBFolder.h index 25f2d9367a4..62fdec6a38a 100644 --- a/mozilla/mailnews/base/util/nsMsgDBFolder.h +++ b/mozilla/mailnews/base/util/nsMsgDBFolder.h @@ -131,7 +131,7 @@ protected: virtual nsresult GetDatabase(nsIMsgWindow *aMsgWindow) = 0; virtual nsresult SendFlagNotifications(nsISupports *item, PRUint32 oldFlags, PRUint32 newFlags); nsresult CheckWithNewMessagesStatus(PRBool messageAdded); - nsresult OnKeyAddedOrDeleted(nsMsgKey aKeyChanged, PRBool added); + nsresult OnHdrAddedOrDeleted(nsIMsgDBHdr *hdrChanged, PRBool added); nsresult CreateFileSpecForDB(const char *userLeafName, nsFileSpec &baseDir, nsIFileSpec **dbFileSpec); nsresult GetFolderCacheKey(nsIFileSpec **aFileSpec); diff --git a/mozilla/mailnews/build/nsMailModule.cpp b/mozilla/mailnews/build/nsMailModule.cpp index 3381321f351..a5bdd77cd1e 100644 --- a/mozilla/mailnews/build/nsMailModule.cpp +++ b/mozilla/mailnews/build/nsMailModule.cpp @@ -93,7 +93,7 @@ #include "nsMsgFolderCompactor.h" #include "nsMsgThreadedDBView.h" #include "nsMsgSpecialViews.h" -#include "nsMsgSearchDBView.h" +#include "nsMsgXFVirtualFolderDBView.h" #include "nsMsgQuickSearchDBView.h" #include "nsMsgOfflineManager.h" #include "nsMsgProgress.h" @@ -316,6 +316,7 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsMsgThreadedDBView) NS_GENERIC_FACTORY_CONSTRUCTOR(nsMsgThreadsWithUnreadDBView) NS_GENERIC_FACTORY_CONSTRUCTOR(nsMsgWatchedThreadsWithUnreadDBView) NS_GENERIC_FACTORY_CONSTRUCTOR(nsMsgSearchDBView) +NS_GENERIC_FACTORY_CONSTRUCTOR(nsMsgXFVirtualFolderDBView) NS_GENERIC_FACTORY_CONSTRUCTOR(nsMsgQuickSearchDBView) NS_GENERIC_FACTORY_CONSTRUCTOR(nsMsgOfflineManager) NS_GENERIC_FACTORY_CONSTRUCTOR(nsMsgProgress) @@ -734,6 +735,10 @@ static const nsModuleComponentInfo gComponents[] = { NS_MSGQUICKSEARCHDBVIEW_CONTRACTID, nsMsgQuickSearchDBViewConstructor, }, + { "cross folder virtual folder db view", NS_MSG_XFVFDBVIEW_CID, + NS_MSGXFVFDBVIEW_CONTRACTID, + nsMsgXFVirtualFolderDBViewConstructor, + }, { "Messenger Offline Manager", NS_MSGOFFLINEMANAGER_CID, NS_MSGOFFLINEMANAGER_CONTRACTID, nsMsgOfflineManagerConstructor, diff --git a/mozilla/mailnews/db/msgdb/public/nsIDBChangeAnnouncer.idl b/mozilla/mailnews/db/msgdb/public/nsIDBChangeAnnouncer.idl index bdc00e05aaa..17c3733d8ee 100644 --- a/mozilla/mailnews/db/msgdb/public/nsIDBChangeAnnouncer.idl +++ b/mozilla/mailnews/db/msgdb/public/nsIDBChangeAnnouncer.idl @@ -39,19 +39,20 @@ #include "MailNewsTypes2.idl" interface nsIDBChangeListener; +interface nsIMsgDBHdr; -[scriptable, uuid(2aa6733a-2b36-11d3-a51c-0060b0fc04b7)] +[scriptable, uuid(22baf00b-939d-42c3-ac51-21d99dfa1f05)] interface nsIDBChangeAnnouncer : nsISupports { /* these 2 calls return NS_OK on success, NS_COMFALSE on failure */ void AddListener(in nsIDBChangeListener listener); void RemoveListener(in nsIDBChangeListener listener); - void NotifyKeyChangeAll(in nsMsgKey keyChanged, in unsigned long aOldFlags, in unsigned long aNewFlags, + void NotifyHdrChangeAll(in nsIMsgDBHdr aHdrChanged, in unsigned long aOldFlags, in unsigned long aNewFlags, in nsIDBChangeListener instigator); - void NotifyKeyAddedAll(in nsMsgKey keyAdded, in nsMsgKey parentKey, in long flags, + void NotifyHdrAddedAll(in nsIMsgDBHdr aHdrAdded, in nsMsgKey parentKey, in long flags, in nsIDBChangeListener instigator); - void NotifyKeyDeletedAll(in nsMsgKey keyDeleted, in nsMsgKey parentKey, in long flags, + void NotifyHdrDeletedAll(in nsIMsgDBHdr aHdrDeleted, in nsMsgKey parentKey, in long flags, in nsIDBChangeListener instigator); void NotifyParentChangedAll(in nsMsgKey keyReparented, in nsMsgKey oldParent, in nsMsgKey newParent, in nsIDBChangeListener instigator); diff --git a/mozilla/mailnews/db/msgdb/public/nsIDBChangeListener.idl b/mozilla/mailnews/db/msgdb/public/nsIDBChangeListener.idl index 849cb87b1ab..085ff17bbda 100644 --- a/mozilla/mailnews/db/msgdb/public/nsIDBChangeListener.idl +++ b/mozilla/mailnews/db/msgdb/public/nsIDBChangeListener.idl @@ -39,15 +39,16 @@ #include "MailNewsTypes2.idl" interface nsIDBChangeAnnouncer; +interface nsIMsgDBHdr; -[scriptable, uuid(ad0f7f90-baff-11d2-8d67-00805f8a6617)] +[scriptable, uuid(1d409e71-3b4e-4611-9759-6335c7362f5c)] interface nsIDBChangeListener : nsISupports { - void onKeyChange(in nsMsgKey aKeyChanged, in unsigned long aOldFlags, in unsigned long aNewFlags, + void onHdrChange(in nsIMsgDBHdr aHdrChanged, in unsigned long aOldFlags, in unsigned long aNewFlags, in nsIDBChangeListener aInstigator); - void onKeyDeleted(in nsMsgKey aKeyChanged, in nsMsgKey aParentKey, in long aFlags, + void onHdrDeleted(in nsIMsgDBHdr aHdrChanged, in nsMsgKey aParentKey, in long aFlags, in nsIDBChangeListener aInstigator); - void onKeyAdded(in nsMsgKey aKeyChanged, in nsMsgKey aParentKey, in long aFlags, + void onHdrAdded(in nsIMsgDBHdr aHdrChanged, in nsMsgKey aParentKey, in long aFlags, in nsIDBChangeListener aInstigator); void onParentChanged (in nsMsgKey aKeyChanged, in nsMsgKey oldParent, in nsMsgKey newParent, in nsIDBChangeListener aInstigator); void onAnnouncerGoingAway(in nsIDBChangeAnnouncer instigator); diff --git a/mozilla/mailnews/db/msgdb/src/nsMsgDatabase.cpp b/mozilla/mailnews/db/msgdb/src/nsMsgDatabase.cpp index 901ba1ced71..29c02a9e161 100644 --- a/mozilla/mailnews/db/msgdb/src/nsMsgDatabase.cpp +++ b/mozilla/mailnews/db/msgdb/src/nsMsgDatabase.cpp @@ -571,7 +571,7 @@ NS_IMETHODIMP nsMsgDatabase::RemoveListener(nsIDBChangeListener *listener) } // change announcer methods - just broadcast to all listeners. -NS_IMETHODIMP nsMsgDatabase::NotifyKeyChangeAll(nsMsgKey keyChanged, PRUint32 oldFlags, PRUint32 newFlags, +NS_IMETHODIMP nsMsgDatabase::NotifyHdrChangeAll(nsIMsgDBHdr *aHdrChanged, PRUint32 oldFlags, PRUint32 newFlags, nsIDBChangeListener *instigator) { if (!m_ChangeListeners) @@ -584,7 +584,7 @@ NS_IMETHODIMP nsMsgDatabase::NotifyKeyChangeAll(nsMsgKey keyChanged, PRUint32 ol nsCOMPtr changeListener; m_ChangeListeners->QueryElementAt(i, NS_GET_IID(nsIDBChangeListener), (void **) getter_AddRefs(changeListener)); - nsresult rv = changeListener->OnKeyChange(keyChanged, oldFlags, newFlags, instigator); + nsresult rv = changeListener->OnHdrChange(aHdrChanged, oldFlags, newFlags, instigator); if (NS_FAILED(rv)) return rv; } @@ -627,7 +627,7 @@ NS_IMETHODIMP nsMsgDatabase::NotifyJunkScoreChanged(nsIDBChangeListener *instiga return NS_OK; } -NS_IMETHODIMP nsMsgDatabase::NotifyKeyDeletedAll(nsMsgKey keyDeleted, nsMsgKey parentKey, PRInt32 flags, +NS_IMETHODIMP nsMsgDatabase::NotifyHdrDeletedAll(nsIMsgDBHdr *aHdrDeleted, nsMsgKey parentKey, PRInt32 flags, nsIDBChangeListener *instigator) { if (m_ChangeListeners == nsnull) @@ -638,14 +638,14 @@ NS_IMETHODIMP nsMsgDatabase::NotifyKeyDeletedAll(nsMsgKey keyDeleted, nsMsgKey p { nsCOMPtr changeListener; m_ChangeListeners->QueryElementAt(i, NS_GET_IID(nsIDBChangeListener), (void **) getter_AddRefs(changeListener)); - nsresult rv = changeListener->OnKeyDeleted(keyDeleted, parentKey, flags, instigator); + nsresult rv = changeListener->OnHdrDeleted(aHdrDeleted, parentKey, flags, instigator); if (NS_FAILED(rv)) return rv; } return NS_OK; } -NS_IMETHODIMP nsMsgDatabase::NotifyKeyAddedAll(nsMsgKey keyAdded, nsMsgKey parentKey, PRInt32 flags, +NS_IMETHODIMP nsMsgDatabase::NotifyHdrAddedAll(nsIMsgDBHdr *aHdrAdded, nsMsgKey parentKey, PRInt32 flags, nsIDBChangeListener *instigator) { #ifdef DEBUG_bienvenu1 @@ -660,7 +660,7 @@ NS_IMETHODIMP nsMsgDatabase::NotifyKeyAddedAll(nsMsgKey keyAdded, nsMsgKey paren nsCOMPtr changeListener; m_ChangeListeners->QueryElementAt(i, NS_GET_IID(nsIDBChangeListener), (void **) getter_AddRefs(changeListener)); - nsresult rv = changeListener->OnKeyAdded(keyAdded, parentKey, flags, instigator); + nsresult rv = changeListener->OnHdrAdded(aHdrAdded, parentKey, flags, instigator); if (NS_FAILED(rv)) return rv; } @@ -1827,7 +1827,7 @@ NS_IMETHODIMP nsMsgDatabase::DeleteHeader(nsIMsgDBHdr *msg, nsIDBChangeListener if (notify /* && NS_SUCCEEDED(ret)*/) { - NotifyKeyDeletedAll(key, threadParent, flags, instigator); // tell listeners + NotifyHdrDeletedAll(msg, threadParent, flags, instigator); // tell listeners } // if (!onlyRemoveFromThread) // to speed up expiration, try this. But really need to do this in RemoveHeaderFromDB nsresult ret = RemoveHeaderFromDB(msgHdr); @@ -2016,7 +2016,7 @@ nsresult nsMsgDatabase::MarkHdrReadInDB(nsIMsgDBHdr *msgHdr, PRBool bRead, if (oldFlags == flags) return NS_OK; - return NotifyKeyChangeAll(key, oldFlags, flags, instigator); + return NotifyHdrChangeAll(msgHdr, oldFlags, flags, instigator); } NS_IMETHODIMP nsMsgDatabase::MarkRead(nsMsgKey key, PRBool bRead, @@ -2102,8 +2102,10 @@ nsMsgDatabase::MarkThreadIgnored(nsIMsgThread *thread, nsMsgKey threadKey, PRBoo threadFlags &= ~MSG_FLAG_IGNORED; thread->SetFlags(threadFlags); - NotifyKeyChangeAll(threadKey, oldThreadFlags, threadFlags, instigator); - return NS_OK; + nsCOMPtr msg; + nsresult rv = GetMsgHdrForKey(threadKey, getter_AddRefs(msg)); + + return NotifyHdrChangeAll(msg, oldThreadFlags, threadFlags, instigator); } NS_IMETHODIMP @@ -2122,9 +2124,12 @@ nsMsgDatabase::MarkThreadWatched(nsIMsgThread *thread, nsMsgKey threadKey, PRBoo else threadFlags &= ~MSG_FLAG_WATCHED; - NotifyKeyChangeAll(threadKey, oldThreadFlags, threadFlags, instigator); + nsCOMPtr msg; + GetMsgHdrForKey(threadKey, getter_AddRefs(msg)); + + nsresult rv = NotifyHdrChangeAll(msg, oldThreadFlags, threadFlags, instigator); thread->SetFlags(threadFlags); - return NS_OK; + return rv; } NS_IMETHODIMP nsMsgDatabase::MarkMarked(nsMsgKey key, PRBool mark, @@ -2165,8 +2170,7 @@ NS_IMETHODIMP nsMsgDatabase::SetStringProperty(nsMsgKey aKey, const char *aPrope PRUint32 flags; (void)msgHdr->GetFlags(&flags); - NotifyKeyChangeAll(aKey, flags, flags, nsnull); - return rv; + return NotifyHdrChangeAll(msgHdr, flags, flags, nsnull); } NS_IMETHODIMP nsMsgDatabase::SetLabel(nsMsgKey key, nsMsgLabelValue label) @@ -2262,13 +2266,11 @@ nsresult nsMsgDatabase::SetKeyFlag(nsMsgKey key, PRBool set, PRUint32 flag, if (oldFlags == flags) return NS_OK; - NotifyKeyChangeAll(key, oldFlags, flags, instigator); - return rv; + return NotifyHdrChangeAll(msgHdr, oldFlags, flags, instigator); } nsresult nsMsgDatabase::SetMsgHdrFlag(nsIMsgDBHdr *msgHdr, PRBool set, PRUint32 flag, nsIDBChangeListener *instigator) { - nsresult rv; PRUint32 oldFlags; msgHdr->GetFlags(&oldFlags); @@ -2280,12 +2282,7 @@ nsresult nsMsgDatabase::SetMsgHdrFlag(nsIMsgDBHdr *msgHdr, PRBool set, PRUint32 if (oldFlags == flags) return NS_OK; - PRUint32 key; - rv = msgHdr->GetMessageKey(&key); - - if(NS_SUCCEEDED(rv)) - NotifyKeyChangeAll(key, oldFlags, flags, instigator); - return rv; + return NotifyHdrChangeAll(msgHdr, oldFlags, flags, instigator); } // Helper routine - lowest level of flag setting - returns PR_TRUE if flags change, @@ -2477,13 +2474,11 @@ NS_IMETHODIMP nsMsgDatabase::ClearNewList(PRBool notify /* = FALSE */) err = GetMsgHdrForKey(lastNewKey, getter_AddRefs(msgHdr)); if (NS_SUCCEEDED(err)) { - nsMsgKey key; - (void)msgHdr->GetMessageKey(&key); PRUint32 flags; (void)msgHdr->GetFlags(&flags); if ((flags | MSG_FLAG_NEW) != flags) - NotifyKeyChangeAll(key, flags | MSG_FLAG_NEW, flags, nsnull); + NotifyHdrChangeAll(msgHdr, flags | MSG_FLAG_NEW, flags, nsnull); } if (elementIndex == 0) break; @@ -2977,7 +2972,7 @@ NS_IMETHODIMP nsMsgDatabase::AddNewHdrToDB(nsIMsgDBHdr *newHdr, PRBool notify) nsMsgKey threadParent; newHdr->GetThreadParent(&threadParent); - NotifyKeyAddedAll(key, threadParent, flags, NULL); + NotifyHdrAddedAll(newHdr, threadParent, flags, NULL); } } NS_ASSERTION(NS_SUCCEEDED(err), "error creating thread"); diff --git a/mozilla/mailnews/imap/src/nsImapMailFolder.cpp b/mozilla/mailnews/imap/src/nsImapMailFolder.cpp index 1109032c32c..8d3a234279d 100644 --- a/mozilla/mailnews/imap/src/nsImapMailFolder.cpp +++ b/mozilla/mailnews/imap/src/nsImapMailFolder.cpp @@ -320,14 +320,61 @@ nsShouldIgnoreFile(nsString& name) return PR_TRUE; } +// this is only called for virtual folders, currently. NS_IMETHODIMP nsImapMailFolder::AddSubfolder(const nsAString& aName, nsIMsgFolder** aChild) { - nsresult rv = nsMsgDBFolder::AddSubfolder(aName, aChild); + NS_ENSURE_ARG_POINTER(aChild); + + PRInt32 flags = 0; + nsresult rv; + nsCOMPtr rdf = do_GetService("@mozilla.org/rdf/rdf-service;1", &rv); + NS_ENSURE_SUCCESS(rv,rv); + + nsCAutoString uri(mURI); + uri.Append('/'); + + // convert name to imap modified utf7, like an imap server would + nsCAutoString utfFolderName; + rv = CopyUTF16toMUTF7(PromiseFlatString(aName), utfFolderName); NS_ENSURE_SUCCESS(rv, rv); + + uri += utfFolderName.get(); + + nsCOMPtr msgFolder; + rv = GetChildWithURI(uri.get(), PR_FALSE/*deep*/, PR_TRUE /*case Insensitive*/, getter_AddRefs(msgFolder)); + if (NS_SUCCEEDED(rv) && msgFolder) + return NS_MSG_FOLDER_EXISTS; + + nsCOMPtr res; + rv = rdf->GetResource(uri, getter_AddRefs(res)); + if (NS_FAILED(rv)) + return rv; + + nsCOMPtr folder(do_QueryInterface(res, &rv)); + if (NS_FAILED(rv)) + return rv; + + folder->GetFlags((PRUint32 *)&flags); + + flags |= MSG_FOLDER_FLAG_MAIL; + + folder->SetParent(this); + + folder->SetFlags(flags); + + nsCOMPtr supports = do_QueryInterface(folder); + if(folder) + mSubFolders->AppendElement(supports); + NS_ADDREF(*aChild = folder); + nsCOMPtr imapChild = do_QueryInterface(*aChild); if (imapChild) + { + NS_LossyConvertUTF16toASCII folderCName(aName); + imapChild->SetOnlineName(folderCName.get()); imapChild->SetHierarchyDelimiter(m_hierarchyDelimiter); + } return rv; } diff --git a/mozilla/mailnews/local/src/nsParseMailbox.cpp b/mozilla/mailnews/local/src/nsParseMailbox.cpp index 939b55e88e9..8f0b88dd98c 100644 --- a/mozilla/mailnews/local/src/nsParseMailbox.cpp +++ b/mozilla/mailnews/local/src/nsParseMailbox.cpp @@ -172,20 +172,17 @@ NS_IMETHODIMP nsMsgMailboxParser::OnStopRequest(nsIRequest *request, nsISupports -/* void OnKeyChange (in nsMsgKey aKeyChanged, in unsigned long aOldFlags, in unsigned long aNewFlags, in nsIDBChangeListener aInstigator); */ -NS_IMETHODIMP nsMsgMailboxParser::OnKeyChange(nsMsgKey aKeyChanged, PRUint32 aOldFlags, PRUint32 aNewFlags, nsIDBChangeListener *aInstigator) +NS_IMETHODIMP nsMsgMailboxParser::OnHdrChange(nsIMsgDBHdr *aHdrChanged, PRUint32 aOldFlags, PRUint32 aNewFlags, nsIDBChangeListener *aInstigator) { return NS_OK; } -/* void OnKeyDeleted (in nsMsgKey aKeyChanged, in nsMsgKey aParentKey, in long aFlags, in nsIDBChangeListener aInstigator); */ -NS_IMETHODIMP nsMsgMailboxParser::OnKeyDeleted(nsMsgKey aKeyChanged, nsMsgKey aParentKey, PRInt32 aFlags, nsIDBChangeListener *aInstigator) +NS_IMETHODIMP nsMsgMailboxParser::OnHdrDeleted(nsIMsgDBHdr *aHdrChanged, nsMsgKey aParentKey, PRInt32 aFlags, nsIDBChangeListener *aInstigator) { return NS_OK; } -/* void OnKeyAdded (in nsMsgKey aKeyChanged, in nsMsgKey aParentKey, in long aFlags, in nsIDBChangeListener aInstigator); */ -NS_IMETHODIMP nsMsgMailboxParser::OnKeyAdded(nsMsgKey aKeyChanged, nsMsgKey aParentKey, PRInt32 aFlags, nsIDBChangeListener *aInstigator) +NS_IMETHODIMP nsMsgMailboxParser::OnHdrAdded(nsIMsgDBHdr *aHdrAdded, nsMsgKey aParentKey, PRInt32 aFlags, nsIDBChangeListener *aInstigator) { return NS_OK; }