backend changes for cross-folder virtual folders, sr=mscott 11051

This commit is contained in:
bienvenu%nventure.com 2004-08-31 20:53:24 +00:00
parent 356984010a
commit 666683986e
21 changed files with 462 additions and 251 deletions

View File

@ -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();

View File

@ -114,6 +114,7 @@ CPPSRCS = \
nsMsgSpecialViews.cpp \
nsMsgQuickSearchDBView.cpp \
nsMsgSearchDBView.cpp \
nsMsgXFVirtualFolderDBView.cpp \
nsMsgOfflineManager.cpp \
nsMsgProgress.cpp \
nsMessengerContentHandler.cpp \

View File

@ -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 <nsIMsgDatabase> msgDB;
nsresult rv = m_folderWatching->GetMsgDatabase(nsnull, getter_AddRefs(msgDB));
nsCOMPtr <nsIMsgDBHdr> 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 <nsIMsgDatabase> 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 <nsIMsgMailSession> 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 <nsIMsgDatabase> msgDB;
nsresult rv = m_folderWatching->GetMsgDatabase(nsnull, getter_AddRefs(msgDB));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr <nsIMsgDBHdr> 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 <nsIMsgDatabase> 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 <nsIMsgDatabase> msgDB;
nsresult rv = m_folderWatching->GetMsgDatabase(nsnull, getter_AddRefs(msgDB));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr <nsIMsgDBHdr> 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 <nsIMsgDatabase> 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<nsIMsgDBService> msgDBService = do_GetService(NS_MSGDB_SERVICE_CONTRACTID, &rv);
if (msgDBService)
msgDBService->UnregisterPendingListener(this);
return rv;
nsCOMPtr <nsIMsgDatabase> 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<nsIFileInputStream> 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 <nsILineInputStream> lineInputStream(do_QueryInterface(fileStream));
PRBool isMore = PR_TRUE;
nsCAutoString buffer;
PRInt32 version = -1;
nsCOMPtr <nsIMsgFolder> virtualFolder;
nsCOMPtr <nsIDBFolderInfo> dbFolderInfo;
nsCOMPtr<nsIRDFResource> resource;
nsCOMPtr<nsIRDFService> 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 <nsIMsgFolder> folder;
nsCOMPtr<nsIRDFService> rdf(do_GetService("@mozilla.org/rdf/rdf-service;1", &rv));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIRDFResource> 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 <nsIMsgFolder> parentFolder = do_QueryInterface(resource);
if (parentFolder)
{
nsCOMPtr <nsIMsgFolder> 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 <nsIMsgDatabase> db;
childFolder->GetMsgDatabase(nsnull, getter_AddRefs(db)); // force db to get created.
nsCOMPtr <nsIDBFolderInfo> 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 <nsIMsgFolder> 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 <nsIMsgFolder> childFolder;
rv = parentFolder->AddSubfolder(currentFolderNameStr, getter_AddRefs(childFolder));
nsCOMPtr <nsIMsgDatabase> 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 <nsIMsgFolder> 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 <nsIRDFResource> folderRes (do_QueryElementAt(virtualFolders, folderIndex));
nsCOMPtr <nsIMsgFolder> msgFolder = do_QueryInterface(folderRes);
const char *uri;
nsCOMPtr <nsIMsgDatabase> db;
nsCOMPtr <nsIDBFolderInfo> 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 <nsIMsgDatabase> virtDatabase;
nsCOMPtr <nsIDBFolderInfo> 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();
}

View File

@ -204,6 +204,7 @@ private:
// handle virtual folders
nsresult GetVirtualFoldersFile(nsCOMPtr<nsILocalFile>& file);
nsresult LoadVirtualFolders();
nsresult WriteLineToOutputStream(const char *prefix, const char * line, nsIOutputStream *outputStream);
static void getUniqueKey(const char* prefix,
nsHashtable *hashTable,

View File

@ -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
//

View File

@ -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 <nsIMsgDBHdr> msgHdr;
rv = GetMsgHdrForViewIndex(viewPosition, getter_AddRefs(msgHdr));
NS_ENSURE_SUCCESS(rv,rv);
nsCOMPtr <nsIMsgFolder> 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<nsIMsgDBHdr> 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 <nsIMsgFolder> 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<nsIMsgFolder> 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 <nsIMsgImapMailFolder> imapFolder = do_QueryInterface(m_folder);
nsCOMPtr <nsIMsgImapMailFolder> imapFolder = do_QueryInterface(folder);
PRBool thisIsImapFolder = (imapFolder != nsnull);
nsCOMPtr<nsIJunkMailPlugin> junkPlugin;
@ -2302,8 +2321,6 @@ nsMsgDBView::ApplyCommandToIndices(nsMsgViewCommandTypeValue command, nsMsgViewI
// more junk status column in the 'search messages' dialog
// like in earlier versions...)
//
nsCOMPtr<nsIMsgFolder> folder;
rv = GetFolderForViewIndex(indices[0], getter_AddRefs(folder));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIMsgIncomingServer> 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 <nsIMsgDBHdr> 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)
{

View File

@ -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;

View File

@ -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 <nsIMsgDBHdr> msgHdr;
rv = m_db->GetMsgHdrForKey(newKey, getter_AddRefs(msgHdr));
if (NS_SUCCEEDED(rv) && msgHdr != nsnull)
if (newHdr)
{
PRBool match=PR_FALSE;
nsCOMPtr <nsIMsgSearchSession> 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 <nsIMsgDBHdr> 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 <nsIMsgSearchSession> 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);
}

View File

@ -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();

View File

@ -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 <nsISupportsArray> 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 <nsISupports> 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 <nsIMsgFolder> curFolder =
do_QueryElementAt(uniqueFoldersSelected, folderIndex, &rv);
for (nsMsgViewIndex i = 0; i < (nsMsgViewIndex) numIndices; i++)
{
nsCOMPtr <nsIMsgFolder> 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;

View File

@ -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 <nsISupportsArray> m_folders; // maybe we should store ranges, or the actual headers instead.
nsCOMPtr <nsISupportsArray> m_hdrsForEachFolder;

View File

@ -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 <nsIMsgDBHdr> 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 <nsIMsgThread> 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);
}
}
}

View File

@ -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);

View File

@ -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<nsIMsgDBHdr> pMsgDBHdr;
nsresult rv = mDatabase->GetMsgHdrForKey(aKeyChanged, getter_AddRefs(pMsgDBHdr));
if(NS_SUCCEEDED(rv) && pMsgDBHdr)
if(aHdrChanged)
{
nsCOMPtr<nsISupports> msgSupports(do_QueryInterface(pMsgDBHdr, &rv));
if(NS_SUCCEEDED(rv))
nsCOMPtr<nsISupports> 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<nsIMsgDBHdr> 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<nsIMsgDBHdr> 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;
}

View File

@ -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);

View File

@ -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,

View File

@ -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);

View File

@ -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);

View File

@ -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<nsIDBChangeListener> 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<nsIDBChangeListener> 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<nsIDBChangeListener> 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 <nsIMsgDBHdr> 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 <nsIMsgDBHdr> 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");

View File

@ -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<nsIRDFService> 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 <nsIMsgFolder> 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<nsIRDFResource> res;
rv = rdf->GetResource(uri, getter_AddRefs(res));
if (NS_FAILED(rv))
return rv;
nsCOMPtr<nsIMsgFolder> 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<nsISupports> supports = do_QueryInterface(folder);
if(folder)
mSubFolders->AppendElement(supports);
NS_ADDREF(*aChild = folder);
nsCOMPtr <nsIMsgImapMailFolder> imapChild = do_QueryInterface(*aChild);
if (imapChild)
{
NS_LossyConvertUTF16toASCII folderCName(aName);
imapChild->SetOnlineName(folderCName.get());
imapChild->SetHierarchyDelimiter(m_hierarchyDelimiter);
}
return rv;
}

View File

@ -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;
}