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:
sspitzer%netscape.com 2001-01-04 00:12:36 +00:00
Родитель 39630222f8
Коммит 66ca0c7f60
31 изменённых файлов: 319 добавлений и 367 удалений

Просмотреть файл

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

Просмотреть файл

@ -1,42 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* 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) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#include "nsISupports.idl"
#include "nsIRDFResource.idl"
#include "nsIEnumerator.idl"
interface nsIMsgWindow;
[scriptable, uuid(14495572-E945-11d2-8A52-0060B0FC04D2)]
/* Use this for any object that wants to handle copying/moving messages to it */
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);
};

Просмотреть файл

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

Просмотреть файл

@ -1,174 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* 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) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Pierre Phaneuf <pp@ludusdesign.com>
*/
#include "nsMessageView.h"
#include "nsCOMPtr.h"
#include "nsIMessage.h"
#include "nsIMsgFolder.h"
#include "nsMsgUtils.h"
#include "nsMessageViewDataSource.h"
#include "nsEnumeratorUtils.h"
NS_IMPL_ISUPPORTS1(nsMessageView, nsIMessageView)
nsMessageView::nsMessageView()
{
NS_INIT_REFCNT();
mShowThreads = PR_FALSE;
mViewType = nsIMessageView::eShowAll;
}
nsMessageView::~nsMessageView()
{
}
nsresult nsMessageView::Init()
{
return NS_OK;
}
NS_IMETHODIMP nsMessageView::GetViewType(PRUint32 *aViewType)
{
if(!aViewType)
return NS_ERROR_NULL_POINTER;
*aViewType = mViewType;
return NS_OK;
}
NS_IMETHODIMP nsMessageView::SetViewType(PRUint32 aViewType)
{
mViewType = aViewType;
return NS_OK;
}
NS_IMETHODIMP nsMessageView::GetShowThreads(PRBool *aShowThreads)
{
if(!aShowThreads)
return NS_ERROR_NULL_POINTER;
*aShowThreads = mShowThreads;
return NS_OK;
}
NS_IMETHODIMP nsMessageView::SetShowThreads(PRBool aShowThreads)
{
mShowThreads = aShowThreads;
return NS_OK;
}
NS_IMETHODIMP nsMessageView::GetMessages(nsIRDFResource *parentResource, nsIMsgWindow* msgWindow, nsISimpleEnumerator **messages)
{
nsresult rv = NS_OK;
*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);
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;
}
}
}
}
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;
nsMessageViewThreadEnumerator * threadEnumerator =
new nsMessageViewThreadEnumerator(threads, folder);
if(!threadEnumerator)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(threadEnumerator);
*messages = threadEnumerator;
rv = NS_OK;
}
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;
nsMessageViewMessageEnumerator * messageEnumerator =
new nsMessageViewMessageEnumerator(folderMessages, viewType);
if(!messageEnumerator)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(messageEnumerator);
*messages = messageEnumerator;
rv = NS_OK;
}
}
}
if(!*messages)
{
//return empty array
nsCOMPtr<nsISupportsArray> assertions;
rv = NS_NewISupportsArray(getter_AddRefs(assertions));
if(NS_FAILED(rv))
return rv;
rv = NS_NewArrayEnumerator(messages, assertions);
}
return rv;
}

Просмотреть файл

@ -1,47 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* 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) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef _nsMessageView_h
#define _nsMessageView_h
#include "nsIMessageView.h"
class nsMessageView : public nsIMessageView {
public:
NS_DECL_ISUPPORTS
nsMessageView();
virtual ~nsMessageView();
nsresult Init();
NS_DECL_NSIMESSAGEVIEW
protected:
PRBool mShowThreads;
PRUint32 mViewType;
};
#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;
};