diff --git a/mozilla/mail/base/content/commandglue.js b/mozilla/mail/base/content/commandglue.js index d74cfb7df4c..a196dc1f6be 100644 --- a/mozilla/mail/base/content/commandglue.js +++ b/mozilla/mail/base/content/commandglue.js @@ -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; } diff --git a/mozilla/mail/base/content/mailWindowOverlay.js b/mozilla/mail/base/content/mailWindowOverlay.js index 1d3b311a40d..cbc98f72e0d 100644 --- a/mozilla/mail/base/content/mailWindowOverlay.js +++ b/mozilla/mail/base/content/mailWindowOverlay.js @@ -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() diff --git a/mozilla/mail/base/content/mailWindowOverlay.xul b/mozilla/mail/base/content/mailWindowOverlay.xul index 46a0baac44e..37681135f42 100644 --- a/mozilla/mail/base/content/mailWindowOverlay.xul +++ b/mozilla/mail/base/content/mailWindowOverlay.xul @@ -1226,6 +1226,7 @@ + diff --git a/mozilla/mail/base/skin/mailWindow1.css b/mozilla/mail/base/skin/mailWindow1.css index 9c54c4511f5..d3810fe9524 100644 --- a/mozilla/mail/base/skin/mailWindow1.css +++ b/mozilla/mail/base/skin/mailWindow1.css @@ -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"); } diff --git a/mozilla/mailnews/base/build/nsMsgFactory.cpp b/mozilla/mailnews/base/build/nsMsgFactory.cpp index 6076a2f192d..3b42863f0a2 100644 --- a/mozilla/mailnews/base/build/nsMsgFactory.cpp +++ b/mozilla/mailnews/base/build/nsMsgFactory.cpp @@ -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, diff --git a/mozilla/mailnews/base/public/nsIMsgDBView.idl b/mozilla/mailnews/base/public/nsIMsgDBView.idl index afb24bd098d..2997e04f8ba 100644 --- a/mozilla/mailnews/base/public/nsIMsgDBView.idl +++ b/mozilla/mailnews/base/public/nsIMsgDBView.idl @@ -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; diff --git a/mozilla/mailnews/base/resources/content/commandglue.js b/mozilla/mailnews/base/resources/content/commandglue.js index a1d9587c251..b69ad7bf562 100644 --- a/mozilla/mailnews/base/resources/content/commandglue.js +++ b/mozilla/mailnews/base/resources/content/commandglue.js @@ -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; } diff --git a/mozilla/mailnews/base/resources/content/mailWindowOverlay.js b/mozilla/mailnews/base/resources/content/mailWindowOverlay.js index 8b7954efae2..f4e11c89cd4 100644 --- a/mozilla/mailnews/base/resources/content/mailWindowOverlay.js +++ b/mozilla/mailnews/base/resources/content/mailWindowOverlay.js @@ -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() diff --git a/mozilla/mailnews/base/resources/content/mailWindowOverlay.xul b/mozilla/mailnews/base/resources/content/mailWindowOverlay.xul index 0871075e21a..9d30bbef026 100644 --- a/mozilla/mailnews/base/resources/content/mailWindowOverlay.xul +++ b/mozilla/mailnews/base/resources/content/mailWindowOverlay.xul @@ -1224,6 +1224,7 @@ + diff --git a/mozilla/mailnews/base/resources/content/threadPane.js b/mozilla/mailnews/base/resources/content/threadPane.js index 3776b4e1334..c82b4a93374 100644 --- a/mozilla/mailnews/base/resources/content/threadPane.js +++ b/mozilla/mailnews/base/resources/content/threadPane.js @@ -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); diff --git a/mozilla/mailnews/base/resources/locale/en-US/messenger.dtd b/mozilla/mailnews/base/resources/locale/en-US/messenger.dtd index 51a0f18005b..7979fa10570 100644 --- a/mozilla/mailnews/base/resources/locale/en-US/messenger.dtd +++ b/mozilla/mailnews/base/resources/locale/en-US/messenger.dtd @@ -201,6 +201,8 @@ + + diff --git a/mozilla/mailnews/base/src/Makefile.in b/mozilla/mailnews/base/src/Makefile.in index 29d9ce5f716..5fffad51703 100644 --- a/mozilla/mailnews/base/src/Makefile.in +++ b/mozilla/mailnews/base/src/Makefile.in @@ -115,6 +115,8 @@ CPPSRCS = \ nsMsgQuickSearchDBView.cpp \ nsMsgSearchDBView.cpp \ nsMsgXFVirtualFolderDBView.cpp \ + nsMsgGroupThread.cpp \ + nsMsgGroupView.cpp \ nsMsgOfflineManager.cpp \ nsMsgProgress.cpp \ nsMessengerContentHandler.cpp \ diff --git a/mozilla/mailnews/base/src/nsMsgBaseCID.h b/mozilla/mailnews/base/src/nsMsgBaseCID.h index e048e3bcd27..ac1077b3af7 100644 --- a/mozilla/mailnews/base/src/nsMsgBaseCID.h +++ b/mozilla/mailnews/base/src/nsMsgBaseCID.h @@ -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 // diff --git a/mozilla/mailnews/base/src/nsMsgDBView.cpp b/mozilla/mailnews/base/src/nsMsgDBView.cpp index 2acd30e41d4..eaec26461f4 100644 --- a/mozilla/mailnews/base/src/nsMsgDBView.cpp +++ b/mozilla/mailnews/base/src/nsMsgDBView.cpp @@ -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 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 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 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 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"); diff --git a/mozilla/mailnews/base/src/nsMsgDBView.h b/mozilla/mailnews/base/src/nsMsgDBView.h index 4017c0fdcb9..c857e4e1a16 100644 --- a/mozilla/mailnews/base/src/nsMsgDBView.h +++ b/mozilla/mailnews/base/src/nsMsgDBView.h @@ -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); diff --git a/mozilla/mailnews/base/src/nsMsgGroupThread.cpp b/mozilla/mailnews/base/src/nsMsgGroupThread.cpp index ff28cbd55c9..b02768dc0a2 100755 --- a/mozilla/mailnews/base/src/nsMsgGroupThread.cpp +++ b/mozilla/mailnews/base/src/nsMsgGroupThread.cpp @@ -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; } diff --git a/mozilla/mailnews/base/src/nsMsgGroupView.cpp b/mozilla/mailnews/base/src/nsMsgGroupView.cpp index a52489338e0..ed04bfbbf0d 100755 --- a/mozilla/mailnews/base/src/nsMsgGroupView.cpp +++ b/mozilla/mailnews/base/src/nsMsgGroupView.cpp @@ -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 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 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) diff --git a/mozilla/mailnews/base/src/nsMsgSearchDBView.cpp b/mozilla/mailnews/base/src/nsMsgSearchDBView.cpp index 797bb7259bb..b88e931d727 100644 --- a/mozilla/mailnews/base/src/nsMsgSearchDBView.cpp +++ b/mozilla/mailnews/base/src/nsMsgSearchDBView.cpp @@ -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); diff --git a/mozilla/mailnews/base/src/nsMsgThreadedDBView.cpp b/mozilla/mailnews/base/src/nsMsgThreadedDBView.cpp index 32dc8c7b21f..765ab3ac775 100644 --- a/mozilla/mailnews/base/src/nsMsgThreadedDBView.cpp +++ b/mozilla/mailnews/base/src/nsMsgThreadedDBView.cpp @@ -67,17 +67,11 @@ NS_IMETHODIMP nsMsgThreadedDBView::Open(nsIMsgFolder *folder, nsMsgViewSortTypeV // Preset msg hdr cache size for performance reason. PRInt32 totalMessages, unreadMessages; nsCOMPtr 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); } diff --git a/mozilla/mailnews/base/src/nsMsgThreadedDBView.h b/mozilla/mailnews/base/src/nsMsgThreadedDBView.h index afb06e41fdc..6f5dc95a049 100644 --- a/mozilla/mailnews/base/src/nsMsgThreadedDBView.h +++ b/mozilla/mailnews/base/src/nsMsgThreadedDBView.h @@ -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 m_threadEnumerator; };