mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 11:25:00 +00:00
make the message view persist on a per folder basis. (#63853)
make it so you can view "threads with unread". (#52927) threaded and unread are no longer mutually exclusive. later, I'll add "unread threaded" which is no the same thing as "thread with unread". fix the nsMsgMessageDataSource() to ask the view, thread or msg database for existance of messages, instead of getting an enumerator for all messages, and seeing if it is non empty. more performance work on the way. move enums from MailNewsTypes.h to MailNewsTypes2.idl, so that I can use the same ones from JS and C++. sr=bienvenu
This commit is contained in:
parent
4e02ab8830
commit
e2955b1ba8
@ -55,19 +55,6 @@
|
||||
{0x8a, 0x5d, 0x0, 0x60, 0xb0, 0xfc, 0x4, 0xd2} \
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// nsMessageViewDataSource
|
||||
//
|
||||
#define NS_MESSAGEVIEWDATASOURCE_CONTRACTID \
|
||||
NS_RDF_DATASOURCE_CONTRACTID_PREFIX "mail-messageview"
|
||||
|
||||
#define NS_MESSAGEVIEWDATASOURCE_CID \
|
||||
{ /* 14495573-E945-11d2-8A52-0060B0FC04D2 */ \
|
||||
0x14495573, 0xe945, 0x11d2, \
|
||||
{0x8a, 0x52, 0x0, 0x60, 0xb0, 0xfc, 0x4, 0xd2}}
|
||||
|
||||
|
||||
//
|
||||
// nsMsgAccountManager
|
||||
//
|
||||
|
@ -51,7 +51,6 @@
|
||||
#include "nsMessengerMigrator.h"
|
||||
#include "nsMsgIdentity.h"
|
||||
#include "nsMsgIncomingServer.h"
|
||||
#include "nsMessageViewDataSource.h"
|
||||
#include "nsMsgFolderDataSource.h"
|
||||
#include "nsMsgMessageDataSource.h"
|
||||
|
||||
|
@ -32,11 +32,9 @@ interface nsIMsgWindow;
|
||||
|
||||
interface nsIMessageView : nsISupports
|
||||
{
|
||||
%{C++
|
||||
enum { eShowAll =0, eShowRead =1, eShowUnread =2 , eShowWatched =3};
|
||||
%}
|
||||
attribute unsigned long viewType;
|
||||
attribute boolean showThreads;
|
||||
|
||||
void GetMessages(in nsIRDFResource parentResource, in nsIMsgWindow msgWindow, out nsISimpleEnumerator messages);
|
||||
boolean hasMessages(in nsIRDFResource parentResource, in nsIMsgWindow msgWindow);
|
||||
};
|
||||
|
@ -68,10 +68,12 @@ const nsMsgBiffState nsMsgBiffState_Unknown = 2; // We dunno whether there is ne
|
||||
void ReplaceElement(in nsISupports element, in nsISupports newElement);
|
||||
|
||||
nsISimpleEnumerator getMessages(in nsIMsgWindow aMsgWindow);
|
||||
nsISimpleEnumerator getThreads(in nsIMsgWindow aMsgWindow);
|
||||
nsISimpleEnumerator getThreadsOfType(in nsIMsgWindow aMsgWindow, in unsigned long viewType);
|
||||
boolean hasThreads(in nsIMsgWindow aMsgWindow);
|
||||
boolean hasMessagesOfType(in nsIMsgWindow aMsgWindow, in unsigned long viewType);
|
||||
|
||||
void startFolderLoading();
|
||||
void endFolderLoading();
|
||||
void startFolderLoading();
|
||||
void endFolderLoading();
|
||||
|
||||
/* get new headers for db */
|
||||
void updateFolder(in nsIMsgWindow aWindow);
|
||||
|
@ -48,5 +48,7 @@ interface nsIMsgThread : nsISupports {
|
||||
void MarkChildRead(in boolean bRead);
|
||||
|
||||
nsISimpleEnumerator EnumerateMessages(in nsMsgKey parent);
|
||||
|
||||
nsISimpleEnumerator EnumerateUnreadMessages(in nsMsgKey parent);
|
||||
|
||||
boolean hasMessagesOfType(in nsMsgKey parent, in unsigned long viewType);
|
||||
};
|
||||
|
@ -98,7 +98,7 @@ function ChangeFolderByDOMNode(folderNode)
|
||||
dump(uri + "\n");
|
||||
|
||||
var isThreaded = folderNode.getAttribute('threaded');
|
||||
|
||||
|
||||
if ((isThreaded == "") && isNewsURI(uri)) {
|
||||
isThreaded = "true";
|
||||
}
|
||||
@ -109,8 +109,10 @@ function ChangeFolderByDOMNode(folderNode)
|
||||
|
||||
var sortDirection = folderNode.getAttribute('sortDirection');
|
||||
|
||||
var viewType = folderNode.getAttribute('viewType');
|
||||
|
||||
if (uri)
|
||||
ChangeFolderByURI(uri, isThreaded == "true", sortResource, sortDirection);
|
||||
ChangeFolderByURI(uri, isThreaded == "true", sortResource, sortDirection, viewType);
|
||||
}
|
||||
|
||||
function setTitleFromFolder(msgfolder, subject)
|
||||
@ -159,7 +161,7 @@ function setTitleFromFolder(msgfolder, subject)
|
||||
window.title = title;
|
||||
}
|
||||
|
||||
function ChangeFolderByURI(uri, isThreaded, sortID, sortDirection)
|
||||
function ChangeFolderByURI(uri, isThreaded, sortID, sortDirection, viewType)
|
||||
{
|
||||
dump('In ChangeFolderByURI uri = ' + uri + "\n");
|
||||
if (uri == gCurrentLoadingFolderURI)
|
||||
@ -195,6 +197,7 @@ function ChangeFolderByURI(uri, isThreaded, sortID, sortDirection)
|
||||
gCurrentLoadingFolderIsThreaded = isThreaded;
|
||||
gCurrentLoadingFolderSortID = sortID;
|
||||
gCurrentLoadingFolderSortDirection = sortDirection;
|
||||
gCurrentLoadingFolderViewType = viewType;
|
||||
msgfolder.startFolderLoading();
|
||||
msgfolder.updateFolder(msgWindow);
|
||||
}
|
||||
@ -209,7 +212,8 @@ function ChangeFolderByURI(uri, isThreaded, sortID, sortDirection)
|
||||
gCurrentFolderToReroot = "";
|
||||
gCurrentLoadingFolderIsThreaded = false;
|
||||
gCurrentLoadingFolderSortID = "";
|
||||
RerootFolder(uri, msgfolder, isThreaded, sortID, sortDirection);
|
||||
gCurrentLoadingFolderViewType = "";
|
||||
RerootFolder(uri, msgfolder, isThreaded, sortID, sortDirection, viewType);
|
||||
|
||||
//Need to do this after rerooting folder. Otherwise possibility of receiving folder loaded
|
||||
//notification before folder has actually changed.
|
||||
@ -227,7 +231,7 @@ function isNewsURI(uri)
|
||||
}
|
||||
}
|
||||
|
||||
function RerootFolder(uri, newFolder, isThreaded, sortID, sortDirection)
|
||||
function RerootFolder(uri, newFolder, isThreaded, sortID, sortDirection, viewType)
|
||||
{
|
||||
dump('In reroot folder\n');
|
||||
|
||||
@ -242,7 +246,9 @@ function RerootFolder(uri, newFolder, isThreaded, sortID, sortDirection)
|
||||
|
||||
//Set threaded state
|
||||
ShowThreads(isThreaded);
|
||||
|
||||
|
||||
//Set the view type
|
||||
SetViewType(viewType);
|
||||
|
||||
//Clear the new messages of the old folder
|
||||
var oldFolderURI = folder.getAttribute("ref");
|
||||
@ -854,9 +860,22 @@ function IsSpecialFolder(msgFolder, specialFolderNames)
|
||||
}
|
||||
|
||||
|
||||
function SetViewType(viewType)
|
||||
{
|
||||
//dump("in SetViewType with " + viewType + "\n");
|
||||
if (!viewType || (viewType == "")) {
|
||||
viewType = nsMsgViewType.eShowAll;
|
||||
}
|
||||
|
||||
if(messageView)
|
||||
{
|
||||
messageView.viewType = viewType;
|
||||
}
|
||||
}
|
||||
|
||||
function ShowThreads(showThreads)
|
||||
{
|
||||
dump('in showthreads\n');
|
||||
//dump('in showthreads\n');
|
||||
if(messageView)
|
||||
{
|
||||
messageView.showThreads = showThreads;
|
||||
|
@ -58,7 +58,7 @@
|
||||
CanSubscribe="rdf:http://home.netscape.com/NC-rdf#CanSubscribe"
|
||||
CanFileMessages="rdf:http://home.netscape.com/NC-rdf#CanFileMessages"
|
||||
NoSelect="rdf:http://home.netscape.com/NC-rdf#NoSelect"
|
||||
persist="threaded open sortResource sortDirection">
|
||||
persist="threaded open sortResource sortDirection viewType">
|
||||
<treerow class="tree-folder-row"
|
||||
IsServer="rdf:http://home.netscape.com/NC-rdf#IsServer"
|
||||
HasUnreadMessages="rdf:http://home.netscape.com/NC-rdf#HasUnreadMessages"
|
||||
|
@ -288,12 +288,9 @@ var DefaultController =
|
||||
case "cmd_previousFlaggedMsg":
|
||||
return IsViewNavigationItemEnabled();
|
||||
case "cmd_viewAllMsgs":
|
||||
return true;
|
||||
case "cmd_sortByThread":
|
||||
return (messageView.viewType != viewShowUnread);
|
||||
break;
|
||||
case "cmd_viewUnreadMsgs":
|
||||
return (messageView.showThreads == false);
|
||||
return true;
|
||||
break;
|
||||
case "cmd_undo":
|
||||
case "cmd_redo":
|
||||
@ -816,10 +813,7 @@ function MsgPreviousFlaggedMessage()
|
||||
GoPreviousMessage(navigateFlagged, true);
|
||||
}
|
||||
|
||||
var viewShowAll =0;
|
||||
var viewShowRead = 1;
|
||||
var viewShowUnread =2;
|
||||
var viewShowWatched = 3;
|
||||
var nsMsgViewType = Components.interfaces.nsMsgViewType;
|
||||
|
||||
function MsgViewAllMsgs()
|
||||
{
|
||||
@ -827,8 +821,12 @@ function MsgViewAllMsgs()
|
||||
|
||||
if(messageView)
|
||||
{
|
||||
messageView.viewType = viewShowAll;
|
||||
messageView.showThreads = false;
|
||||
messageView.viewType = nsMsgViewType.eShowAll;
|
||||
|
||||
var folder = GetSelectedFolder();
|
||||
if(folder) {
|
||||
folder.setAttribute("viewType", messageView.viewType);
|
||||
}
|
||||
}
|
||||
RefreshThreadTreeView();
|
||||
}
|
||||
@ -839,8 +837,12 @@ function MsgViewUnreadMsg()
|
||||
|
||||
if(messageView)
|
||||
{
|
||||
messageView.viewType = viewShowUnread;
|
||||
messageView.showThreads = false;
|
||||
messageView.viewType = nsMsgViewType.eShowUnread;
|
||||
|
||||
var folder = GetSelectedFolder();
|
||||
if(folder) {
|
||||
folder.setAttribute("viewType", messageView.viewType);
|
||||
}
|
||||
}
|
||||
|
||||
RefreshThreadTreeView();
|
||||
|
@ -73,12 +73,12 @@ function InitViewMessagesMenu()
|
||||
var allMenuItem = document.getElementById("viewAllMessagesMenuItem");
|
||||
var hidden = allMenuItem.getAttribute("hidden") == "true";
|
||||
if(allMenuItem && !hidden)
|
||||
allMenuItem.setAttribute("checked", messageView.viewType == viewShowAll);
|
||||
allMenuItem.setAttribute("checked", messageView.viewType == nsMsgViewType.eShowAll);
|
||||
|
||||
var unreadMenuItem = document.getElementById("viewUnreadMessagesMenuItem");
|
||||
hidden = unreadMenuItem.getAttribute("hidden") == "true";
|
||||
if(unreadMenuItem && !hidden)
|
||||
unreadMenuItem.setAttribute("checked", messageView.viewType == viewShowUnread);
|
||||
unreadMenuItem.setAttribute("checked", messageView.viewType == nsMsgViewType.eShowUnread);
|
||||
|
||||
}
|
||||
|
||||
|
@ -36,6 +36,7 @@ var gCurrentFolderToReroot;
|
||||
var gCurrentLoadingFolderIsThreaded = false;
|
||||
var gCurrentLoadingFolderSortID ="";
|
||||
var gCurrentLoadingFolderSortDirection = null;
|
||||
var gCurrentLoadingFolderViewType = "";
|
||||
|
||||
var gCurrentDisplayedMessage = null;
|
||||
var gNextMessageAfterDelete = null;
|
||||
@ -110,10 +111,11 @@ var folderListener = {
|
||||
if(msgFolder)
|
||||
{
|
||||
msgFolder.endFolderLoading();
|
||||
RerootFolder(uri, msgFolder, gCurrentLoadingFolderIsThreaded, gCurrentLoadingFolderSortID, gCurrentLoadingFolderSortDirection);
|
||||
RerootFolder(uri, msgFolder, gCurrentLoadingFolderIsThreaded, gCurrentLoadingFolderSortID, gCurrentLoadingFolderSortDirection, gCurrentLoadingFolderViewType);
|
||||
gCurrentLoadingFolderIsThreaded = false;
|
||||
gCurrentLoadingFolderSortID = "";
|
||||
gCurrentLoadingFolderSortDirection = null;
|
||||
gCurrentLoadingFolderViewType = "";
|
||||
|
||||
if (gNextMessageAfterLoad) {
|
||||
gNextMessageAfterLoad = false;
|
||||
|
@ -208,11 +208,6 @@ function ChangeThreadView()
|
||||
}
|
||||
else if(currentView == 'unthreaded')
|
||||
{
|
||||
//if we're in unread messages view, don't allow to go into threaded mode because
|
||||
//we don't support it.
|
||||
if(messageView.viewType == viewShowUnread)
|
||||
return;
|
||||
|
||||
ShowThreads(true);
|
||||
if(folder)
|
||||
folder.setAttribute('threaded', "true");
|
||||
|
@ -28,7 +28,6 @@ nsMsgMailSession.h
|
||||
nsMsgFolderCache.h
|
||||
nsMsgFolderDataSource.h
|
||||
nsMsgMessageDataSource.h
|
||||
nsMessageViewDataSource.h
|
||||
nsMsgAccount.h
|
||||
nsMsgAccountManager.h
|
||||
nsMsgRDFDataSource.h
|
||||
|
@ -43,7 +43,6 @@ CPPSRCS = \
|
||||
nsMsgRDFDataSource.cpp \
|
||||
nsMsgFolderDataSource.cpp \
|
||||
nsMsgMessageDataSource.cpp \
|
||||
nsMessageViewDataSource.cpp \
|
||||
nsMsgAccountManagerDS.cpp \
|
||||
nsMsgRDFUtils.cpp \
|
||||
nsMsgBiffManager.cpp \
|
||||
@ -74,7 +73,6 @@ EXPORTS = \
|
||||
nsMsgFolderDataSource.h \
|
||||
nsMsgFolderCache.h \
|
||||
nsMsgMessageDataSource.h \
|
||||
nsMessageViewDataSource.h \
|
||||
nsMsgAccountManagerDS.h \
|
||||
nsMsgRDFDataSource.h \
|
||||
nsMsgRDFUtils.h \
|
||||
|
@ -37,7 +37,6 @@ EXPORTS= \
|
||||
nsMsgFolderDataSource.h \
|
||||
nsMsgFolderCache.h \
|
||||
nsMsgMessageDataSource.h \
|
||||
nsMessageViewDataSource.h \
|
||||
nsMsgAccount.h \
|
||||
nsMsgAccountManager.h \
|
||||
nsMsgRDFDataSource.h \
|
||||
@ -72,7 +71,6 @@ CPP_OBJS= \
|
||||
.\$(OBJDIR)\nsUrlListenerManager.obj \
|
||||
.\$(OBJDIR)\nsMsgMailSession.obj \
|
||||
.\$(OBJDIR)\nsCopyMessageStreamListener.obj \
|
||||
.\$(OBJDIR)\nsMessageViewDataSource.obj \
|
||||
.\$(OBJDIR)\nsMsgAccountManager.obj \
|
||||
.\$(OBJDIR)\nsMsgAccount.obj \
|
||||
.\$(OBJDIR)\nsMsgFolderDataSource.obj \
|
||||
|
@ -26,10 +26,9 @@
|
||||
#include "nsIMessage.h"
|
||||
#include "nsIMsgFolder.h"
|
||||
#include "nsMsgUtils.h"
|
||||
#include "nsMessageViewDataSource.h"
|
||||
#include "nsEnumeratorUtils.h"
|
||||
|
||||
|
||||
#include "MailNewsTypes.h"
|
||||
#include "MailNewsTypes2.h"
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsMessageView, nsIMessageView)
|
||||
|
||||
@ -37,8 +36,7 @@ nsMessageView::nsMessageView()
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
mShowThreads = PR_FALSE;
|
||||
mViewType = nsIMessageView::eShowAll;
|
||||
|
||||
mViewType = nsMsgViewType::eShowAll;
|
||||
}
|
||||
|
||||
nsMessageView::~nsMessageView()
|
||||
@ -81,94 +79,358 @@ NS_IMETHODIMP nsMessageView::SetShowThreads(PRBool aShowThreads)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessageView::GetMessages(nsIRDFResource *parentResource, nsIMsgWindow* msgWindow, nsISimpleEnumerator **messages)
|
||||
NS_IMETHODIMP nsMessageView::HasMessages(nsIRDFResource *parentResource, nsIMsgWindow* msgWindow, PRBool *hasMessages)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
*messages = nsnull;
|
||||
*hasMessages = PR_FALSE;
|
||||
|
||||
PRUint32 viewType;
|
||||
rv = GetViewType(&viewType);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
nsCOMPtr<nsIMessage> message(do_QueryInterface(parentResource, &rv));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
|
||||
if(mShowThreads)
|
||||
{
|
||||
if(mShowThreads) {
|
||||
nsCOMPtr<nsIMsgFolder> msgfolder;
|
||||
rv = message->GetMsgFolder(getter_AddRefs(msgfolder));
|
||||
if(NS_SUCCEEDED(rv))
|
||||
{
|
||||
if(NS_SUCCEEDED(rv)) {
|
||||
nsCOMPtr<nsIMsgThread> thread;
|
||||
rv = msgfolder->GetThreadForMessage(message, getter_AddRefs(thread));
|
||||
if(NS_SUCCEEDED(rv))
|
||||
{
|
||||
nsCOMPtr<nsISimpleEnumerator> threadMessages;
|
||||
nsMsgKey msgKey;
|
||||
message->GetMessageKey(&msgKey);
|
||||
thread->EnumerateMessages(msgKey, getter_AddRefs(threadMessages));
|
||||
nsCOMPtr<nsMessageFromMsgHdrEnumerator> converter;
|
||||
NS_NewMessageFromMsgHdrEnumerator(threadMessages, msgfolder, getter_AddRefs(converter));
|
||||
PRUint32 viewType;
|
||||
rv = GetViewType(&viewType);
|
||||
if(NS_FAILED(rv)) return rv;
|
||||
|
||||
nsMessageViewMessageEnumerator * messageEnumerator =
|
||||
new nsMessageViewMessageEnumerator(converter, viewType);
|
||||
if(!messageEnumerator)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
NS_ADDREF(messageEnumerator);
|
||||
*messages = messageEnumerator;
|
||||
rv = NS_OK;
|
||||
if(NS_SUCCEEDED(rv)) {
|
||||
nsMsgKey msgKey;
|
||||
message->GetMessageKey(&msgKey);
|
||||
|
||||
rv = thread->HasMessagesOfType(msgKey, viewType, hasMessages);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
nsCOMPtr<nsIMsgFolder> folder(do_QueryInterface(parentResource));
|
||||
else {
|
||||
nsCOMPtr<nsIMsgFolder> folder(do_QueryInterface(parentResource));
|
||||
if(folder) {
|
||||
if(mShowThreads) {
|
||||
rv = folder->HasThreads(msgWindow, hasMessages);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
}
|
||||
else {
|
||||
rv = folder->HasMessagesOfType(msgWindow, viewType, hasMessages);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(folder)
|
||||
{
|
||||
if(mShowThreads)
|
||||
{
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP nsMessageView::GetMessages(nsIRDFResource *parentResource, nsIMsgWindow* msgWindow, nsISimpleEnumerator **messages)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
PRUint32 viewType;
|
||||
rv = GetViewType(&viewType);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
*messages = nsnull;
|
||||
nsCOMPtr<nsIMessage> message(do_QueryInterface(parentResource, &rv));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
if(mShowThreads) {
|
||||
nsCOMPtr<nsIMsgFolder> msgfolder;
|
||||
rv = message->GetMsgFolder(getter_AddRefs(msgfolder));
|
||||
if(NS_SUCCEEDED(rv)) {
|
||||
nsCOMPtr<nsIMsgThread> thread;
|
||||
rv = msgfolder->GetThreadForMessage(message, getter_AddRefs(thread));
|
||||
if(NS_SUCCEEDED(rv)) {
|
||||
nsCOMPtr<nsISimpleEnumerator> threadMessages;
|
||||
nsMsgKey msgKey;
|
||||
message->GetMessageKey(&msgKey);
|
||||
#ifdef HAVE_4X_UNREAD_THREADS
|
||||
switch (viewType) {
|
||||
case nsMsgViewType::eShowAll:
|
||||
thread->EnumerateMessages(msgKey, getter_AddRefs(threadMessages));
|
||||
break;
|
||||
case nsMsgViewType::eShowUnread:
|
||||
thread->EnumerateUnreadMessages(msgKey, getter_AddRefs(threadMessages));
|
||||
break;
|
||||
case nsMsgViewType::eShowRead:
|
||||
case nsMsgViewType::eShowWatched:
|
||||
default:
|
||||
NS_ENSURE_SUCCESS(NS_ERROR_UNEXPECTED,NS_ERROR_UNEXPECTED);
|
||||
break;
|
||||
}
|
||||
#else
|
||||
// Threads with unread
|
||||
thread->EnumerateMessages(msgKey, getter_AddRefs(threadMessages));
|
||||
#endif /* HAVE_4X_UNREAD_THREADS */
|
||||
nsCOMPtr<nsMessageFromMsgHdrEnumerator> converter;
|
||||
NS_NewMessageFromMsgHdrEnumerator(threadMessages, msgfolder, getter_AddRefs(converter));
|
||||
|
||||
// we've done the work (by calling EnumerateMessages()
|
||||
// or EnumerateUnreadMessages(), based on viewType)
|
||||
// so we want all messages that are left.
|
||||
nsMessageViewMessageEnumerator * messageEnumerator =
|
||||
new nsMessageViewMessageEnumerator(converter, nsMsgViewType::eShowAll);
|
||||
|
||||
if(!messageEnumerator) return NS_ERROR_OUT_OF_MEMORY;
|
||||
NS_ADDREF(messageEnumerator);
|
||||
*messages = messageEnumerator;
|
||||
rv = NS_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
nsCOMPtr<nsIMsgFolder> folder(do_QueryInterface(parentResource));
|
||||
if(folder) {
|
||||
if(mShowThreads) {
|
||||
nsCOMPtr<nsISimpleEnumerator> threads;
|
||||
rv = folder->GetThreads(msgWindow, getter_AddRefs(threads));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
rv = folder->GetThreadsOfType(msgWindow, viewType, getter_AddRefs(threads));
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
nsMessageViewThreadEnumerator * threadEnumerator =
|
||||
new nsMessageViewThreadEnumerator(threads, folder);
|
||||
if(!threadEnumerator)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
if(!threadEnumerator) return NS_ERROR_OUT_OF_MEMORY;
|
||||
NS_ADDREF(threadEnumerator);
|
||||
*messages = threadEnumerator;
|
||||
rv = NS_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
nsCOMPtr<nsISimpleEnumerator> folderMessages;
|
||||
rv = folder->GetMessages(msgWindow, getter_AddRefs(folderMessages));
|
||||
if (NS_SUCCEEDED(rv))
|
||||
{
|
||||
PRUint32 viewType;
|
||||
rv = GetViewType(&viewType);
|
||||
if(NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsMessageViewMessageEnumerator * messageEnumerator =
|
||||
new nsMessageViewMessageEnumerator(folderMessages, viewType);
|
||||
if(!messageEnumerator)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
if(!messageEnumerator) return NS_ERROR_OUT_OF_MEMORY;
|
||||
NS_ADDREF(messageEnumerator);
|
||||
*messages = messageEnumerator;
|
||||
rv = NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
if(!*messages)
|
||||
{
|
||||
|
||||
if(!*messages) {
|
||||
//return empty array
|
||||
nsCOMPtr<nsISupportsArray> assertions;
|
||||
rv = NS_NewISupportsArray(getter_AddRefs(assertions));
|
||||
if(NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
rv = NS_NewArrayEnumerator(messages, assertions);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
////////////////////////// nsMessageViewMessageEnumerator //////////////////
|
||||
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsMessageViewMessageEnumerator, nsISimpleEnumerator)
|
||||
|
||||
nsMessageViewMessageEnumerator::nsMessageViewMessageEnumerator(nsISimpleEnumerator *srcEnumerator,
|
||||
PRUint32 viewType)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
|
||||
mSrcEnumerator = dont_QueryInterface(srcEnumerator);
|
||||
|
||||
mViewType = viewType;
|
||||
}
|
||||
nsMessageViewMessageEnumerator::~nsMessageViewMessageEnumerator()
|
||||
{
|
||||
//member variables are nsCOMPtr's.
|
||||
}
|
||||
|
||||
|
||||
/** Next will advance the list. will return failed if already at end
|
||||
*/
|
||||
NS_IMETHODIMP nsMessageViewMessageEnumerator::GetNext(nsISupports **aItem)
|
||||
{
|
||||
if (!aItem)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
if(!mCurMsg)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
*aItem = mCurMsg;
|
||||
NS_ADDREF(*aItem);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/** GetNext will return the next item it will fail if the list is empty
|
||||
* @param aItem return value
|
||||
*/
|
||||
/** return if the collection is at the end. that is the beginning following a call to Prev
|
||||
* and it is the end of the list following a call to next
|
||||
* @param aItem return value
|
||||
*/
|
||||
NS_IMETHODIMP nsMessageViewMessageEnumerator::HasMoreElements(PRBool *aResult)
|
||||
{
|
||||
if(!aResult)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
nsresult rv = SetAtNextItem();
|
||||
*aResult = NS_SUCCEEDED(rv);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//This function sets mSrcEnumerator at the next item that fits
|
||||
//the criteria for this enumerator. If there are no more items
|
||||
//returns NS_ERROR_FAILURE
|
||||
nsresult nsMessageViewMessageEnumerator::SetAtNextItem()
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsISupports> currentItem;
|
||||
nsCOMPtr<nsIMessage> message;
|
||||
|
||||
PRBool hasMore = PR_FALSE;
|
||||
while(NS_SUCCEEDED(mSrcEnumerator->HasMoreElements(&hasMore)) && hasMore)
|
||||
{
|
||||
rv = mSrcEnumerator->GetNext(getter_AddRefs(currentItem));
|
||||
PRBool successful = PR_FALSE;
|
||||
if(NS_FAILED(rv))
|
||||
break;
|
||||
|
||||
message = do_QueryInterface(currentItem, &rv);
|
||||
if(NS_SUCCEEDED(rv))
|
||||
{
|
||||
PRBool meetsCriteria;
|
||||
rv = MeetsCriteria(message, &meetsCriteria);
|
||||
if(NS_SUCCEEDED(rv) & meetsCriteria)
|
||||
successful = PR_TRUE;
|
||||
}
|
||||
if(successful)
|
||||
{
|
||||
mCurMsg = do_QueryInterface(currentItem, &rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
}
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsresult nsMessageViewMessageEnumerator::MeetsCriteria(nsIMessage *message, PRBool *meetsCriteria)
|
||||
{
|
||||
|
||||
if(!meetsCriteria)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
*meetsCriteria = PR_FALSE;
|
||||
|
||||
if(mViewType == nsMsgViewType::eShowAll)
|
||||
{
|
||||
*meetsCriteria = PR_TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
PRUint32 flags;
|
||||
message->GetFlags(&flags);
|
||||
|
||||
if(mViewType == nsMsgViewType::eShowRead)
|
||||
*meetsCriteria = flags & MSG_FLAG_READ;
|
||||
else if(mViewType == nsMsgViewType::eShowUnread)
|
||||
*meetsCriteria = !(flags & MSG_FLAG_READ);
|
||||
else if(mViewType == nsMsgViewType::eShowWatched)
|
||||
*meetsCriteria = flags & MSG_FLAG_WATCHED;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
////////////////////////// nsMessageViewThreadEnumerator //////////////////
|
||||
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsMessageViewThreadEnumerator, nsISimpleEnumerator)
|
||||
|
||||
nsMessageViewThreadEnumerator::nsMessageViewThreadEnumerator(nsISimpleEnumerator *threads,
|
||||
nsIMsgFolder *srcFolder)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
|
||||
mThreads = do_QueryInterface(threads);
|
||||
mFolder = do_QueryInterface(srcFolder);
|
||||
mNeedToPrefetch = PR_TRUE;
|
||||
}
|
||||
|
||||
nsMessageViewThreadEnumerator::~nsMessageViewThreadEnumerator()
|
||||
{
|
||||
//member variables are nsCOMPtr's
|
||||
}
|
||||
|
||||
/** Next will advance the list. will return failed if already at end
|
||||
*/
|
||||
NS_IMETHODIMP nsMessageViewThreadEnumerator::GetNext(nsISupports **aItem)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
if(!mMessages)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (mNeedToPrefetch)
|
||||
rv = Prefetch();
|
||||
if (NS_SUCCEEDED(rv) && mMessages)
|
||||
rv = mMessages->GetNext(aItem);
|
||||
// NS_ASSERTION(NS_SUCCEEDED(rv),"getnext shouldn't fail");
|
||||
mNeedToPrefetch = PR_TRUE;
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult nsMessageViewThreadEnumerator::Prefetch()
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
//then check to see if the there are no more messages in last thread
|
||||
//Get the next thread
|
||||
rv = mThreads->GetNext(getter_AddRefs(mCurThread));
|
||||
if(NS_SUCCEEDED(rv))
|
||||
{
|
||||
rv = GetMessagesForCurrentThread();
|
||||
mNeedToPrefetch = PR_FALSE;
|
||||
}
|
||||
else
|
||||
mMessages = nsnull;
|
||||
return rv;
|
||||
}
|
||||
|
||||
/** return if the collection is at the end. that is the beginning following a call to Prev
|
||||
* and it is the end of the list following a call to next
|
||||
* @param aItem return value
|
||||
*/
|
||||
NS_IMETHODIMP nsMessageViewThreadEnumerator::HasMoreElements(PRBool *aResult)
|
||||
{
|
||||
if (!aResult)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
if (mNeedToPrefetch)
|
||||
Prefetch();
|
||||
//First check to see if there are no more threads
|
||||
if (mMessages)
|
||||
rv = mMessages->HasMoreElements(aResult);
|
||||
else
|
||||
*aResult = nsnull;
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult nsMessageViewThreadEnumerator::GetMessagesForCurrentThread()
|
||||
{
|
||||
nsCOMPtr<nsIMsgThread> thread;
|
||||
nsresult rv = NS_OK;
|
||||
if(mCurThread)
|
||||
{
|
||||
thread = do_QueryInterface(mCurThread, &rv);
|
||||
if(NS_SUCCEEDED(rv))
|
||||
{
|
||||
nsCOMPtr<nsISimpleEnumerator> msgHdrs;
|
||||
rv = thread->EnumerateMessages(nsMsgKey_None, getter_AddRefs(msgHdrs));
|
||||
nsMessageFromMsgHdrEnumerator *messages;
|
||||
NS_NewMessageFromMsgHdrEnumerator(msgHdrs, mFolder, &messages);
|
||||
mMessages = do_QueryInterface(messages, &rv);
|
||||
NS_IF_RELEASE(messages);
|
||||
}
|
||||
}
|
||||
else
|
||||
mMessages = nsnull;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -24,6 +24,9 @@
|
||||
#define _nsMessageView_h
|
||||
|
||||
#include "nsIMessageView.h"
|
||||
#include "nsIEnumerator.h"
|
||||
#include "nsIMsgFolder.h"
|
||||
#include "nsIMessage.h"
|
||||
|
||||
class nsMessageView : public nsIMessageView {
|
||||
|
||||
@ -42,6 +45,55 @@ protected:
|
||||
|
||||
};
|
||||
|
||||
class nsMessageViewMessageEnumerator: public nsISimpleEnumerator
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
nsMessageViewMessageEnumerator(nsISimpleEnumerator *srcEnumerator, PRUint32 viewType);
|
||||
virtual ~nsMessageViewMessageEnumerator();
|
||||
|
||||
NS_DECL_NSISIMPLEENUMERATOR
|
||||
|
||||
protected:
|
||||
nsresult SetAtNextItem();
|
||||
nsresult MeetsCriteria(nsIMessage *message, PRBool *meetsCriteria);
|
||||
|
||||
protected:
|
||||
|
||||
nsCOMPtr<nsISimpleEnumerator> mSrcEnumerator;
|
||||
nsCOMPtr<nsISupports> mCurMsg;
|
||||
nsCOMPtr<nsISupports> mCurThread;
|
||||
PRUint32 mViewType;
|
||||
|
||||
};
|
||||
|
||||
class nsMessageViewThreadEnumerator: public nsISimpleEnumerator
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
nsMessageViewThreadEnumerator(nsISimpleEnumerator *srcEnumerator, nsIMsgFolder *srcFolder);
|
||||
virtual ~nsMessageViewThreadEnumerator();
|
||||
|
||||
NS_DECL_NSISIMPLEENUMERATOR
|
||||
|
||||
protected:
|
||||
nsresult GetMessagesForCurrentThread();
|
||||
nsresult Prefetch();
|
||||
|
||||
protected:
|
||||
|
||||
nsCOMPtr<nsISimpleEnumerator> mThreads;
|
||||
nsCOMPtr<nsISimpleEnumerator> mMessages;
|
||||
nsCOMPtr<nsISupports> mCurThread;
|
||||
nsCOMPtr<nsIMsgFolder> mFolder;
|
||||
PRBool mNeedToPrefetch;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -1,816 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Pierre Phaneuf <pp@ludusdesign.com>
|
||||
*/
|
||||
|
||||
#include "nsMessageViewDataSource.h"
|
||||
#include "nsEnumeratorUtils.h"
|
||||
#include "nsRDFCID.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsXPIDLString.h"
|
||||
#include "nsMsgRDFUtils.h"
|
||||
#include "nsMsgUtils.h"
|
||||
|
||||
|
||||
#include "plstr.h"
|
||||
|
||||
static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID);
|
||||
|
||||
|
||||
nsIRDFResource* nsMessageViewDataSource::kNC_MessageChild = nsnull;
|
||||
nsIRDFResource* nsMessageViewDataSource::kNC_Subject = nsnull;
|
||||
nsIRDFResource* nsMessageViewDataSource::kNC_Sender = nsnull;
|
||||
nsIRDFResource* nsMessageViewDataSource::kNC_Date = nsnull;
|
||||
nsIRDFResource* nsMessageViewDataSource::kNC_Status = nsnull;
|
||||
|
||||
NS_IMPL_ADDREF(nsMessageViewDataSource)
|
||||
|
||||
NS_IMETHODIMP_(nsrefcnt)
|
||||
nsMessageViewDataSource::Release()
|
||||
{
|
||||
// We need a special implementation of Release(). The composite
|
||||
// datasource holds a reference to mDataSource, and mDataSource
|
||||
// holds a reference _back_ to the composite datasource by way of
|
||||
// the "observer".
|
||||
NS_PRECONDITION(PRInt32(mRefCnt) > 0, "duplicate release");
|
||||
--mRefCnt;
|
||||
|
||||
// When the number of references is one, we know that all that
|
||||
// remains is the circular references from mDataSource back to
|
||||
// us. Release it.
|
||||
if (mRefCnt == 1 && mDataSource) {
|
||||
mDataSource->RemoveObserver(this);
|
||||
return 0;
|
||||
}
|
||||
else if (mRefCnt == 0) {
|
||||
delete this;
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
return mRefCnt;
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMessageViewDataSource::QueryInterface(REFNSIID iid, void** result)
|
||||
{
|
||||
if (! result)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
*result = nsnull;
|
||||
if (iid.Equals(NS_GET_IID(nsIRDFCompositeDataSource)) ||
|
||||
iid.Equals(NS_GET_IID(nsIRDFDataSource)) ||
|
||||
iid.Equals(NS_GET_IID(nsISupports)))
|
||||
{
|
||||
*result = NS_STATIC_CAST(nsIRDFCompositeDataSource*, this);
|
||||
NS_ADDREF_THIS();
|
||||
}
|
||||
if(*result)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return NS_NOINTERFACE;
|
||||
}
|
||||
|
||||
nsMessageViewDataSource::nsMessageViewDataSource(void)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
mObservers = nsnull;
|
||||
mViewType = nsIMessageView::eShowAll;
|
||||
mInitialized = PR_FALSE;
|
||||
mShowThreads = PR_FALSE;
|
||||
}
|
||||
|
||||
nsMessageViewDataSource::~nsMessageViewDataSource (void)
|
||||
{
|
||||
mRDFService->UnregisterDataSource(this);
|
||||
|
||||
nsrefcnt refcnt;
|
||||
NS_RELEASE2(kNC_MessageChild, refcnt);
|
||||
NS_RELEASE2(kNC_Subject, refcnt);
|
||||
NS_RELEASE2(kNC_Date, refcnt);
|
||||
NS_RELEASE2(kNC_Sender, refcnt);
|
||||
NS_RELEASE2(kNC_Status, refcnt);
|
||||
nsServiceManager::ReleaseService(kRDFServiceCID, mRDFService); // XXX probably need shutdown listener here
|
||||
mRDFService = nsnull;
|
||||
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsMessageViewDataSource::Init()
|
||||
{
|
||||
if (mInitialized)
|
||||
return NS_ERROR_ALREADY_INITIALIZED;
|
||||
|
||||
nsresult rv;
|
||||
rv = nsServiceManager::GetService(kRDFServiceCID,
|
||||
NS_GET_IID(nsIRDFService),
|
||||
(nsISupports**) &mRDFService); // XXX probably need shutdown listener here
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
mRDFService->RegisterDataSource(this, PR_FALSE);
|
||||
|
||||
if (! kNC_MessageChild) {
|
||||
mRDFService->GetResource(NC_RDF_MESSAGECHILD, &kNC_MessageChild);
|
||||
mRDFService->GetResource(NC_RDF_SUBJECT, &kNC_Subject);
|
||||
mRDFService->GetResource(NC_RDF_DATE, &kNC_Date);
|
||||
mRDFService->GetResource(NC_RDF_SENDER, &kNC_Sender);
|
||||
mRDFService->GetResource(NC_RDF_STATUS , &kNC_Status);
|
||||
}
|
||||
mInitialized = PR_TRUE;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessageViewDataSource::GetURI(char* *uri)
|
||||
{
|
||||
if ((*uri = nsXPIDLCString::Copy("rdf:mail-messageview")) == nsnull)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
else
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessageViewDataSource::GetSource(nsIRDFResource* property,
|
||||
nsIRDFNode* target,
|
||||
PRBool tv,
|
||||
nsIRDFResource** source /* out */)
|
||||
{
|
||||
if(mDataSource)
|
||||
return mDataSource->GetSource(property, target, tv, source);
|
||||
else
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessageViewDataSource::GetTarget(nsIRDFResource* source,
|
||||
nsIRDFResource* property,
|
||||
PRBool tv,
|
||||
nsIRDFNode** target)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
//First see if we handle this
|
||||
nsCOMPtr<nsIMessage> message(do_QueryInterface(source));
|
||||
if(message)
|
||||
{
|
||||
rv = createMessageNode(message, property, target);
|
||||
if(NS_SUCCEEDED(rv) && rv != NS_RDF_NO_VALUE)
|
||||
return rv;
|
||||
}
|
||||
|
||||
if(mDataSource)
|
||||
return mDataSource->GetTarget(source, property, tv, target);
|
||||
else
|
||||
return NS_RDF_NO_VALUE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessageViewDataSource::GetSources(nsIRDFResource* property,
|
||||
nsIRDFNode* target,
|
||||
PRBool tv,
|
||||
nsISimpleEnumerator** sources)
|
||||
{
|
||||
if(mDataSource)
|
||||
return mDataSource->GetSources(property, target, tv, sources);
|
||||
else
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessageViewDataSource::GetTargets(nsIRDFResource* source,
|
||||
nsIRDFResource* property,
|
||||
PRBool tv,
|
||||
nsISimpleEnumerator** targets)
|
||||
{
|
||||
if(mDataSource)
|
||||
return mDataSource->GetTargets(source, property, tv, targets);
|
||||
else
|
||||
return NS_RDF_NO_VALUE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessageViewDataSource::Assert(nsIRDFResource* source,
|
||||
nsIRDFResource* property,
|
||||
nsIRDFNode* target,
|
||||
PRBool tv)
|
||||
{
|
||||
if(mDataSource)
|
||||
return mDataSource->Assert(source, property, target, tv);
|
||||
else
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessageViewDataSource::Unassert(nsIRDFResource* source,
|
||||
nsIRDFResource* property,
|
||||
nsIRDFNode* target)
|
||||
{
|
||||
if(mDataSource)
|
||||
return mDataSource->Unassert(source, property, target);
|
||||
else
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessageViewDataSource::Change(nsIRDFResource* aSource,
|
||||
nsIRDFResource* aProperty,
|
||||
nsIRDFNode* aOldTarget,
|
||||
nsIRDFNode* aNewTarget)
|
||||
{
|
||||
if (mDataSource)
|
||||
return mDataSource->Change(aSource, aProperty, aOldTarget, aNewTarget);
|
||||
else
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP nsMessageViewDataSource::Move(nsIRDFResource* aOldSource,
|
||||
nsIRDFResource* aNewSource,
|
||||
nsIRDFResource* aProperty,
|
||||
nsIRDFNode* aTarget)
|
||||
{
|
||||
if (mDataSource)
|
||||
return mDataSource->Move(aOldSource, aNewSource, aProperty, aTarget);
|
||||
else
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessageViewDataSource::HasAssertion(nsIRDFResource* source,
|
||||
nsIRDFResource* property,
|
||||
nsIRDFNode* target,
|
||||
PRBool tv,
|
||||
PRBool* hasAssertion)
|
||||
{
|
||||
if(mDataSource)
|
||||
return mDataSource->HasAssertion(source, property, target, tv, hasAssertion);
|
||||
else
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessageViewDataSource::AddObserver(nsIRDFObserver* n)
|
||||
{
|
||||
if (! mObservers) {
|
||||
nsresult rv = NS_NewISupportsArray(getter_AddRefs(mObservers));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
mObservers->AppendElement(n);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessageViewDataSource::RemoveObserver(nsIRDFObserver* n)
|
||||
{
|
||||
if (! mObservers)
|
||||
return NS_OK;
|
||||
mObservers->RemoveElement(n);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsMessageViewDataSource::GetMessageEnumerator(nsIMessage* message, nsISimpleEnumerator* *result)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIMsgFolder> folder;
|
||||
rv = message->GetMsgFolder(getter_AddRefs(folder));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
NS_ASSERTION(folder, "GetMsgFolder returned NS_OK, but no folder");
|
||||
|
||||
nsCOMPtr<nsIMsgThread> thread;
|
||||
rv = folder->GetThreadForMessage(message, getter_AddRefs(thread));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
NS_ASSERTION(folder, "GetThreadForMessage returned NS_OK, but no thread");
|
||||
|
||||
nsMsgKey msgKey;
|
||||
rv = message->GetMessageKey(&msgKey);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCOMPtr<nsISimpleEnumerator> messages;
|
||||
rv = thread->EnumerateMessages(msgKey, getter_AddRefs(messages));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCOMPtr<nsMessageFromMsgHdrEnumerator> converter;
|
||||
rv = NS_NewMessageFromMsgHdrEnumerator(messages, folder, getter_AddRefs(converter));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsMessageViewMessageEnumerator* messageEnumerator =
|
||||
new nsMessageViewMessageEnumerator(converter, nsIMessageView::eShowAll);
|
||||
if (!messageEnumerator)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
NS_ADDREF(messageEnumerator);
|
||||
*result = messageEnumerator;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMessageViewDataSource::HasArcIn(nsIRDFNode *aNode, nsIRDFResource *aArc, PRBool *result)
|
||||
{
|
||||
*result = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMessageViewDataSource::HasArcOut(nsIRDFResource *aSource, nsIRDFResource *aArc, PRBool *result)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIMessage> message;
|
||||
if(mShowThreads && NS_SUCCEEDED(aSource->QueryInterface(NS_GET_IID(nsIMessage), getter_AddRefs(message))))
|
||||
{
|
||||
if (aArc == kNC_Subject ||
|
||||
aArc == kNC_Sender ||
|
||||
aArc == kNC_Date ||
|
||||
aArc == kNC_Status) {
|
||||
*result = PR_TRUE;
|
||||
return NS_OK;
|
||||
}
|
||||
else if (aArc == kNC_MessageChild) {
|
||||
nsCOMPtr<nsISimpleEnumerator> messageEnumerator;
|
||||
rv = GetMessageEnumerator(message, getter_AddRefs(messageEnumerator));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
PRBool hasMore = PR_FALSE;
|
||||
if (NS_SUCCEEDED(messageEnumerator->HasMoreElements(&hasMore)) && hasMore) {
|
||||
*result = PR_TRUE;
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mDataSource)
|
||||
return mDataSource->HasArcOut(aSource, aArc, result);
|
||||
else
|
||||
*result = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessageViewDataSource::ArcLabelsIn(nsIRDFNode* node,
|
||||
nsISimpleEnumerator** labels)
|
||||
{
|
||||
if(mDataSource)
|
||||
return mDataSource->ArcLabelsIn(node, labels);
|
||||
else
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessageViewDataSource::ArcLabelsOut(nsIRDFResource* source,
|
||||
nsISimpleEnumerator** labels)
|
||||
{
|
||||
nsCOMPtr<nsIMessage> message;
|
||||
if(mShowThreads && NS_SUCCEEDED(source->QueryInterface(NS_GET_IID(nsIMessage), getter_AddRefs(message))))
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsISupportsArray> arcs;
|
||||
NS_NewISupportsArray(getter_AddRefs(arcs));
|
||||
if (arcs == nsnull)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
arcs->AppendElement(kNC_Subject);
|
||||
arcs->AppendElement(kNC_Sender);
|
||||
arcs->AppendElement(kNC_Date);
|
||||
arcs->AppendElement(kNC_Status);
|
||||
|
||||
nsCOMPtr<nsISimpleEnumerator> messageEnumerator;
|
||||
rv = GetMessageEnumerator(message, getter_AddRefs(messageEnumerator));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
PRBool hasMore = PR_FALSE;
|
||||
if (NS_SUCCEEDED(messageEnumerator->HasMoreElements(&hasMore)) && hasMore) {
|
||||
arcs->AppendElement(kNC_MessageChild);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_NewArrayEnumerator(labels, arcs);
|
||||
}
|
||||
if(mDataSource)
|
||||
return mDataSource->ArcLabelsOut(source, labels);
|
||||
else
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessageViewDataSource::GetAllResources(nsISimpleEnumerator** aCursor)
|
||||
{
|
||||
if(mDataSource)
|
||||
return mDataSource->GetAllResources(aCursor);
|
||||
else
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessageViewDataSource::GetAllCommands(nsIRDFResource* source,
|
||||
nsIEnumerator/*<nsIRDFResource>*/** commands)
|
||||
{
|
||||
if(mDataSource)
|
||||
return mDataSource->GetAllCommands(source, commands);
|
||||
else
|
||||
return NS_OK;
|
||||
}
|
||||
NS_IMETHODIMP nsMessageViewDataSource::GetAllCmds(nsIRDFResource* source,
|
||||
nsISimpleEnumerator/*<nsIRDFResource>*/** commands)
|
||||
{
|
||||
if(mDataSource)
|
||||
return mDataSource->GetAllCmds(source, commands);
|
||||
else
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessageViewDataSource::IsCommandEnabled(nsISupportsArray/*<nsIRDFResource>*/* aSources,
|
||||
nsIRDFResource* aCommand,
|
||||
nsISupportsArray/*<nsIRDFResource>*/* aArguments,
|
||||
PRBool* aResult)
|
||||
{
|
||||
if(mDataSource)
|
||||
return mDataSource->IsCommandEnabled(aSources, aCommand, aArguments, aResult);
|
||||
else
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessageViewDataSource::DoCommand(nsISupportsArray/*<nsIRDFResource>*/* aSources,
|
||||
nsIRDFResource* aCommand,
|
||||
nsISupportsArray/*<nsIRDFResource>*/* aArguments)
|
||||
{
|
||||
if(mDataSource)
|
||||
return mDataSource->DoCommand(aSources, aCommand, aArguments);
|
||||
else
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMessageViewDataSource::GetAllowNegativeAssertions(PRBool *aAllowNegativeAssertions)
|
||||
{
|
||||
// *aAllowNegativeAssertions = mAllowNegativeAssertions;
|
||||
*aAllowNegativeAssertions = PR_TRUE; // XXX fix build bustage
|
||||
return(NS_OK);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMessageViewDataSource::SetAllowNegativeAssertions(PRBool aAllowNegativeAssertions)
|
||||
{
|
||||
// mAllowNegativeAssertions = aAllowNegativeAssertions;
|
||||
return(NS_OK);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMessageViewDataSource::GetCoalesceDuplicateArcs(PRBool *aCoalesceDuplicateArcs)
|
||||
{
|
||||
// *aCoalesceDuplicateArcs = mCoalesceDuplicateArcs;
|
||||
*aCoalesceDuplicateArcs = PR_TRUE; // XXX fix build bustage
|
||||
return(NS_OK);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMessageViewDataSource::SetCoalesceDuplicateArcs(PRBool aCoalesceDuplicateArcs)
|
||||
{
|
||||
// mCoalesceDuplicateArcs = aCoalesceDuplicateArcs;
|
||||
return(NS_OK);
|
||||
}
|
||||
|
||||
//We're only going to allow one datasource at a time.
|
||||
NS_IMETHODIMP nsMessageViewDataSource::AddDataSource(nsIRDFDataSource* source)
|
||||
{
|
||||
if(mDataSource)
|
||||
RemoveDataSource(mDataSource);
|
||||
|
||||
mDataSource = dont_QueryInterface(source);
|
||||
|
||||
mDataSource->AddObserver(this);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessageViewDataSource::RemoveDataSource(nsIRDFDataSource* source)
|
||||
{
|
||||
mDataSource->RemoveObserver(this);
|
||||
mDataSource = null_nsCOMPtr();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessageViewDataSource::GetDataSources(nsISimpleEnumerator** _result)
|
||||
{
|
||||
return NS_NewSingletonEnumerator(_result, mDataSource);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessageViewDataSource::OnAssert(nsIRDFDataSource* aDataSource,
|
||||
nsIRDFResource* subject,
|
||||
nsIRDFResource* predicate,
|
||||
nsIRDFNode* object)
|
||||
{
|
||||
if (mObservers) {
|
||||
PRUint32 count;
|
||||
nsresult rv = mObservers->Count(&count);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
for (PRInt32 i = count - 1; i >= 0; --i) {
|
||||
nsIRDFObserver* obs = (nsIRDFObserver*) mObservers->ElementAt(i);
|
||||
obs->OnAssert(this, subject, predicate, object);
|
||||
NS_RELEASE(obs);
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessageViewDataSource::OnUnassert(nsIRDFDataSource* aDataSource,
|
||||
nsIRDFResource* subject,
|
||||
nsIRDFResource* predicate,
|
||||
nsIRDFNode* object)
|
||||
{
|
||||
if (mObservers) {
|
||||
PRUint32 count;
|
||||
nsresult rv = mObservers->Count(&count);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
for (PRInt32 i = PRInt32(count) - 1; i >= 0; --i) {
|
||||
nsIRDFObserver* obs = (nsIRDFObserver*) mObservers->ElementAt(i);
|
||||
obs->OnUnassert(this, subject, predicate, object);
|
||||
NS_RELEASE(obs);
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP nsMessageViewDataSource::OnChange(nsIRDFDataSource* aDataSource,
|
||||
nsIRDFResource* aSource,
|
||||
nsIRDFResource* aProperty,
|
||||
nsIRDFNode* aOldTarget,
|
||||
nsIRDFNode* aNewTarget)
|
||||
{
|
||||
if (mObservers) {
|
||||
PRUint32 count;
|
||||
nsresult rv = mObservers->Count(&count);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
for (PRInt32 i = PRInt32(count) - 1; i >= 0; --i) {
|
||||
nsIRDFObserver* obs = (nsIRDFObserver*) mObservers->ElementAt(i);
|
||||
obs->OnChange(this, aSource, aProperty, aOldTarget, aNewTarget);
|
||||
NS_RELEASE(obs);
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP nsMessageViewDataSource::OnMove(nsIRDFDataSource* aDataSource,
|
||||
nsIRDFResource* aOldSource,
|
||||
nsIRDFResource* aNewSource,
|
||||
nsIRDFResource* aProperty,
|
||||
nsIRDFNode* aTarget)
|
||||
{
|
||||
if (mObservers) {
|
||||
PRUint32 count;
|
||||
nsresult rv = mObservers->Count(&count);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
for (PRInt32 i = PRInt32(count) - 1; i >= 0; --i) {
|
||||
nsIRDFObserver* obs = (nsIRDFObserver*) mObservers->ElementAt(i);
|
||||
obs->OnMove(aDataSource, aOldSource, aNewSource, aProperty, aTarget);
|
||||
NS_RELEASE(obs);
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessageViewDataSource::BeginUpdateBatch(nsIRDFDataSource* aDataSource)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMessageViewDataSource::EndUpdateBatch(nsIRDFDataSource* aDataSource)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsMessageViewDataSource::createMessageNode(nsIMessage *message,
|
||||
nsIRDFResource *property,
|
||||
nsIRDFNode **target)
|
||||
{
|
||||
return NS_RDF_NO_VALUE;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////// nsMessageViewMessageEnumerator //////////////////
|
||||
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsMessageViewMessageEnumerator, nsISimpleEnumerator)
|
||||
|
||||
nsMessageViewMessageEnumerator::nsMessageViewMessageEnumerator(nsISimpleEnumerator *srcEnumerator,
|
||||
PRUint32 showStatus)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
|
||||
mSrcEnumerator = dont_QueryInterface(srcEnumerator);
|
||||
|
||||
mShowStatus = showStatus;
|
||||
}
|
||||
nsMessageViewMessageEnumerator::~nsMessageViewMessageEnumerator()
|
||||
{
|
||||
//member variables are nsCOMPtr's.
|
||||
}
|
||||
|
||||
|
||||
/** Next will advance the list. will return failed if already at end
|
||||
*/
|
||||
NS_IMETHODIMP nsMessageViewMessageEnumerator::GetNext(nsISupports **aItem)
|
||||
{
|
||||
if (!aItem)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
if(!mCurMsg)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
*aItem = mCurMsg;
|
||||
NS_ADDREF(*aItem);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/** GetNext will return the next item it will fail if the list is empty
|
||||
* @param aItem return value
|
||||
*/
|
||||
/** return if the collection is at the end. that is the beginning following a call to Prev
|
||||
* and it is the end of the list following a call to next
|
||||
* @param aItem return value
|
||||
*/
|
||||
NS_IMETHODIMP nsMessageViewMessageEnumerator::HasMoreElements(PRBool *aResult)
|
||||
{
|
||||
if(!aResult)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
nsresult rv = SetAtNextItem();
|
||||
*aResult = NS_SUCCEEDED(rv);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//This function sets mSrcEnumerator at the next item that fits
|
||||
//the criteria for this enumerator. If there are no more items
|
||||
//returns NS_ERROR_FAILURE
|
||||
nsresult nsMessageViewMessageEnumerator::SetAtNextItem()
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsISupports> currentItem;
|
||||
nsCOMPtr<nsIMessage> message;
|
||||
|
||||
PRBool hasMore = PR_FALSE;
|
||||
while(NS_SUCCEEDED(mSrcEnumerator->HasMoreElements(&hasMore)) && hasMore)
|
||||
{
|
||||
rv = mSrcEnumerator->GetNext(getter_AddRefs(currentItem));
|
||||
PRBool successful = PR_FALSE;
|
||||
if(NS_FAILED(rv))
|
||||
break;
|
||||
|
||||
message = do_QueryInterface(currentItem, &rv);
|
||||
if(NS_SUCCEEDED(rv))
|
||||
{
|
||||
PRBool meetsCriteria;
|
||||
rv = MeetsCriteria(message, &meetsCriteria);
|
||||
if(NS_SUCCEEDED(rv) & meetsCriteria)
|
||||
successful = PR_TRUE;
|
||||
}
|
||||
if(successful)
|
||||
{
|
||||
mCurMsg = do_QueryInterface(currentItem, &rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
}
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsresult nsMessageViewMessageEnumerator::MeetsCriteria(nsIMessage *message, PRBool *meetsCriteria)
|
||||
{
|
||||
|
||||
if(!meetsCriteria)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
*meetsCriteria = PR_FALSE;
|
||||
|
||||
if(mShowStatus == nsIMessageView::eShowAll)
|
||||
{
|
||||
*meetsCriteria = PR_TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
PRUint32 flags;
|
||||
message->GetFlags(&flags);
|
||||
|
||||
if(mShowStatus == nsIMessageView::eShowRead)
|
||||
*meetsCriteria = flags & MSG_FLAG_READ;
|
||||
else if(mShowStatus == nsIMessageView::eShowUnread)
|
||||
*meetsCriteria = !(flags & MSG_FLAG_READ);
|
||||
else if(mShowStatus == nsIMessageView::eShowWatched)
|
||||
*meetsCriteria = flags & MSG_FLAG_WATCHED;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
////////////////////////// nsMessageViewThreadEnumerator //////////////////
|
||||
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsMessageViewThreadEnumerator, nsISimpleEnumerator)
|
||||
|
||||
nsMessageViewThreadEnumerator::nsMessageViewThreadEnumerator(nsISimpleEnumerator *threads,
|
||||
nsIMsgFolder *srcFolder)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
|
||||
mThreads = do_QueryInterface(threads);
|
||||
mFolder = do_QueryInterface(srcFolder);
|
||||
mNeedToPrefetch = PR_TRUE;
|
||||
}
|
||||
|
||||
nsMessageViewThreadEnumerator::~nsMessageViewThreadEnumerator()
|
||||
{
|
||||
//member variables are nsCOMPtr's
|
||||
}
|
||||
|
||||
/** Next will advance the list. will return failed if already at end
|
||||
*/
|
||||
NS_IMETHODIMP nsMessageViewThreadEnumerator::GetNext(nsISupports **aItem)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
if(!mMessages)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (mNeedToPrefetch)
|
||||
rv = Prefetch();
|
||||
if (NS_SUCCEEDED(rv) && mMessages)
|
||||
rv = mMessages->GetNext(aItem);
|
||||
// NS_ASSERTION(NS_SUCCEEDED(rv),"getnext shouldn't fail");
|
||||
mNeedToPrefetch = PR_TRUE;
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult nsMessageViewThreadEnumerator::Prefetch()
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
//then check to see if the there are no more messages in last thread
|
||||
//Get the next thread
|
||||
rv = mThreads->GetNext(getter_AddRefs(mCurThread));
|
||||
if(NS_SUCCEEDED(rv))
|
||||
{
|
||||
rv = GetMessagesForCurrentThread();
|
||||
mNeedToPrefetch = PR_FALSE;
|
||||
}
|
||||
else
|
||||
mMessages = nsnull;
|
||||
return rv;
|
||||
}
|
||||
|
||||
/** return if the collection is at the end. that is the beginning following a call to Prev
|
||||
* and it is the end of the list following a call to next
|
||||
* @param aItem return value
|
||||
*/
|
||||
NS_IMETHODIMP nsMessageViewThreadEnumerator::HasMoreElements(PRBool *aResult)
|
||||
{
|
||||
if (!aResult)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
if (mNeedToPrefetch)
|
||||
Prefetch();
|
||||
//First check to see if there are no more threads
|
||||
if (mMessages)
|
||||
rv = mMessages->HasMoreElements(aResult);
|
||||
else
|
||||
*aResult = nsnull;
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult nsMessageViewThreadEnumerator::GetMessagesForCurrentThread()
|
||||
{
|
||||
nsCOMPtr<nsIMsgThread> thread;
|
||||
nsresult rv = NS_OK;
|
||||
if(mCurThread)
|
||||
{
|
||||
thread = do_QueryInterface(mCurThread, &rv);
|
||||
if(NS_SUCCEEDED(rv))
|
||||
{
|
||||
nsCOMPtr<nsISimpleEnumerator> msgHdrs;
|
||||
rv = thread->EnumerateMessages(nsMsgKey_None, getter_AddRefs(msgHdrs));
|
||||
nsMessageFromMsgHdrEnumerator *messages;
|
||||
NS_NewMessageFromMsgHdrEnumerator(msgHdrs, mFolder, &messages);
|
||||
mMessages = do_QueryInterface(messages, &rv);
|
||||
NS_IF_RELEASE(messages);
|
||||
}
|
||||
}
|
||||
else
|
||||
mMessages = nsnull;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
@ -1,128 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#ifndef NSMESSAGEVIEWDATASOURCE_H
|
||||
#define NSMESSAGEVIEWDATASOURCE_H
|
||||
|
||||
#include "nsIRDFCompositeDataSource.h"
|
||||
#include "nsIMessageView.h"
|
||||
#include "nsIMsgFolder.h"
|
||||
#include "nsIRDFNode.h"
|
||||
#include "nsIRDFService.h"
|
||||
#include "nsISupportsArray.h"
|
||||
#include "nsIEnumerator.h"
|
||||
#include "nsIMessage.h"
|
||||
#include "nsIMsgThread.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
/**
|
||||
* The mail data source.
|
||||
*/
|
||||
class nsMessageViewDataSource : public nsIRDFCompositeDataSource,
|
||||
public nsIRDFObserver
|
||||
{
|
||||
private:
|
||||
nsCOMPtr<nsISupportsArray> mObservers;
|
||||
PRBool mInitialized;
|
||||
nsIRDFService * mRDFService;
|
||||
|
||||
public:
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIRDFDATASOURCE
|
||||
NS_DECL_NSIRDFCOMPOSITEDATASOURCE
|
||||
NS_DECL_NSIRDFOBSERVER
|
||||
nsMessageViewDataSource(void);
|
||||
virtual ~nsMessageViewDataSource (void);
|
||||
virtual nsresult Init();
|
||||
|
||||
protected:
|
||||
nsresult createMessageNode(nsIMessage *message, nsIRDFResource *property, nsIRDFNode **target);
|
||||
nsresult GetMessageEnumerator(nsIMessage* message, nsISimpleEnumerator* *result);
|
||||
|
||||
// caching frequently used resources
|
||||
protected:
|
||||
|
||||
nsCOMPtr<nsIRDFDataSource> mDataSource;
|
||||
PRUint32 mViewType;
|
||||
PRBool mShowThreads;
|
||||
|
||||
static nsIRDFResource* kNC_MessageChild;
|
||||
static nsIRDFResource* kNC_Subject;
|
||||
static nsIRDFResource* kNC_Date;
|
||||
static nsIRDFResource* kNC_Sender;
|
||||
static nsIRDFResource* kNC_Status;
|
||||
|
||||
|
||||
};
|
||||
|
||||
class nsMessageViewMessageEnumerator: public nsISimpleEnumerator
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
nsMessageViewMessageEnumerator(nsISimpleEnumerator *srcEnumerator, PRUint32 showStatus);
|
||||
virtual ~nsMessageViewMessageEnumerator();
|
||||
|
||||
NS_DECL_NSISIMPLEENUMERATOR
|
||||
|
||||
protected:
|
||||
nsresult SetAtNextItem();
|
||||
nsresult MeetsCriteria(nsIMessage *message, PRBool *meetsCriteria);
|
||||
|
||||
protected:
|
||||
|
||||
nsCOMPtr<nsISimpleEnumerator> mSrcEnumerator;
|
||||
nsCOMPtr<nsISupports> mCurMsg;
|
||||
nsCOMPtr<nsISupports> mCurThread;
|
||||
PRUint32 mShowStatus;
|
||||
|
||||
};
|
||||
|
||||
class nsMessageViewThreadEnumerator: public nsISimpleEnumerator
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
nsMessageViewThreadEnumerator(nsISimpleEnumerator *srcEnumerator, nsIMsgFolder *srcFolder);
|
||||
virtual ~nsMessageViewThreadEnumerator();
|
||||
|
||||
NS_DECL_NSISIMPLEENUMERATOR
|
||||
|
||||
protected:
|
||||
nsresult GetMessagesForCurrentThread();
|
||||
nsresult Prefetch();
|
||||
protected:
|
||||
|
||||
nsCOMPtr<nsISimpleEnumerator> mThreads;
|
||||
nsCOMPtr<nsISimpleEnumerator> mMessages;
|
||||
nsCOMPtr<nsISupports> mCurThread;
|
||||
nsCOMPtr<nsIMsgFolder> mFolder;
|
||||
PRBool mNeedToPrefetch;
|
||||
|
||||
};
|
||||
#endif
|
||||
|
@ -45,8 +45,6 @@
|
||||
#include "nsMsgBaseCID.h"
|
||||
#include "nsIInputStream.h"
|
||||
|
||||
#include "nsMessageViewDataSource.h"
|
||||
|
||||
#include "nsTraceRefcnt.h"
|
||||
#include "nsIMsgFolder.h" // TO include biffState enum. Change to bool later...
|
||||
|
||||
|
@ -39,7 +39,6 @@
|
||||
#include "nsMsgBaseCID.h"
|
||||
#include "nsIMessageView.h"
|
||||
#include "nsMsgUtils.h"
|
||||
#include "nsMessageViewDataSource.h"
|
||||
#include "nsTextFormatter.h"
|
||||
|
||||
|
||||
@ -1825,8 +1824,6 @@ nsresult
|
||||
nsMsgMessageDataSource::createMessageMessageChildNode(nsIMessage *message,
|
||||
nsIRDFNode **target)
|
||||
{
|
||||
// this is slow, but for now, call GetTargets and then create
|
||||
// a node out of the first message, if any
|
||||
nsCOMPtr<nsIRDFResource> messageResource(do_QueryInterface(message));
|
||||
return createMessageChildNode(messageResource, target);
|
||||
}
|
||||
@ -1843,15 +1840,18 @@ nsresult
|
||||
nsMsgMessageDataSource::createMessageChildNode(nsIRDFResource *resource, nsIRDFNode** target)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsISimpleEnumerator> messages;
|
||||
rv = GetTargets(resource, kNC_MessageChild, PR_TRUE,
|
||||
getter_AddRefs(messages));
|
||||
nsCOMPtr<nsIMessageView> messageView;
|
||||
|
||||
PRBool hasMessages;
|
||||
messages->HasMoreElements(&hasMessages);
|
||||
rv = GetMessageView(getter_AddRefs(messageView));
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
if (hasMessages)
|
||||
PRBool hasMessages = PR_FALSE;
|
||||
rv = messageView->HasMessages(resource, mWindow, &hasMessages);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
if (hasMessages) {
|
||||
return createNode("has messages", target, getRDFService());
|
||||
}
|
||||
|
||||
return NS_RDF_NO_VALUE;
|
||||
|
||||
|
@ -166,12 +166,34 @@ NS_IMETHODIMP nsMsgDBFolder::EndFolderLoading(void)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgDBFolder::GetThreads(nsIMsgWindow *aMsgWindow, nsISimpleEnumerator** threadEnumerator)
|
||||
NS_IMETHODIMP nsMsgDBFolder::HasThreads(nsIMsgWindow *aMsgWindow, PRBool *hasThreads)
|
||||
{
|
||||
nsresult rv = GetDatabase(aMsgWindow);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
rv = mDatabase->HasThreads(hasThreads);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgDBFolder::HasMessagesOfType(nsIMsgWindow *aMsgWindow, PRUint32 viewType, PRBool *hasMessages)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
rv = GetDatabase(aMsgWindow);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
rv = mDatabase->HasMessagesOfType(viewType, hasMessages);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgDBFolder::GetThreadsOfType(nsIMsgWindow *aMsgWindow, PRUint32 viewType, nsISimpleEnumerator** threadEnumerator)
|
||||
{
|
||||
nsresult rv = GetDatabase(aMsgWindow);
|
||||
|
||||
if(NS_SUCCEEDED(rv))
|
||||
return mDatabase->EnumerateThreads(threadEnumerator);
|
||||
return mDatabase->EnumerateThreads(viewType, threadEnumerator);
|
||||
else
|
||||
return rv;
|
||||
}
|
||||
|
@ -50,11 +50,13 @@ public:
|
||||
virtual ~nsMsgDBFolder(void);
|
||||
NS_DECL_NSIDBCHANGELISTENER
|
||||
|
||||
NS_IMETHOD StartFolderLoading(void);
|
||||
NS_IMETHOD EndFolderLoading(void);
|
||||
NS_IMETHOD GetThreads(nsIMsgWindow *aMsgWindow, nsISimpleEnumerator** threadEnumerator);
|
||||
NS_IMETHOD StartFolderLoading(void);
|
||||
NS_IMETHOD EndFolderLoading(void);
|
||||
NS_IMETHOD GetThreadsOfType(nsIMsgWindow *aMsgWindow, PRUint32 viewType, nsISimpleEnumerator** threadEnumerator);
|
||||
NS_IMETHOD GetThreadForMessage(nsIMessage *message, nsIMsgThread **thread);
|
||||
NS_IMETHOD HasMessage(nsIMessage *message, PRBool *hasMessage);
|
||||
NS_IMETHOD HasThreads(nsIMsgWindow *aMsgWindow, PRBool *hasThreads);
|
||||
NS_IMETHOD HasMessagesOfType(nsIMsgWindow *aMsgWindow, PRUint32 viewType, PRBool *hasMessages);
|
||||
NS_IMETHOD GetCharset(PRUnichar * *aCharset);
|
||||
NS_IMETHOD SetCharset(const PRUnichar * aCharset);
|
||||
//NS_IMETHOD HasNewMessages(PRBool *hasNewMessages);
|
||||
|
@ -435,6 +435,12 @@ NS_IMETHODIMP nsMsgFolder::GetParent(nsIFolder **aParent)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMsgFolder::HasMessagesOfType(nsIMsgWindow *aMsgWindow, PRUint32 type, PRBool *hasMessages)
|
||||
{
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMsgFolder::GetMessages(nsIMsgWindow *aMsgWindow, nsISimpleEnumerator* *result)
|
||||
{
|
||||
@ -458,8 +464,14 @@ nsMsgFolder::UpdateFolder(nsIMsgWindow *)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMsgFolder::HasThreads(nsIMsgWindow *aMsgWindow, PRBool *hasThreads)
|
||||
{
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMsgFolder::GetThreads(nsIMsgWindow *aMsgWindow, nsISimpleEnumerator ** threadEnumerator)
|
||||
nsMsgFolder::GetThreadsOfType(nsIMsgWindow *aMsgWindow, PRUint32 viewType, nsISimpleEnumerator ** threadEnumerator)
|
||||
{
|
||||
// XXX should this return an empty enumeration?
|
||||
return NS_ERROR_FAILURE;
|
||||
|
@ -67,8 +67,11 @@ public:
|
||||
// begin NS_DECL_NSIMSGFOLDER
|
||||
NS_IMETHOD AddUnique(nsISupports *element);
|
||||
NS_IMETHOD ReplaceElement(nsISupports *element, nsISupports *newElement);
|
||||
NS_IMETHOD HasMessagesOfType(nsIMsgWindow *aMsgWindow, PRUint32 viewType, PRBool *
|
||||
hasMessages);
|
||||
NS_IMETHOD GetMessages(nsIMsgWindow *aMsgWindow, nsISimpleEnumerator **_retval);
|
||||
NS_IMETHOD GetThreads(nsIMsgWindow *aMsgWindow, nsISimpleEnumerator **_retval);
|
||||
NS_IMETHOD GetThreadsOfType(nsIMsgWindow *aMsgWindow, PRUint32 viewType, nsISimpleEnumerator **_retval);
|
||||
NS_IMETHOD HasThreads(nsIMsgWindow *aMsgWindow, PRBool *hasThreads);
|
||||
NS_IMETHOD StartFolderLoading(void);
|
||||
NS_IMETHOD EndFolderLoading(void);
|
||||
NS_IMETHOD UpdateFolder(nsIMsgWindow *window);
|
||||
|
@ -106,7 +106,9 @@ interface nsIMsgDatabase : nsIDBChangeAnnouncer {
|
||||
[noscript] void ListAllKeys(in nsMsgKeyArrayRef outputKeys);
|
||||
|
||||
nsISimpleEnumerator EnumerateMessages();
|
||||
nsISimpleEnumerator EnumerateThreads();
|
||||
boolean hasMessagesOfType(in unsigned long viewType);
|
||||
nsISimpleEnumerator EnumerateThreads(in unsigned long viewType);
|
||||
boolean hasThreads();
|
||||
|
||||
nsIMsgThread GetThreadContainingMsgHdr(in nsIMsgDBHdr msgHdr) ;
|
||||
|
||||
|
@ -60,6 +60,8 @@ public:
|
||||
virtual nsresult CreateMsgHdr(nsIMdbRow* hdrRow, nsMsgKey key, nsIMsgDBHdr **result);
|
||||
virtual nsresult GetThreadForMsgKey(nsMsgKey msgKey, nsIMsgThread **result);
|
||||
virtual nsresult EnumerateUnreadMessages(nsISimpleEnumerator* *result);
|
||||
virtual nsresult EnumerateReadMessages(nsISimpleEnumerator* *result);
|
||||
|
||||
// this might just be for debugging - we'll see.
|
||||
nsresult ListAllThreads(nsMsgKeyArray *threadIds);
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -46,6 +46,8 @@
|
||||
#include "nsIMsgAccountManager.h"
|
||||
#include "nsIMsgFolderCache.h"
|
||||
#include "nsIMsgFolderCacheElement.h"
|
||||
#include "MailNewsTypes2.h"
|
||||
|
||||
static NS_DEFINE_CID(kCMorkFactory, NS_MORK_CID);
|
||||
|
||||
#if defined(XP_MAC) && defined(CompareString)
|
||||
@ -623,8 +625,8 @@ nsMsgDatabase::nsMsgDatabase()
|
||||
m_offlineMsgOffsetColumnToken(0),
|
||||
m_offlineMessageSizeColumnToken(0),
|
||||
m_HeaderParser(nsnull),
|
||||
m_cachedHeaders(nsnull),
|
||||
m_headersInUse(nsnull),
|
||||
m_cachedHeaders(nsnull),
|
||||
m_bCacheHeaders(PR_FALSE)
|
||||
|
||||
{
|
||||
@ -2247,6 +2249,14 @@ NS_IMETHODIMP nsMsgDatabase::ListAllKeys(nsMsgKeyArray &outputKeys)
|
||||
return err;
|
||||
}
|
||||
|
||||
static nsresult
|
||||
nsMsgDBThreadUnreadFilter(nsIMsgThread *thread)
|
||||
{
|
||||
PRUint32 numUnreadChildren = 0;
|
||||
nsresult rv = thread->GetNumUnreadChildren(&numUnreadChildren);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
return (numUnreadChildren > 0) ? NS_OK : NS_COMFALSE;
|
||||
}
|
||||
|
||||
class nsMsgDBThreadEnumerator : public nsISimpleEnumerator
|
||||
{
|
||||
@ -2257,10 +2267,10 @@ public:
|
||||
NS_DECL_NSISIMPLEENUMERATOR
|
||||
|
||||
// nsMsgDBEnumerator methods:
|
||||
typedef nsresult (*nsMsgDBThreadEnumeratorFilter)(nsIMsgThread* hdr, void* closure);
|
||||
typedef nsresult (*nsMsgDBThreadEnumeratorFilter)(nsIMsgThread* thread);
|
||||
|
||||
nsMsgDBThreadEnumerator(nsMsgDatabase* db,
|
||||
nsMsgDBThreadEnumeratorFilter filter, void* closure);
|
||||
nsMsgDBThreadEnumeratorFilter filter);
|
||||
virtual ~nsMsgDBThreadEnumerator();
|
||||
|
||||
protected:
|
||||
@ -2272,13 +2282,12 @@ protected:
|
||||
PRBool mDone;
|
||||
PRBool mNextPrefetched;
|
||||
nsMsgDBThreadEnumeratorFilter mFilter;
|
||||
void* mClosure;
|
||||
};
|
||||
|
||||
nsMsgDBThreadEnumerator::nsMsgDBThreadEnumerator(nsMsgDatabase* db,
|
||||
nsMsgDBThreadEnumeratorFilter filter, void* closure)
|
||||
nsMsgDBThreadEnumeratorFilter filter)
|
||||
: mDB(db), mTableCursor(nsnull), mResultThread(nsnull), mDone(PR_FALSE),
|
||||
mFilter(filter), mClosure(closure)
|
||||
mFilter(filter)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
NS_ADDREF(mDB);
|
||||
@ -2370,7 +2379,7 @@ nsresult nsMsgDBThreadEnumerator::PrefetchNext()
|
||||
if (numChildren == 0)
|
||||
continue;
|
||||
}
|
||||
if (mFilter && mFilter(mResultThread, mClosure) != NS_OK)
|
||||
if (mFilter && mFilter(mResultThread) != NS_OK)
|
||||
continue;
|
||||
else
|
||||
break;
|
||||
@ -2394,9 +2403,27 @@ NS_IMETHODIMP nsMsgDBThreadEnumerator::HasMoreElements(PRBool *aResult)
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMsgDatabase::EnumerateThreads(nsISimpleEnumerator* *result)
|
||||
nsMsgDatabase::EnumerateThreads(PRUint32 viewType, nsISimpleEnumerator* *result)
|
||||
{
|
||||
nsMsgDBThreadEnumerator* e = new nsMsgDBThreadEnumerator(this, nsnull, nsnull);
|
||||
nsresult rv = NS_OK;
|
||||
nsMsgDBThreadEnumerator* e = nsnull;
|
||||
switch (viewType) {
|
||||
case nsMsgViewType::eShowAll:
|
||||
e = new nsMsgDBThreadEnumerator(this, nsnull);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
break;
|
||||
case nsMsgViewType::eShowUnread:
|
||||
e = new nsMsgDBThreadEnumerator(this, nsMsgDBThreadUnreadFilter);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
break;
|
||||
case nsMsgViewType::eShowRead:
|
||||
case nsMsgViewType::eShowWatched:
|
||||
default:
|
||||
NS_ENSURE_SUCCESS(NS_ERROR_UNEXPECTED,NS_ERROR_UNEXPECTED);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (e == nsnull)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
NS_ADDREF(e);
|
||||
@ -2463,6 +2490,28 @@ nsMsgDatabase::EnumerateUnreadMessages(nsISimpleEnumerator* *result)
|
||||
*result = e;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static nsresult
|
||||
nsMsgReadFilter(nsIMsgDBHdr* msg, void* closure)
|
||||
{
|
||||
nsMsgDatabase* db = (nsMsgDatabase*)closure;
|
||||
PRBool wasRead = PR_TRUE;
|
||||
nsresult rv = db->IsHeaderRead(msg, &wasRead);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
return wasRead ? NS_OK : NS_COMFALSE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMsgDatabase::EnumerateReadMessages(nsISimpleEnumerator* *result)
|
||||
{
|
||||
nsMsgDBEnumerator* e = new nsMsgDBEnumerator(this, nsMsgReadFilter, this);
|
||||
if (e == nsnull)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
NS_ADDREF(e);
|
||||
*result = e;
|
||||
return NS_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
NS_IMETHODIMP nsMsgDatabase::CreateNewHdr(nsMsgKey key, nsIMsgDBHdr **pnewHdr)
|
||||
@ -3239,21 +3288,17 @@ nsresult nsMsgDatabase::ListAllThreads(nsMsgKeyArray *threadIds)
|
||||
nsresult rv;
|
||||
nsMsgThread *pThread;
|
||||
|
||||
nsISimpleEnumerator* threads;
|
||||
rv = EnumerateThreads(&threads);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
nsCOMPtr <nsISimpleEnumerator> threads;
|
||||
rv = EnumerateThreads(nsMsgViewType::eShowAll, getter_AddRefs(threads));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
PRBool hasMore = PR_FALSE;
|
||||
|
||||
while (NS_SUCCEEDED(rv = threads->HasMoreElements(&hasMore)) && (hasMore == PR_TRUE))
|
||||
{
|
||||
rv = threads->GetNext((nsISupports**)&pThread);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "nsMsgDBEnumerator broken");
|
||||
if (NS_FAILED(rv))
|
||||
break;
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
if (threadIds)
|
||||
{
|
||||
if (threadIds) {
|
||||
nsMsgKey key;
|
||||
(void)pThread->GetThreadKey(&key);
|
||||
threadIds->Add(key);
|
||||
@ -3261,7 +3306,6 @@ nsresult nsMsgDatabase::ListAllThreads(nsMsgKeyArray *threadIds)
|
||||
// NS_RELEASE(pThread);
|
||||
pThread = nsnull;
|
||||
}
|
||||
NS_RELEASE(threads);
|
||||
return rv;
|
||||
}
|
||||
|
||||
@ -3292,6 +3336,47 @@ NS_IMETHODIMP nsMsgDatabase::GetLowWaterArticleNum(nsMsgKey *key)
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgDatabase::HasMessagesOfType(PRUint32 viewType, PRBool *hasMessages)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr <nsISimpleEnumerator> messages;
|
||||
|
||||
switch (viewType) {
|
||||
case nsMsgViewType::eShowAll:
|
||||
rv = EnumerateMessages(getter_AddRefs(messages));
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
break;
|
||||
case nsMsgViewType::eShowRead:
|
||||
rv = EnumerateReadMessages(getter_AddRefs(messages));
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
break;
|
||||
case nsMsgViewType::eShowUnread:
|
||||
rv = EnumerateUnreadMessages(getter_AddRefs(messages));
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
break;
|
||||
case nsMsgViewType::eShowWatched:
|
||||
default:
|
||||
NS_ENSURE_SUCCESS(NS_ERROR_UNEXPECTED,NS_ERROR_UNEXPECTED);
|
||||
break;
|
||||
}
|
||||
|
||||
rv = messages->HasMoreElements(hasMessages);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgDatabase::HasThreads(PRBool *hasThreads)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr <nsISimpleEnumerator> threads;
|
||||
rv = EnumerateThreads(nsMsgViewType::eShowAll, getter_AddRefs(threads));
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
rv = threads->HasMoreElements(hasThreads);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
nsresult nsMsgDatabase::DumpContents()
|
||||
|
@ -567,8 +567,7 @@ NS_IMETHODIMP nsMsgHdr::GetMessageOffset(PRUint32 *result)
|
||||
|
||||
NS_IMETHODIMP nsMsgHdr::SetMessageOffset(PRUint32 offset)
|
||||
{
|
||||
|
||||
nsresult rv = SetUInt32Column(offset, m_mdb->m_offlineMsgOffsetColumnToken);
|
||||
SetUInt32Column(offset, m_mdb->m_offlineMsgOffsetColumnToken);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "nsMsgThread.h"
|
||||
#include "nsMsgDatabase.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "MailNewsTypes2.h"
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsMsgThread, nsMsgThread)
|
||||
|
||||
@ -602,9 +603,9 @@ protected:
|
||||
PRInt32 mChildIndex;
|
||||
PRBool mDone;
|
||||
PRBool mNeedToPrefetch;
|
||||
PRBool mFoundChildren;
|
||||
nsMsgThreadEnumeratorFilter mFilter;
|
||||
void* mClosure;
|
||||
PRBool mFoundChildren;
|
||||
};
|
||||
|
||||
nsMsgThreadEnumerator::nsMsgThreadEnumerator(nsMsgThread *thread, nsMsgKey startKey,
|
||||
@ -767,6 +768,11 @@ nsresult nsMsgThreadEnumerator::Prefetch()
|
||||
nsMsgKey parentKey;
|
||||
nsMsgKey curKey;
|
||||
|
||||
if (mFilter && mFilter(mResultHdr, mClosure) != NS_OK) {
|
||||
mResultHdr = nsnull;
|
||||
continue;
|
||||
}
|
||||
|
||||
mResultHdr->GetThreadParent(&parentKey);
|
||||
mResultHdr->GetMessageKey(&curKey);
|
||||
// if the parent is the same as the msg we're enumerating over,
|
||||
@ -819,6 +825,90 @@ NS_IMETHODIMP nsMsgThreadEnumerator::HasMoreElements(PRBool *aResult)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
#if 0
|
||||
// this performance optimization isn't working quite right yet.
|
||||
NS_IMETHODIMP nsMsgThread::HasMessagesOfType(nsMsgKey parentKey, PRUint32 viewType, PRBool *hasMessages)
|
||||
{
|
||||
nsresult rv;
|
||||
PRUint32 numChildren = 0;
|
||||
PRUint32 numUnreadChildren = 0;
|
||||
|
||||
rv = GetNumChildren(&numChildren);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
switch (viewType) {
|
||||
case nsMsgViewType::eShowAll:
|
||||
// don't return true on messages without children
|
||||
*hasMessages = (numChildren > 1);
|
||||
break;
|
||||
case nsMsgViewType::eShowUnread:
|
||||
rv = GetNumUnreadChildren(&numUnreadChildren);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
// don't return true on messages without children
|
||||
*hasMessages = ((numChildren > 1) && (numUnreadChildren > 1));
|
||||
break;
|
||||
case nsMsgViewType::eShowRead:
|
||||
case nsMsgViewType::eShowWatched:
|
||||
default:
|
||||
NS_ENSURE_SUCCESS(NS_ERROR_UNEXPECTED,NS_ERROR_UNEXPECTED);
|
||||
break;
|
||||
}
|
||||
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
return NS_OK;
|
||||
}
|
||||
#else
|
||||
NS_IMETHODIMP nsMsgThread::HasMessagesOfType(nsMsgKey parentKey, PRUint32 viewType, PRBool *hasMessages)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr <nsISimpleEnumerator> messages;
|
||||
|
||||
switch (viewType) {
|
||||
case nsMsgViewType::eShowAll:
|
||||
rv = EnumerateMessages(parentKey, getter_AddRefs(messages));
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
break;
|
||||
case nsMsgViewType::eShowUnread:
|
||||
rv = EnumerateUnreadMessages(parentKey, getter_AddRefs(messages));
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
break;
|
||||
case nsMsgViewType::eShowRead:
|
||||
case nsMsgViewType::eShowWatched:
|
||||
default:
|
||||
NS_ENSURE_SUCCESS(NS_ERROR_UNEXPECTED,NS_ERROR_UNEXPECTED);
|
||||
break;
|
||||
}
|
||||
|
||||
rv = messages->HasMoreElements(hasMessages);
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
return NS_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
static nsresult
|
||||
nsMsgThreadUnreadFilter(nsIMsgDBHdr* msg, void* closure)
|
||||
{
|
||||
nsMsgDatabase* db = (nsMsgDatabase*)closure;
|
||||
PRBool wasRead = PR_TRUE;
|
||||
nsresult rv = db->IsHeaderRead(msg, &wasRead);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
return !wasRead ? NS_OK : NS_COMFALSE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgThread::EnumerateUnreadMessages(nsMsgKey parentKey, nsISimpleEnumerator* *result)
|
||||
{
|
||||
nsresult ret = NS_OK;
|
||||
nsMsgThreadEnumerator* e = new nsMsgThreadEnumerator(this, parentKey, nsMsgThreadUnreadFilter, m_mdbDB);
|
||||
if (e == nsnull)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
NS_ADDREF(e);
|
||||
*result = e;
|
||||
return NS_OK;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsMsgThread::EnumerateMessages(nsMsgKey parentKey, nsISimpleEnumerator* *result)
|
||||
{
|
||||
|
@ -84,18 +84,6 @@ enum nsMsgSortType {
|
||||
nsMsgSortType_Recipient
|
||||
};
|
||||
|
||||
enum nsMsgViewType {
|
||||
nsMsgViewType_Any = 0, // this view type matches any other view type,
|
||||
// for the purpose of matching cached views.
|
||||
// Else, it's equivalent to ViewAllThreads
|
||||
nsMsgViewType_AllThreads = 1, // default view, no killed threads
|
||||
nsMsgViewType_OnlyThreadsWithNew = 2,
|
||||
nsMsgViewType_OnlyNewHeaders = 4,
|
||||
nsMsgViewType_WatchedThreadsWithNew = 5,
|
||||
nsMsgViewType_Cacheless // this would be for cacheless imap
|
||||
};
|
||||
|
||||
|
||||
/* Flags about a single message. These values are used in the MSG_MessageLine
|
||||
struct and in a folder's mozilla-status line. The summary file database
|
||||
should use the same set of flags..
|
||||
|
@ -37,3 +37,12 @@ interface nsMsgPriority {
|
||||
const nsMsgPriorityValue highest = 6;
|
||||
};
|
||||
|
||||
typedef long nsMsgViewTypeValue;
|
||||
|
||||
[scriptable, uuid(dac950b0-1dd1-11b2-be06-d4c2003a6927)]
|
||||
interface nsMsgViewType {
|
||||
const nsMsgViewTypeValue eShowAll = 0;
|
||||
const nsMsgViewTypeValue eShowRead = 1;
|
||||
const nsMsgViewTypeValue eShowUnread = 2;
|
||||
const nsMsgViewTypeValue eShowWatched = 3;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user