implement message grouping, 256688 sr=mscott

git-svn-id: svn://10.0.0.236/trunk@163258 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
bienvenu%nventure.com 2004-10-05 20:49:28 +00:00
parent a281bad875
commit 557fe54510
20 changed files with 309 additions and 55 deletions

View File

@ -650,7 +650,10 @@ function CreateBareDBView(originalView, msgFolder, viewType, viewFlags, sortType
break;
case nsMsgViewType.eShowAllThreads:
default:
dbviewContractId += "threaded";
if (viewFlags & nsMsgViewFlagsType.kGroupBySort)
dbviewContractId += "group";
else
dbviewContractId += "threaded";
break;
}

View File

@ -229,19 +229,29 @@ function InitViewSortByMenu()
setSortByMenuItemCheckState("sortByAttachmentsMenuitem", (sortType == nsMsgViewSortType.byAttachments));
var sortOrder = gDBView.sortOrder;
var sortTypeSupportsGrouping = (sortType == nsMsgViewSortType.byAuthor
|| sortType == nsMsgViewSortType.byDate || sortType == nsMsgViewSortType.byPriority
|| sortType == nsMsgViewSortType.bySubject || sortType == nsMsgViewSortType.byLabel
|| sortType == nsMsgViewSortType.byRecipient);
setSortByMenuItemCheckState("sortAscending", (sortOrder == nsMsgViewSortOrder.ascending));
setSortByMenuItemCheckState("sortDescending", (sortOrder == nsMsgViewSortOrder.descending));
var threaded = ((gDBView.viewFlags & nsMsgViewFlagsType.kThreadedDisplay) != 0);
var grouped = ((gDBView.viewFlags & nsMsgViewFlagsType.kGroupBySort) != 0);
var threaded = ((gDBView.viewFlags & nsMsgViewFlagsType.kThreadedDisplay) != 0 && !grouped);
var sortThreadedMenuItem = document.getElementById("sortThreaded");
var sortUnthreadedMenuItem = document.getElementById("sortUnthreaded");
sortThreadedMenuItem.setAttribute("checked", threaded);
sortUnthreadedMenuItem.setAttribute("checked", !threaded);
sortUnthreadedMenuItem.setAttribute("checked", !threaded && !grouped);
sortThreadedMenuItem.setAttribute("disabled", !gDBView.supportsThreading);
sortUnthreadedMenuItem.setAttribute("disabled", !gDBView.supportsThreading);
var groupBySortOrderMenuItem = document.getElementById("groupBySort");
groupBySortOrderMenuItem.setAttribute("disabled", !gDBView.supportsThreading || !sortTypeSupportsGrouping);
groupBySortOrderMenuItem.setAttribute("checked", grouped);
}
function InitViewMessagesMenu()

View File

@ -1226,6 +1226,7 @@
<menuseparator/>
<menuitem id="sortThreaded" type="radio" name="threaded" label="&sortThreaded.label;" accesskey="&sortThreaded.accesskey;" oncommand="MsgSortThreaded();"/>
<menuitem id="sortUnthreaded" type="radio" name="threaded" label="&sortUnthreaded.label;" accesskey="&sortUnthreaded.accesskey;" oncommand="MsgSortUnthreaded();"/>
<menuitem id="groupBySort" type="radio" name="group" label="&groupBySort.label;" accesskey="&groupBySort.accesskey;" oncommand="MsgGroupBySort();"/>
</menupopup>
</menu>

View File

@ -251,6 +251,10 @@ treechildren::-moz-tree-image(unreadButtonColHeader) {
list-style-image: url("chrome://messenger/skin/icons/readmail.gif");
}
treechildren::-moz-tree-image(unreadButtonColHeader, dummy) {
list-style-image: none;
}
treechildren::-moz-tree-image(unreadButtonColHeader, unread) {
list-style-image: url("chrome://messenger/skin/icons/unreadmail.png");
}
@ -277,6 +281,10 @@ treechildren::-moz-tree-image(flaggedCol) {
list-style-image: url("chrome://messenger/skin/icons/readmail.gif");
}
treechildren::-moz-tree-image(flaggedCol, dummy) {
list-style-image: none;
}
treechildren::-moz-tree-image(flaggedCol, flagged) {
list-style-image: url("chrome://messenger/skin/icons/flag.png");
}
@ -298,11 +306,14 @@ treechildren::-moz-tree-image(junkStatusCol, junk) {
list-style-image: url("chrome://messenger/skin/icons/folder-junk.png");
}
treechildren::-moz-tree-image(junkStatusCol, dummy) {
list-style-image: none;
}
treechildren::-moz-tree-image(junkStatusCol, notjunk) {
list-style-image: url("chrome://messenger/skin/icons/readmail.gif");
padding-left: 0px;
}
/* ..... subject column ..... */
treechildren::-moz-tree-image(subjectCol) {
@ -310,6 +321,10 @@ treechildren::-moz-tree-image(subjectCol) {
list-style-image: url("chrome://messenger/skin/icons/message-mail.png ");
}
treechildren::-moz-tree-image(subjectCol, dummy) {
list-style-image: none;
}
treechildren::-moz-tree-image(subjectCol, read) {
list-style-image: url("chrome://messenger/skin/icons/message-mail-read.png");
}

View File

@ -100,6 +100,7 @@
#include "nsMsgSpecialViews.h"
#include "nsMsgXFVirtualFolderDBView.h"
#include "nsMsgQuickSearchDBView.h"
#include "nsMsgGroupView.h"
#include "nsMsgOfflineManager.h"
@ -153,8 +154,9 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsMsgThreadedDBView)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsMsgThreadsWithUnreadDBView)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsMsgWatchedThreadsWithUnreadDBView)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsMsgSearchDBView)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsMsgQuickSearchDBView)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsMsgXFVirtualFolderDBView)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsMsgQuickSearchDBView)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsMsgGroupView)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsMsgOfflineManager)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsMsgProgress)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsSpamSettings)
@ -338,6 +340,10 @@ static const nsModuleComponentInfo gComponents[] = {
NS_MSGXFVFDBVIEW_CONTRACTID,
nsMsgXFVirtualFolderDBViewConstructor,
},
{ "grouped view", NS_MSG_GROUPDBVIEW_CID,
NS_MSGGROUPDBVIEW_CONTRACTID,
nsMsgGroupViewConstructor,
},
{ "Messenger Offline Manager", NS_MSGOFFLINEMANAGER_CID,
NS_MSGOFFLINEMANAGER_CONTRACTID,
nsMsgOfflineManagerConstructor,

View File

@ -45,6 +45,7 @@ interface nsIMsgDBHdr;
interface nsIMsgDBViewCommandUpdater;
interface nsIMsgDatabase;
interface nsIMsgSearchSession;
interface nsISimpleEnumerator;
typedef long nsMsgViewNotificationCodeValue;
typedef long nsMsgViewCommandCheckStateValue;
@ -79,6 +80,7 @@ interface nsMsgViewFlagsType
const nsMsgViewFlagsTypeValue kShowIgnored = 0x8;
const nsMsgViewFlagsTypeValue kUnreadOnly = 0x10;
const nsMsgViewFlagsTypeValue kExpandAll = 0x20;
const nsMsgViewFlagsTypeValue kGroupBySort = 0x40;
};
[scriptable, uuid(b2f31bca-fd18-11d4-a5be-0060b0fc04b7)]
@ -251,6 +253,9 @@ interface nsMsgNavigationType
interface nsIMsgDBView : nsISupports
{
void open(in nsIMsgFolder folder, in nsMsgViewSortTypeValue sortType, in nsMsgViewSortOrderValue sortOrder, in nsMsgViewFlagsTypeValue viewFlags, out long count);
void openWithHdrs(in nsISimpleEnumerator aHeaders, in nsMsgViewSortTypeValue aSortType,
in nsMsgViewSortOrderValue aSortOrder,
in nsMsgViewFlagsTypeValue aViewFlags, out long aCount);
void close();
void init(in nsIMessenger aMessengerInstance, in nsIMsgWindow aMsgWindow, in nsIMsgDBViewCommandUpdater aCommandUpdater);
@ -264,7 +269,7 @@ interface nsIMsgDBView : nsISupports
readonly attribute nsMsgViewTypeValue viewType;
attribute nsMsgViewFlagsTypeValue viewFlags;
readonly attribute nsMsgViewSortTypeValue sortType;
attribute nsMsgViewSortTypeValue sortType;
readonly attribute nsMsgViewSortOrderValue sortOrder;
readonly attribute nsMsgKey keyForFirstSelectedMessage;
readonly attribute nsMsgViewIndex viewIndexForFirstSelectedMsg;

View File

@ -666,7 +666,10 @@ function CreateBareDBView(originalView, msgFolder, viewType, viewFlags, sortType
break;
case nsMsgViewType.eShowAllThreads:
default:
dbviewContractId += "threaded";
if (viewFlags & nsMsgViewFlagsType.kGroupBySort)
dbviewContractId += "group";
else
dbviewContractId += "threaded";
break;
}

View File

@ -210,19 +210,29 @@ function InitViewSortByMenu()
setSortByMenuItemCheckState("sortByRecipientMenuitem", (sortType == nsMsgViewSortType.byRecipient));
var sortOrder = gDBView.sortOrder;
var sortTypeSupportsGrouping = (sortType == nsMsgViewSortType.byAuthor
|| sortType == nsMsgViewSortType.byDate || sortType == nsMsgViewSortType.byPriority
|| sortType == nsMsgViewSortType.bySubject || sortType == nsMsgViewSortType.byLabel
|| sortType == nsMsgViewSortType.byRecipient);
setSortByMenuItemCheckState("sortAscending", (sortOrder == nsMsgViewSortOrder.ascending));
setSortByMenuItemCheckState("sortDescending", (sortOrder == nsMsgViewSortOrder.descending));
var threaded = ((gDBView.viewFlags & nsMsgViewFlagsType.kThreadedDisplay) != 0);
var grouped = ((gDBView.viewFlags & nsMsgViewFlagsType.kGroupBySort) != 0);
var threaded = ((gDBView.viewFlags & nsMsgViewFlagsType.kThreadedDisplay) != 0 && !grouped);
var sortThreadedMenuItem = document.getElementById("sortThreaded");
var sortUnthreadedMenuItem = document.getElementById("sortUnthreaded");
sortThreadedMenuItem.setAttribute("checked", threaded);
sortUnthreadedMenuItem.setAttribute("checked", !threaded);
sortUnthreadedMenuItem.setAttribute("checked", !threaded && !grouped);
sortThreadedMenuItem.setAttribute("disabled", !gDBView.supportsThreading);
sortUnthreadedMenuItem.setAttribute("disabled", !gDBView.supportsThreading);
var groupBySortOrderMenuItem = document.getElementById("groupBySort");
groupBySortOrderMenuItem.setAttribute("disabled", !gDBView.supportsThreading || !sortTypeSupportsGrouping);
groupBySortOrderMenuItem.setAttribute("checked", grouped);
}
function InitViewMessagesMenu()

View File

@ -1224,6 +1224,7 @@
<menuseparator/>
<menuitem id="sortThreaded" type="radio" name="threaded" label="&sortThreaded.label;" accesskey="&sortThreaded.accesskey;" oncommand="MsgSortThreaded();"/>
<menuitem id="sortUnthreaded" type="radio" name="threaded" label="&sortUnthreaded.label;" accesskey="&sortUnthreaded.accesskey;" oncommand="MsgSortUnthreaded();"/>
<menuitem id="groupBySort" type="radio" name="group" label="&groupBySort.label;" accesskey="&groupBySort.accesskey;" oncommand="MsgGroupBySort();"/>
</menupopup>
</menu>
<menu label="&msgsMenu.label;" id="viewMessageViewMenu" accesskey="&msgsMenu.accesskey;">

View File

@ -38,6 +38,8 @@
var gLastMessageUriToLoad = null;
var gThreadPaneCommandUpdater = null;
var gGroupColumn;
var gOldPrevColumn;
function ThreadPaneOnClick(event)
{
@ -155,7 +157,14 @@ function HandleColumnClick(columnID)
}
else {
if (!simpleColumns && (dbview.viewFlags & nsMsgViewFlagsType.kThreadedDisplay)) {
dbview.viewFlags &= ~nsMsgViewFlagsType.kThreadedDisplay;
var viewFlags = dbview.viewFlags;
dbview.viewFlags &= ~ (nsMsgViewFlagsType.kThreadedDisplay | nsMsgViewFlagsType.kGroupBySort);
if (viewFlags & nsMsgViewFlagsType.kGroupBySort)
{
dbview.sortType = sortType; // save sort in current view
viewDebug("switching view to all msgs\n");
return SwitchView("cmd_viewAllMsgs");
}
MsgSortThreadPane(sortType);
}
else if (dbview.sortType == sortType) {
@ -283,6 +292,7 @@ function MsgSortByThread()
if(dbview && !dbview.supportsThreading)
return;
dbview.viewFlags |= nsMsgViewFlagsType.kThreadedDisplay;
dbview.viewFlags &= ~nsMsgViewFlagsType.kGroupBySort;
MsgSortThreadPane(nsMsgViewSortType.byId);
}
@ -307,18 +317,63 @@ function MsgReverseSortThreadPane()
function MsgToggleThreaded()
{
var dbview = GetDBView();
var viewFlags = dbview.viewFlags;
dbview.viewFlags ^= nsMsgViewFlagsType.kThreadedDisplay;
dbview.viewFlags &= ~nsMsgViewFlagsType.kGroupBySort;
if (viewFlags & nsMsgViewFlagsType.kGroupBySort)
{
viewDebug("switching view to all msgs\n");
return SwitchView("cmd_viewAllMsgs");
}
dbview.sort(dbview.sortType, dbview.sortOrder);
UpdateSortIndicators(dbview.sortType, dbview.sortOrder);
}
function MsgSortThreaded()
{
var viewFlags = GetDBView().viewFlags;
if (viewFlags & nsMsgViewFlagsType.kGroupBySort)
{
GetDBView().viewFlags &= ~nsMsgViewFlagsType.kGroupBySort;
viewDebug("switching view to all msgs\n");
SwitchView("cmd_viewAllMsgs");
}
// Toggle if not already threaded.
if ((GetDBView().viewFlags & nsMsgViewFlagsType.kThreadedDisplay) == 0)
else if ((viewFlags & nsMsgViewFlagsType.kThreadedDisplay) == 0)
MsgToggleThreaded();
}
function MsgGroupBySort()
{
var dbview = GetDBView();
var viewFlags = dbview.viewFlags;
var sortOrder = dbview.sortOrder;
var sortType = dbview.sortType;
var count = new Object;
var msgFolder = dbview.msgFolder;
viewFlags |= nsMsgViewFlagsType.kThreadedDisplay | nsMsgViewFlagsType.kGroupBySort;
// null this out, so we don't try sort.
if (gDBView) {
gDBView.close();
gDBView = null;
}
var dbviewContractId = "@mozilla.org/messenger/msgdbview;1?type=group";
gDBView = Components.classes[dbviewContractId].createInstance(Components.interfaces.nsIMsgDBView);
if (!gThreadPaneCommandUpdater)
gThreadPaneCommandUpdater = new nsMsgDBViewCommandUpdater();
gDBView.init(messenger, msgWindow, gThreadPaneCommandUpdater);
gDBView.open(msgFolder, sortType, sortOrder, viewFlags, count);
RerootThreadPane();
UpdateSortIndicators(sortType, nsMsgViewSortOrder.ascending);
}
function MsgSortUnthreaded()
{
// Toggle if not already unthreaded.
@ -344,7 +399,41 @@ function UpdateSortIndicators(sortType, sortOrder)
{
// show the twisties if the view is threaded
var threadCol = document.getElementById("threadCol");
var currCol = document.getElementById("subjectCol");
var currCol;
var sortedColumn;
// set the sort indicator on the column we are sorted by
var colID = ConvertSortTypeToColumnID(sortType);
if (colID)
sortedColumn = document.getElementById(colID);
currCol = gDBView.viewFlags & nsMsgViewFlagsType.kGroupBySort
? sortedColumn : document.getElementById("subjectCol");
if (gDBView.viewFlags & nsMsgViewFlagsType.kGroupBySort)
{
var threadTree = document.getElementById("threadTree");
var subjectCol = document.getElementById("subjectCol");
// if this is persistent, need to reverse it when done.
gOldPrevColumn = currCol._previousVisibleColumn;
viewDebug("gOldPrevColumn = " + gOldPrevColumn + "\n");
if (currCol && subjectCol)
threadTree._reorderColumn(currCol, subjectCol, true);
gGroupColumn = currCol;
}
// clear primary attribute from group column if going to a non-grouped view.
if (gGroupColumn && !(gDBView.viewFlags & nsMsgViewFlagsType.kGroupBySort))
{
if (gGroupColumn != currCol)
gGroupColumn.removeAttribute("primary");
if (gOldPrevColumn)
{
var threadTree = GetThreadTree();
threadTree._reorderColumn(gGroupColumn, gOldPrevColumn, false);
}
gGroupColumn = null;
}
if (GetDBView().viewFlags & nsMsgViewFlagsType.kThreadedDisplay) {
threadCol.setAttribute("sortDirection", "ascending");
currCol.setAttribute("primary", "true");
@ -360,17 +449,12 @@ function UpdateSortIndicators(sortType, sortOrder)
currCol = currCol.nextSibling;
}
// set the sort indicator on the column we are sorted by
var colID = ConvertSortTypeToColumnID(sortType);
if (colID) {
var sortedColumn = document.getElementById(colID);
if (sortedColumn) {
if (sortOrder == nsMsgViewSortOrder.ascending) {
sortedColumn.setAttribute("sortDirection","ascending");
}
else {
sortedColumn.setAttribute("sortDirection","descending");
}
if (sortedColumn) {
if (sortOrder == nsMsgViewSortOrder.ascending) {
sortedColumn.setAttribute("sortDirection","ascending");
}
else {
sortedColumn.setAttribute("sortDirection","descending");
}
}
}
@ -439,4 +523,17 @@ function ThreadPaneSelectionChanged()
GetThreadTree().view.selectionChanged();
}
function ThreadPaneOnUnload()
{
// put group column back where it was.
if (gGroupColumn && gOldPrevColumn)
{
var threadTree = GetThreadTree();
viewDebug ("inserting after col " + gOldPrevColumn + "\n");
threadTree._reorderColumn(gGroupColumn, gOldPrevColumn, false);
gGroupColumn = null;
}
}
addEventListener("load",ThreadPaneOnLoad,true);
addEventListener("unload", ThreadPaneOnUnload, false);

View File

@ -201,6 +201,8 @@
<!ENTITY sortThreaded.accesskey "T">
<!ENTITY sortUnthreaded.label "Unthreaded">
<!ENTITY sortUnthreaded.accesskey "h">
<!ENTITY groupBySort.label "Grouped By Sort">
<!ENTITY groupBySort.accesskey "G">
<!ENTITY msgsMenu.label "Messages">
<!ENTITY msgsMenu.accesskey "M">
<!ENTITY viewAll.label "All">

View File

@ -115,6 +115,8 @@ CPPSRCS = \
nsMsgQuickSearchDBView.cpp \
nsMsgSearchDBView.cpp \
nsMsgXFVirtualFolderDBView.cpp \
nsMsgGroupThread.cpp \
nsMsgGroupView.cpp \
nsMsgOfflineManager.cpp \
nsMsgProgress.cpp \
nsMessengerContentHandler.cpp \

View File

@ -409,6 +409,9 @@
#define NS_MSGXFVFDBVIEW_CONTRACTID \
NS_MSGDBVIEW_CONTRACTID_PREFIX "xfvf"
#define NS_MSGGROUPDBVIEW_CONTRACTID \
NS_MSGDBVIEW_CONTRACTID_PREFIX "group"
/* 52f860e0-1dd2-11b2-aa72-bb751981bd00 */
#define NS_MSGTHREADEDDBVIEW_CID \
{0x52f860e0, 0x1dd2, 0x11b2, \
@ -438,6 +441,11 @@
#define NS_MSG_XFVFDBVIEW_CID \
{0x2af6e050, 0x04f6, 0x495a, \
{0x83, 0x87, 0x86, 0xb0, 0xae, 0xb1, 0x86, 0x3c}}
/* e4603d6c-0a74-47c5-b69e-2f8876990304 */
#define NS_MSG_GROUPDBVIEW_CID \
{0xe4603d6c, 0x0a74, 0x47c5, \
{0xb6, 0x9e, 0x2f, 0x88, 0x76, 0x99, 0x03, 0x04}}
//
// nsMsgAccountManager
//

View File

@ -94,6 +94,7 @@ nsIAtom * nsMsgDBView::kHasImageAtom = nsnull;
nsIAtom * nsMsgDBView::kJunkMsgAtom = nsnull;
nsIAtom * nsMsgDBView::kNotJunkMsgAtom = nsnull;
nsIAtom * nsMsgDBView::kDummyMsgAtom = nsnull;
nsIAtom * nsMsgDBView::mLabelPrefColorAtoms[PREF_LABELS_MAX] = {nsnull, nsnull, nsnull, nsnull, nsnull};
@ -180,7 +181,7 @@ void nsMsgDBView::InitializeAtomsAndLiterals()
kHasImageAtom = NS_NewAtom("hasimage");
kJunkMsgAtom = NS_NewAtom("junk");
kNotJunkMsgAtom = NS_NewAtom("notjunk");
kDummyMsgAtom = NS_NewAtom("dummy");
#ifdef SUPPORT_PRIORITY_COLORS
kHighestPriorityAtom = NS_NewAtom("priority-highest");
kHighPriorityAtom = NS_NewAtom("priority-high");
@ -227,6 +228,7 @@ nsMsgDBView::~nsMsgDBView()
NS_IF_RELEASE(kHasImageAtom);
NS_IF_RELEASE(kJunkMsgAtom);
NS_IF_RELEASE(kNotJunkMsgAtom);
NS_IF_RELEASE(kDummyMsgAtom);
#ifdef SUPPORT_PRIORITY_COLORS
NS_IF_RELEASE(kHighestPriorityAtom);
@ -1833,6 +1835,14 @@ NS_IMETHODIMP nsMsgDBView::Close()
return NS_OK;
}
NS_IMETHODIMP nsMsgDBView::OpenWithHdrs(nsISimpleEnumerator *aHeaders, nsMsgViewSortTypeValue aSortType,
nsMsgViewSortOrderValue aSortOrder, nsMsgViewFlagsTypeValue aViewFlags,
PRInt32 *aCount)
{
NS_ASSERTION(PR_FALSE, "not implemented");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsMsgDBView::Init(nsIMessenger * aMessengerInstance, nsIMsgWindow * aMsgWindow, nsIMsgDBViewCommandUpdater *aCmdUpdater)
{
mMsgWindow = aMsgWindow;
@ -3727,7 +3737,7 @@ nsMsgViewIndex nsMsgDBView::ThreadIndexOfMsg(nsMsgKey msgKey,
nsCOMPtr <nsIMsgDBHdr> msgHdr;
nsresult rv = m_db->GetMsgHdrForKey(msgKey, getter_AddRefs(msgHdr));
NS_ENSURE_SUCCESS(rv, nsMsgViewIndex_None);
rv = m_db->GetThreadContainingMsgHdr(msgHdr, getter_AddRefs(threadHdr));
rv = GetThreadContainingMsgHdr(msgHdr, getter_AddRefs(threadHdr));
NS_ENSURE_SUCCESS(rv, nsMsgViewIndex_None);
nsMsgViewIndex retIndex = nsMsgViewIndex_None;
@ -3770,7 +3780,7 @@ nsMsgKey nsMsgDBView::GetKeyOfFirstMsgInThread(nsMsgKey key)
nsCOMPtr <nsIMsgDBHdr> msgHdr;
nsresult rv = m_db->GetMsgHdrForKey(key, getter_AddRefs(msgHdr));
NS_ENSURE_SUCCESS(rv, rv);
rv = m_db->GetThreadContainingMsgHdr(msgHdr, getter_AddRefs(pThread));
rv = GetThreadContainingMsgHdr(msgHdr, getter_AddRefs(pThread));
NS_ENSURE_SUCCESS(rv, rv);
nsMsgKey firstKeyInThread = nsMsgKey_None;
@ -3833,7 +3843,7 @@ nsresult nsMsgDBView::GetThreadCount(nsMsgKey messageKey, PRUint32 *pThreadCount
rv = m_db->GetMsgHdrForKey(messageKey, getter_AddRefs(msgHdr));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr <nsIMsgThread> pThread;
rv = m_db->GetThreadContainingMsgHdr(msgHdr, getter_AddRefs(pThread));
rv = GetThreadContainingMsgHdr(msgHdr, getter_AddRefs(pThread));
if (NS_SUCCEEDED(rv) && pThread != nsnull)
rv = pThread->GetNumChildren(pThreadCount);
return rv;
@ -3998,6 +4008,11 @@ nsresult nsMsgDBView::ExpandAll()
return NS_OK;
}
nsresult nsMsgDBView::GetThreadContainingMsgHdr(nsIMsgDBHdr *msgHdr, nsIMsgThread **pThread)
{
return m_db->GetThreadContainingMsgHdr(msgHdr, pThread);
}
nsresult nsMsgDBView::ExpandByIndex(nsMsgViewIndex index, PRUint32 *pNumExpanded)
{
PRUint32 flags = m_flags[index];
@ -4021,7 +4036,7 @@ nsresult nsMsgDBView::ExpandByIndex(nsMsgViewIndex index, PRUint32 *pNumExpanded
NS_ASSERTION(PR_FALSE, "couldn't find message to expand");
return NS_MSG_MESSAGE_NOT_FOUND;
}
rv = m_db->GetThreadContainingMsgHdr(msgHdr, getter_AddRefs(pThread));
rv = GetThreadContainingMsgHdr(msgHdr, getter_AddRefs(pThread));
m_flags[index] = flags;
NoteChange(index, 1, nsMsgViewNotificationCode::changed);
if (m_viewFlags & nsMsgViewFlagsType::kUnreadOnly)
@ -4117,7 +4132,7 @@ nsresult nsMsgDBView::GetThreadContainingIndex(nsMsgViewIndex index, nsIMsgThrea
nsresult rv = m_db->GetMsgHdrForKey(m_keys[index], getter_AddRefs(msgHdr));
NS_ENSURE_SUCCESS(rv, rv);
return m_db->GetThreadContainingMsgHdr(msgHdr, resultThread);
return GetThreadContainingMsgHdr(msgHdr, resultThread);
}
nsMsgViewIndex nsMsgDBView::GetIndexForThread(nsIMsgDBHdr *hdr)
@ -4184,7 +4199,9 @@ nsMsgViewIndex nsMsgDBView::GetInsertIndex(nsIMsgDBHdr *msgHdr)
if (highIndex == 0)
return highIndex;
if ((m_viewFlags & nsMsgViewFlagsType::kThreadedDisplay) != 0)
if ((m_viewFlags & nsMsgViewFlagsType::kThreadedDisplay) != 0
&& !(m_viewFlags & nsMsgViewFlagsType::kGroupBySort)
&& m_sortOrder != nsMsgViewSortType::byId)
{
return GetIndexForThread(msgHdr);
}
@ -4434,7 +4451,8 @@ nsresult nsMsgDBView::ListIdsInThread(nsIMsgThread *threadHdr, nsMsgViewIndex st
nsMsgViewIndex viewIndex = startOfThreadViewIndex + 1;
*pNumListed = 0;
if (m_viewFlags & nsMsgViewFlagsType::kThreadedDisplay)
// ### need to rework this when we implemented threading in group views.
if (m_viewFlags & nsMsgViewFlagsType::kThreadedDisplay && ! (m_viewFlags & nsMsgViewFlagsType::kGroupBySort))
{
nsMsgKey parentKey = m_keys[startOfThreadViewIndex];
@ -4709,12 +4727,34 @@ NS_IMETHODIMP nsMsgDBView::GetSortType(nsMsgViewSortTypeValue *aSortType)
return NS_OK;
}
NS_IMETHODIMP nsMsgDBView::SetSortType(nsMsgViewSortTypeValue aSortType)
{
m_sortType = aSortType;
return NS_OK;
}
NS_IMETHODIMP nsMsgDBView::GetViewType(nsMsgViewTypeValue *aViewType)
{
NS_ASSERTION(0,"you should be overriding this\n");
return NS_ERROR_UNEXPECTED;
}
nsresult nsMsgDBView::PersistFolderInfo(nsIDBFolderInfo **dbFolderInfo)
{
nsresult rv = m_db->GetDBFolderInfo(dbFolderInfo);
NS_ENSURE_SUCCESS(rv, rv);
// save off sort type and order, view type and flags
(*dbFolderInfo)->SetSortType(m_sortType);
(*dbFolderInfo)->SetSortOrder(m_sortOrder);
(*dbFolderInfo)->SetViewFlags(m_viewFlags);
nsMsgViewTypeValue viewType;
GetViewType(&viewType);
(*dbFolderInfo)->SetViewType(viewType);
return rv;
}
NS_IMETHODIMP nsMsgDBView::GetViewFlags(nsMsgViewFlagsTypeValue *aViewFlags)
{
NS_ENSURE_ARG_POINTER(aViewFlags);
@ -4974,7 +5014,7 @@ nsresult nsMsgDBView::NavigateFromPos(nsMsgNavigationTypeValue motion, nsMsgView
nsCOMPtr <nsIMsgDBHdr> msgHdr;
rv = m_db->GetMsgHdrForKey(*pResultKey, getter_AddRefs(msgHdr));
NS_ENSURE_SUCCESS(rv, rv);
rv = m_db->GetThreadContainingMsgHdr(msgHdr, getter_AddRefs(threadHdr));
rv = GetThreadContainingMsgHdr(msgHdr, getter_AddRefs(threadHdr));
NS_ENSURE_SUCCESS(rv, rv);
NS_ASSERTION(threadHdr, "threadHdr is null");

View File

@ -75,6 +75,7 @@ enum eFieldType {
// reserve the top 8 bits in the msg flags for the view-only flags.
#define MSG_VIEW_FLAGS 0xEE000000
#define MSG_VIEW_FLAG_HASCHILDREN 0x40000000
#define MSG_VIEW_FLAG_DUMMY 0x20000000
#define MSG_VIEW_FLAG_ISTHREAD 0x8000000
/* There currently only 5 labels defined */
@ -140,6 +141,8 @@ protected:
static nsIAtom* kJunkMsgAtom;
static nsIAtom* kNotJunkMsgAtom;
static nsIAtom* kDummyMsgAtom;
static PRUnichar* kReadString;
static PRUnichar* kRepliedString;
static PRUnichar* kForwardedString;
@ -206,16 +209,18 @@ protected:
nsresult GetThreadCount(nsMsgKey messageKey, PRUint32 *pThreadCount);
nsMsgViewIndex GetIndexOfFirstDisplayedKeyInThread(nsIMsgThread *threadHdr);
nsresult GetFirstMessageHdrToDisplayInThread(nsIMsgThread *threadHdr, nsIMsgDBHdr **result);
nsMsgViewIndex ThreadIndexOfMsg(nsMsgKey msgKey,
virtual nsMsgViewIndex ThreadIndexOfMsg(nsMsgKey msgKey,
nsMsgViewIndex msgIndex = nsMsgViewIndex_None,
PRInt32 *pThreadCount = nsnull,
PRUint32 *pFlags = nsnull);
virtual nsresult GetThreadContainingMsgHdr(nsIMsgDBHdr *msgHdr, nsIMsgThread **pThread);
nsMsgKey GetKeyOfFirstMsgInThread(nsMsgKey key);
PRInt32 CountExpandedThread(nsMsgViewIndex index);
nsresult ExpansionDelta(nsMsgViewIndex index, PRInt32 *expansionDelta);
nsresult ReverseSort();
nsresult ReverseThreads();
nsresult SaveSortInfo(nsMsgViewSortTypeValue sortType, nsMsgViewSortOrderValue sortOrder);
nsresult PersistFolderInfo(nsIDBFolderInfo **dbFolderInfo);
nsMsgKey GetAt(nsMsgViewIndex index) ;
nsMsgViewIndex FindViewIndex(nsMsgKey key)
@ -302,7 +307,7 @@ protected:
nsresult InitLabelPrefs(void);
nsresult CopyDBView(nsMsgDBView *aNewMsgDBView, nsIMessenger *aMessengerInstance, nsIMsgWindow *aMsgWindow, nsIMsgDBViewCommandUpdater *aCmdUpdater);
void InitializeAtomsAndLiterals();
PRInt32 FindLevelInThread(nsIMsgDBHdr *msgHdr, nsMsgViewIndex startOfThread, nsMsgViewIndex viewIndex);
virtual PRInt32 FindLevelInThread(nsIMsgDBHdr *msgHdr, nsMsgViewIndex startOfThread, nsMsgViewIndex viewIndex);
nsresult GetImapDeleteModel(nsIMsgFolder *folder);
nsresult UpdateDisplayMessage(nsMsgViewIndex viewPosition);

View File

@ -400,6 +400,7 @@ NS_IMETHODIMP nsMsgGroupThread::GetChildHdrAt(PRInt32 aIndex, nsIMsgDBHdr **aRes
NS_IMETHODIMP nsMsgGroupThread::RemoveChildAt(PRInt32 aIndex)
{
m_keys.RemoveAt(aIndex);
return NS_OK;
}

View File

@ -51,17 +51,24 @@ nsMsgGroupView::~nsMsgGroupView()
{
}
NS_IMETHODIMP nsMsgGroupView::Open(nsIMsgFolder *folder, nsMsgViewSortTypeValue sortType, nsMsgViewSortOrderValue sortOrder, nsMsgViewFlagsTypeValue viewFlags, PRInt32 *pCount)
NS_IMETHODIMP nsMsgGroupView::Open(nsIMsgFolder *aFolder, nsMsgViewSortTypeValue aSortType, nsMsgViewSortOrderValue aSortOrder, nsMsgViewFlagsTypeValue aViewFlags, PRInt32 *aCount)
{
nsCOMPtr <nsISimpleEnumerator> headers;
nsresult rv = folder->GetMsgDatabase(nsnull, getter_AddRefs(m_db));
nsresult rv = aFolder->GetMsgDatabase(nsnull, getter_AddRefs(m_db));
NS_ENSURE_SUCCESS(rv, rv);
m_db->AddListener(this);
m_viewFlags = aViewFlags;
m_sortOrder = aSortOrder;
m_sortType = aSortType;
nsCOMPtr <nsIDBFolderInfo> dbFolderInfo;
PersistFolderInfo(getter_AddRefs(dbFolderInfo));
rv = m_db->EnumerateMessages(getter_AddRefs(headers));
NS_ENSURE_SUCCESS(rv, rv);
m_folder = folder;
return OpenWithHdrs(headers, sortType, sortOrder, viewFlags, pCount);
m_folder = aFolder;
return OpenWithHdrs(headers, aSortType, aSortOrder, aViewFlags, aCount);
}
/* static */PRIntn PR_CALLBACK ReleaseThread (nsHashKey *aKey, void *thread, void *closure)
@ -104,6 +111,27 @@ nsHashKey *nsMsgGroupView::AllocHashKeyForHdr(nsIMsgDBHdr *msgHdr)
}
break;
case nsMsgViewSortType::byLabel:
{
nsMsgLabelValue label;
msgHdr->GetLabel(&label);
return new nsPRUint32Key(label);
}
break;
case nsMsgViewSortType::byPriority:
{
nsMsgPriorityValue priority;
msgHdr->GetPriority(&priority);
return new nsPRUint32Key(priority);
}
break;
case nsMsgViewSortType::byStatus:
{
PRUint32 status = 0;
GetStatusSortValue(msgHdr, &status);
return new nsPRUint32Key(status);
}
case nsMsgViewSortType::byDate:
{
PRUint32 ageBucket;
@ -202,7 +230,10 @@ nsMsgGroupThread *nsMsgGroupView::AddHdrToThread(nsIMsgDBHdr *msgHdr)
m_groupsTable.Put(hashKey, foundThread);
foundThread->AddRef();
if (m_sortType == nsMsgViewSortType::byDate)
{
foundThread->m_dummy = PR_TRUE;
msgFlags |= MSG_VIEW_FLAG_DUMMY | MSG_VIEW_FLAG_HASCHILDREN;
}
nsMsgViewIndex insertIndex = GetInsertIndex(msgHdr);
if (insertIndex == nsMsgViewIndex_None)
@ -334,9 +365,25 @@ NS_IMETHODIMP nsMsgGroupView::OnHdrDeleted(nsIMsgDBHdr *aHdrDeleted, nsMsgKey aP
nsresult rv = GetThreadContainingMsgHdr(aHdrDeleted, getter_AddRefs(thread));
NS_ENSURE_SUCCESS(rv, rv);
nsMsgViewIndex viewIndexOfThread = GetIndexOfFirstDisplayedKeyInThread(thread);
nsHashKey *hashKey = AllocHashKeyForHdr(aHdrDeleted);
thread->RemoveChildHdr(aHdrDeleted, nsnull);
return nsMsgDBView::OnHdrDeleted(aHdrDeleted, aParentKey, aFlags, aInstigator);
nsMsgGroupThread *groupThread = NS_STATIC_CAST(nsMsgGroupThread *, (nsIMsgThread *) thread);
rv = nsMsgDBView::OnHdrDeleted(aHdrDeleted, aParentKey, aFlags, aInstigator);
if (groupThread->m_dummy && !groupThread->NumRealChildren())
{
thread->RemoveChildAt(0); // get rid of dummy
nsMsgDBView::RemoveByIndex(viewIndexOfThread);
NoteChange(viewIndexOfThread, -1, nsMsgViewNotificationCode::insertOrDelete); // an example where view is not the listener - D&D messages
}
if (!groupThread->m_keys.GetSize())
{
nsHashKey *hashKey = AllocHashKeyForHdr(aHdrDeleted);
m_groupsTable.Remove(hashKey);
delete hashKey;
}
return rv;
}
NS_IMETHODIMP nsMsgGroupView::GetCellProperties(PRInt32 aRow, nsITreeColumn *aCol, nsISupportsArray *aProperties)

View File

@ -542,7 +542,8 @@ nsMsgSearchDBView::GetHdrForFirstSelectedMessage(nsIMsgDBHdr **hdr)
{
NS_ENSURE_ARG_POINTER(hdr);
PRInt32 index;
if (!mTreeSelection)
return NS_ERROR_NULL_POINTER;
nsresult rv = mTreeSelection->GetCurrentIndex(&index);
NS_ENSURE_SUCCESS(rv,rv);

View File

@ -67,17 +67,11 @@ NS_IMETHODIMP nsMsgThreadedDBView::Open(nsIMsgFolder *folder, nsMsgViewSortTypeV
// Preset msg hdr cache size for performance reason.
PRInt32 totalMessages, unreadMessages;
nsCOMPtr <nsIDBFolderInfo> dbFolderInfo;
rv = m_db->GetDBFolderInfo(getter_AddRefs(dbFolderInfo));
PersistFolderInfo(getter_AddRefs(dbFolderInfo));
NS_ENSURE_SUCCESS(rv, rv);
// save off sort type and order, view type and flags
dbFolderInfo->SetSortType(m_sortType);
dbFolderInfo->SetSortOrder(m_sortOrder);
dbFolderInfo->SetViewFlags(m_viewFlags);
dbFolderInfo->GetNumUnreadMessages(&unreadMessages);
dbFolderInfo->GetNumMessages(&totalMessages);
nsMsgViewTypeValue viewType;
GetViewType(&viewType);
dbFolderInfo->SetViewType(viewType);
if (m_viewFlags & nsMsgViewFlagsType::kUnreadOnly)
{
// Set unread msg size + extra entries to avoid reallocation on new mail.
@ -289,7 +283,8 @@ NS_IMETHODIMP nsMsgThreadedDBView::Sort(nsMsgViewSortTypeValue sortType, nsMsgVi
return NS_OK;
}
PRBool sortThreads = m_viewFlags & nsMsgViewFlagsType::kThreadedDisplay; // sort threads by sort order
// sort threads by sort order
PRBool sortThreads = m_viewFlags & (nsMsgViewFlagsType::kThreadedDisplay | nsMsgViewFlagsType::kGroupBySort);
// if sort type is by thread, but we're not threaded, change sort type to byId
if (sortType == nsMsgViewSortType::byThread && (m_viewFlags & nsMsgViewFlagsType::kThreadedDisplay) != 0)
@ -308,6 +303,7 @@ NS_IMETHODIMP nsMsgThreadedDBView::Sort(nsMsgViewSortTypeValue sortType, nsMsgVi
{
m_sortType = sortType;
m_viewFlags |= nsMsgViewFlagsType::kThreadedDisplay;
m_viewFlags &= nsMsgViewFlagsType::kGroupBySort;
if ( m_havePrevView)
{
// restore saved id array and flags array
@ -365,7 +361,7 @@ NS_IMETHODIMP nsMsgThreadedDBView::Sort(nsMsgViewSortTypeValue sortType, nsMsgVi
m_prevLevels.InsertAt(0, &m_levels);
// do this before we sort, so that we'll use the cheap method
// of expanding.
m_viewFlags &= ~nsMsgViewFlagsType::kThreadedDisplay;
m_viewFlags &= ~(nsMsgViewFlagsType::kThreadedDisplay | nsMsgViewFlagsType::kGroupBySort);
ExpandAll();
// m_idArray.RemoveAll();
// m_flags.RemoveAll();
@ -554,6 +550,7 @@ nsresult nsMsgThreadedDBView::InitSort(nsMsgViewSortTypeValue sortType, nsMsgVie
nsMsgDBView::Sort(nsMsgViewSortType::byId, sortOrder); // sort top level threads by id.
m_sortType = nsMsgViewSortType::byThread;
m_viewFlags |= nsMsgViewFlagsType::kThreadedDisplay;
m_viewFlags &= ~nsMsgViewFlagsType::kGroupBySort;
SetViewFlags(m_viewFlags); // persist the view flags.
// m_db->SetSortInfo(m_sortType, sortOrder);
}

View File

@ -57,7 +57,7 @@ public:
NS_IMETHOD GetViewType(nsMsgViewTypeValue *aViewType);
NS_IMETHOD GetSupportsThreading(PRBool *aResult);
NS_IMETHOD OnParentChanged (nsMsgKey aKeyChanged, nsMsgKey oldParent, nsMsgKey newParent, nsIDBChangeListener *aInstigator);
NS_IMETHOD OnParentChanged (nsMsgKey aKeyChanged, nsMsgKey oldParent, nsMsgKey newParent, nsIDBChangeListener *aInstigator);
protected:
virtual const char * GetViewName(void) {return "ThreadedDBView"; }
@ -70,16 +70,16 @@ protected:
nsresult SortThreads(nsMsgViewSortTypeValue sortType, nsMsgViewSortOrderValue sortOrder);
virtual void OnExtraFlagChanged(nsMsgViewIndex index, PRUint32 extraFlag);
virtual void OnHeaderAddedOrDeleted();
void ClearPrevIdArray();
void ClearPrevIdArray();
virtual nsresult RemoveByIndex(nsMsgViewIndex index);
nsMsgViewIndex GetInsertInfoForNewHdr(nsIMsgDBHdr *newHdr, nsMsgViewIndex threadIndex, PRInt32 targetLevel);
// these are used to save off the previous view so that bopping back and forth
// between two views is quick (e.g., threaded and flat sorted by date).
PRBool m_havePrevView;
nsMsgKeyArray m_prevKeys; //this is used for caching non-threaded view.
nsUInt32Array m_prevFlags;
nsUint8Array m_prevLevels;
PRBool m_havePrevView;
nsMsgKeyArray m_prevKeys; //this is used for caching non-threaded view.
nsUInt32Array m_prevFlags;
nsUint8Array m_prevLevels;
nsCOMPtr <nsISimpleEnumerator> m_threadEnumerator;
};