diff options
Diffstat (limited to '')
-rw-r--r-- | comm/mailnews/base/src/nsMsgDBView.h | 558 |
1 files changed, 558 insertions, 0 deletions
diff --git a/comm/mailnews/base/src/nsMsgDBView.h b/comm/mailnews/base/src/nsMsgDBView.h new file mode 100644 index 0000000000..6033a490bc --- /dev/null +++ b/comm/mailnews/base/src/nsMsgDBView.h @@ -0,0 +1,558 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef _nsMsgDBView_H_ +#define _nsMsgDBView_H_ + +#include "nsIMsgDBView.h" +#include "nsIMsgWindow.h" +#include "nsIMessenger.h" +#include "nsIMsgDatabase.h" +#include "nsIMsgHdr.h" +#include "MailNewsTypes.h" +#include "nsIDBChangeListener.h" +#include "nsITreeView.h" +#include "mozilla/dom/XULTreeElement.h" +#include "nsITreeSelection.h" +#include "nsIMsgFolder.h" +#include "nsIMsgThread.h" +#include "nsMsgUtils.h" +#include "nsIImapIncomingServer.h" +#include "nsIMsgFilterPlugin.h" +#include "nsIStringBundle.h" +#include "nsMsgTagService.h" +#include "nsCOMArray.h" +#include "nsTArray.h" +#include "nsTHashtable.h" +#include "nsHashKeys.h" +#include "nsIMsgCustomColumnHandler.h" +#include "nsIWeakReferenceUtils.h" +#include "nsMsgEnumerator.h" + +#define MESSENGER_STRING_URL "chrome://messenger/locale/messenger.properties" + +typedef AutoTArray<nsMsgViewIndex, 1> nsMsgViewIndexArray; +static_assert(nsMsgViewIndex(nsMsgViewIndexArray::NoIndex) == + nsMsgViewIndex_None, + "These need to be the same value."); + +enum eFieldType { kCollationKey, kU32 }; + +// This is used in an nsTArray<> to keep track of a multi-column sort. +class MsgViewSortColumnInfo { + public: + MsgViewSortColumnInfo(const MsgViewSortColumnInfo& other); + MsgViewSortColumnInfo() + : mSortType(nsMsgViewSortType::byNone), + mSortOrder(nsMsgViewSortOrder::none) {} + bool operator==(const MsgViewSortColumnInfo& other) const; + nsMsgViewSortTypeValue mSortType; + nsMsgViewSortOrderValue mSortOrder; + // If mSortType == byCustom, info about the custom column sort. + nsString mCustomColumnName; + nsCOMPtr<nsIMsgCustomColumnHandler> mColHandler; +}; + +// Reserve some bits in the msg flags for the view-only flags. +// NOTE: this bit space is shared by nsMsgMessageFlags (and labels). +#define MSG_VIEW_FLAG_ISTHREAD 0x8000000 +#define MSG_VIEW_FLAG_DUMMY 0x20000000 +#define MSG_VIEW_FLAG_HASCHILDREN 0x40000000 +#define MSG_VIEW_FLAGS \ + (MSG_VIEW_FLAG_HASCHILDREN | MSG_VIEW_FLAG_DUMMY | MSG_VIEW_FLAG_ISTHREAD) + +// Helper struct for sorting by numeric fields. +// Associates a message with a key for ordering it in the view. +struct IdUint32 { + nsMsgKey id; + uint32_t bits; + uint32_t dword; // The numeric key. + nsIMsgFolder* folder; +}; + +// Extends IdUint32 for sorting by a collation key field (eg subject). +// (Also used as IdUint32 a couple of places to simplify the code, where +// the overhead of an unused nsTArray isn't a big deal). +struct IdKey : public IdUint32 { + nsTArray<uint8_t> key; +}; + +class nsMsgDBViewService final : public nsIMsgDBViewService { + public: + NS_DECL_ISUPPORTS + NS_DECL_NSIMSGDBVIEWSERVICE + + nsMsgDBViewService(){}; + + protected: + ~nsMsgDBViewService(){}; +}; + +// This is an abstract implementation class. +// The actual view objects will be instances of sub-classes of this class. +class nsMsgDBView : public nsIMsgDBView, + public nsIDBChangeListener, + public nsITreeView, + public nsIJunkMailClassificationListener { + public: + friend class nsMsgDBViewService; + nsMsgDBView(); + + NS_DECL_ISUPPORTS + NS_DECL_NSIMSGDBVIEW + NS_DECL_NSIDBCHANGELISTENER + NS_DECL_NSITREEVIEW + NS_DECL_NSIJUNKMAILCLASSIFICATIONLISTENER + + nsMsgViewIndex GetInsertIndexHelper(nsIMsgDBHdr* msgHdr, + nsTArray<nsMsgKey>& keys, + nsCOMArray<nsIMsgFolder>* folders, + nsMsgViewSortOrderValue sortOrder, + nsMsgViewSortTypeValue sortType); + int32_t SecondaryCompare(nsMsgKey key1, nsIMsgFolder* folder1, nsMsgKey key2, + nsIMsgFolder* folder2, + class viewSortInfo* comparisonContext); + + protected: + virtual ~nsMsgDBView(); + + static nsString kHighestPriorityString; + static nsString kHighPriorityString; + static nsString kLowestPriorityString; + static nsString kLowPriorityString; + static nsString kNormalPriorityString; + + static nsString kReadString; + static nsString kRepliedString; + static nsString kForwardedString; + static nsString kRedirectedString; + static nsString kNewString; + + // Used for group views. + static nsString kTodayString; + static nsString kYesterdayString; + static nsString kLastWeekString; + static nsString kTwoWeeksAgoString; + static nsString kOldMailString; + static nsString kFutureDateString; + + RefPtr<mozilla::dom::XULTreeElement> mTree; + nsCOMPtr<nsIMsgJSTree> mJSTree; + nsCOMPtr<nsITreeSelection> mTreeSelection; + // We cache this to determine when to push command status notifications. + uint32_t mNumSelectedRows; + // Set when the message pane is collapsed. + bool mSuppressMsgDisplay; + bool mSuppressCommandUpdating; + // Set when we're telling the outline a row is being removed. Used to + // suppress msg loading during delete/move operations. + bool mRemovingRow; + bool mCommandsNeedDisablingBecauseOfSelection; + bool mSuppressChangeNotification; + + virtual const char* GetViewName(void) { return "MsgDBView"; } + nsresult FetchAuthor(nsIMsgDBHdr* aHdr, nsAString& aAuthorString); + nsresult FetchRecipients(nsIMsgDBHdr* aHdr, nsAString& aRecipientsString); + nsresult FetchSubject(nsIMsgDBHdr* aMsgHdr, uint32_t aFlags, + nsAString& aValue); + nsresult FetchDate(nsIMsgDBHdr* aHdr, nsAString& aDateString, + bool rcvDate = false); + nsresult FetchStatus(uint32_t aFlags, nsAString& aStatusString); + nsresult FetchSize(nsIMsgDBHdr* aHdr, nsAString& aSizeString); + nsresult FetchPriority(nsIMsgDBHdr* aHdr, nsAString& aPriorityString); + nsresult FetchLabel(nsIMsgDBHdr* aHdr, nsAString& aLabelString); + nsresult FetchTags(nsIMsgDBHdr* aHdr, nsAString& aTagString); + nsresult FetchKeywords(nsIMsgDBHdr* aHdr, nsACString& keywordString); + nsresult FetchRowKeywords(nsMsgViewIndex aRow, nsIMsgDBHdr* aHdr, + nsACString& keywordString); + nsresult FetchAccount(nsIMsgDBHdr* aHdr, nsAString& aAccount); + bool IsOutgoingMsg(nsIMsgDBHdr* aHdr); + + // The default enumerator is over the db, but things like + // quick search views will enumerate just the displayed messages. + virtual nsresult GetMessageEnumerator(nsIMsgEnumerator** enumerator); + // this is a message enumerator that enumerates based on the view contents + virtual nsresult GetViewEnumerator(nsIMsgEnumerator** enumerator); + + // Save and Restore Selection are a pair of routines you should + // use when performing an operation which is going to change the view + // and you want to remember the selection. (i.e. for sorting). + // Call SaveAndClearSelection and we'll give you an array of msg keys for + // the current selection. We also freeze and clear the selection. + // When you are done changing the view, + // call RestoreSelection passing in the same array + // and we'll restore the selection AND unfreeze selection in the UI. + nsresult SaveAndClearSelection(nsMsgKey* aCurrentMsgKey, + nsTArray<nsMsgKey>& aMsgKeyArray); + nsresult RestoreSelection(nsMsgKey aCurrentmsgKey, + nsTArray<nsMsgKey>& aMsgKeyArray); + + // This is not safe to use when you have a selection. + // RowCountChanged() will call AdjustSelection(). + // It should be called after SaveAndClearSelection() and before + // RestoreSelection(). + nsresult AdjustRowCount(int32_t rowCountBeforeSort, + int32_t rowCountAfterSort); + + nsresult GenerateURIForMsgKey(nsMsgKey aMsgKey, nsIMsgFolder* folder, + nsACString& aURI); + + // Routines used in building up view. + virtual bool WantsThisThread(nsIMsgThread* thread); + virtual nsresult AddHdr(nsIMsgDBHdr* msgHdr, + nsMsgViewIndex* resultIndex = nullptr); + bool GetShowingIgnored() { + return (m_viewFlags & nsMsgViewFlagsType::kShowIgnored) != 0; + } + bool OperateOnMsgsInCollapsedThreads(); + + virtual nsresult OnNewHeader(nsIMsgDBHdr* aNewHdr, nsMsgKey parentKey, + bool ensureListed); + virtual nsMsgViewIndex GetInsertIndex(nsIMsgDBHdr* msgHdr); + nsMsgViewIndex GetIndexForThread(nsIMsgDBHdr* hdr); + nsMsgViewIndex GetThreadRootIndex(nsIMsgDBHdr* msgHdr); + virtual nsresult GetMsgHdrForViewIndex(nsMsgViewIndex index, + nsIMsgDBHdr** msgHdr); + // Given a view index, return the index of the top-level msg in the thread. + nsMsgViewIndex GetThreadIndex(nsMsgViewIndex msgIndex); + + virtual void InsertMsgHdrAt(nsMsgViewIndex index, nsIMsgDBHdr* hdr, + nsMsgKey msgKey, uint32_t flags, uint32_t level); + virtual void SetMsgHdrAt(nsIMsgDBHdr* hdr, nsMsgViewIndex index, + nsMsgKey msgKey, uint32_t flags, uint32_t level); + virtual void InsertEmptyRows(nsMsgViewIndex viewIndex, int32_t numRows); + virtual void RemoveRows(nsMsgViewIndex viewIndex, int32_t numRows); + nsresult ToggleExpansion(nsMsgViewIndex index, uint32_t* numChanged); + nsresult ExpandByIndex(nsMsgViewIndex index, uint32_t* pNumExpanded); + nsresult CollapseByIndex(nsMsgViewIndex index, uint32_t* pNumCollapsed); + nsresult ExpandAll(); + nsresult CollapseAll(); + nsresult ExpandAndSelectThread(); + + // Helper routines for thread expanding and collapsing. + nsresult GetThreadCount(nsMsgViewIndex viewIndex, uint32_t* pThreadCount); + /** + * Retrieve the view index of the first displayed message in the given thread. + * @param threadHdr The thread you care about. + * @param allowDummy Should dummy headers be returned when the non-dummy + * header is available? If the root node of the thread is a dummy header + * and you pass false, then we will return the first child of the thread + * unless the thread is elided, in which case we will return the root. + * If you pass true, we will always return the root. + * @return the view index of the first message in the thread, if any. + */ + nsMsgViewIndex GetIndexOfFirstDisplayedKeyInThread(nsIMsgThread* threadHdr, + bool allowDummy = false); + virtual nsresult GetFirstMessageHdrToDisplayInThread(nsIMsgThread* threadHdr, + nsIMsgDBHdr** result); + virtual nsMsgViewIndex ThreadIndexOfMsg( + nsMsgKey msgKey, nsMsgViewIndex msgIndex = nsMsgViewIndex_None, + int32_t* pThreadCount = nullptr, uint32_t* pFlags = nullptr); + nsMsgViewIndex ThreadIndexOfMsgHdr( + nsIMsgDBHdr* msgHdr, nsMsgViewIndex msgIndex = nsMsgViewIndex_None, + int32_t* pThreadCount = nullptr, uint32_t* pFlags = nullptr); + nsMsgKey GetKeyOfFirstMsgInThread(nsMsgKey key); + int32_t CountExpandedThread(nsMsgViewIndex index); + virtual nsresult ExpansionDelta(nsMsgViewIndex index, + int32_t* expansionDelta); + void ReverseSort(); + void ReverseThreads(); + nsresult SaveSortInfo(nsMsgViewSortTypeValue sortType, + nsMsgViewSortOrderValue sortOrder); + nsresult RestoreSortInfo(); + nsresult PersistFolderInfo(nsIDBFolderInfo** dbFolderInfo); + void SetMRUTimeForFolder(nsIMsgFolder* folder); + + nsMsgKey GetAt(nsMsgViewIndex index) { + return m_keys.SafeElementAt(index, nsMsgKey_None); + } + + nsMsgViewIndex FindViewIndex(nsMsgKey key) { return FindKey(key, false); } + /** + * Find the message header if it is visible in this view. (Messages in + * threads/groups that are elided will not be + * @param msgHdr Message header to look for. + * @param startIndex The index to start looking from. + * @param allowDummy Are dummy headers acceptable? If yes, then for a group + * with a dummy header, we return the root of the thread (the dummy + * header), otherwise we return the actual "content" header for the + * message. + * @return The view index of the header found, if any. + */ + virtual nsMsgViewIndex FindHdr(nsIMsgDBHdr* msgHdr, + nsMsgViewIndex startIndex = 0, + bool allowDummy = false); + virtual nsMsgViewIndex FindKey(nsMsgKey key, bool expand); + virtual nsresult GetDBForViewIndex(nsMsgViewIndex index, nsIMsgDatabase** db); + virtual nsCOMArray<nsIMsgFolder>* GetFolders(); + virtual nsresult GetFolderFromMsgURI(const nsACString& aMsgURI, + nsIMsgFolder** aFolder); + + virtual nsresult ListIdsInThread(nsIMsgThread* threadHdr, + nsMsgViewIndex viewIndex, + uint32_t* pNumListed); + nsresult ListUnreadIdsInThread(nsIMsgThread* threadHdr, + nsMsgViewIndex startOfThreadViewIndex, + uint32_t* pNumListed); + nsMsgViewIndex FindParentInThread(nsMsgKey parentKey, + nsMsgViewIndex startOfThreadViewIndex); + virtual nsresult ListIdsInThreadOrder(nsIMsgThread* threadHdr, + nsMsgKey parentKey, uint32_t level, + nsMsgViewIndex* viewIndex, + uint32_t* pNumListed); + uint32_t GetSize(void) { return (m_keys.Length()); } + + // For commands. + virtual nsresult ApplyCommandToIndicesWithFolder( + nsMsgViewCommandTypeValue command, + nsTArray<nsMsgViewIndex> const& selection, nsIMsgFolder* destFolder); + virtual nsresult CopyMessages(nsIMsgWindow* window, + nsTArray<nsMsgViewIndex> const& selection, + bool isMove, nsIMsgFolder* destFolder); + virtual nsresult DeleteMessages(nsIMsgWindow* window, + nsTArray<nsMsgViewIndex> const& selection, + bool deleteStorage); + nsresult GetHeadersFromSelection(nsTArray<nsMsgViewIndex> const& selection, + nsTArray<RefPtr<nsIMsgDBHdr>>& hdrs); + // ListCollapsedChildren() adds to messageArray (rather than replacing it). + virtual nsresult ListCollapsedChildren( + nsMsgViewIndex viewIndex, nsTArray<RefPtr<nsIMsgDBHdr>>& messageArray); + + nsresult SetMsgHdrJunkStatus(nsIJunkMailPlugin* aJunkPlugin, + nsIMsgDBHdr* aMsgHdr, + nsMsgJunkStatus aNewClassification); + nsresult ToggleReadByIndex(nsMsgViewIndex index); + nsresult SetReadByIndex(nsMsgViewIndex index, bool read); + nsresult SetThreadOfMsgReadByIndex(nsMsgViewIndex index, + nsTArray<nsMsgKey>& keysMarkedRead, + bool read); + nsresult SetFlaggedByIndex(nsMsgViewIndex index, bool mark); + nsresult OrExtraFlag(nsMsgViewIndex index, uint32_t orflag); + nsresult AndExtraFlag(nsMsgViewIndex index, uint32_t andflag); + nsresult SetExtraFlag(nsMsgViewIndex index, uint32_t extraflag); + virtual nsresult RemoveByIndex(nsMsgViewIndex index); + virtual void OnExtraFlagChanged(nsMsgViewIndex /*index*/, + uint32_t /*extraFlag*/) {} + virtual void OnHeaderAddedOrDeleted() {} + nsresult ToggleWatched(nsTArray<nsMsgViewIndex> const& selection); + nsresult SetThreadWatched(nsIMsgThread* thread, nsMsgViewIndex index, + bool watched); + nsresult SetThreadIgnored(nsIMsgThread* thread, nsMsgViewIndex threadIndex, + bool ignored); + nsresult SetSubthreadKilled(nsIMsgDBHdr* header, nsMsgViewIndex msgIndex, + bool ignored); + nsresult DownloadForOffline(nsIMsgWindow* window, + nsTArray<nsMsgViewIndex> const& selection); + nsresult DownloadFlaggedForOffline(nsIMsgWindow* window); + nsMsgViewIndex GetThreadFromMsgIndex(nsMsgViewIndex index, + nsIMsgThread** threadHdr); + /// Should junk commands be enabled for the current message in the view? + bool JunkControlsEnabled(nsMsgViewIndex aViewIndex); + + // For sorting. + nsresult GetFieldTypeAndLenForSort( + nsMsgViewSortTypeValue sortType, uint16_t* pMaxLen, + eFieldType* pFieldType, nsIMsgCustomColumnHandler* colHandler = nullptr); + nsresult GetCollationKey(nsIMsgDBHdr* msgHdr, nsMsgViewSortTypeValue sortType, + nsTArray<uint8_t>& result, + nsIMsgCustomColumnHandler* colHandler = nullptr); + nsresult GetLongField(nsIMsgDBHdr* msgHdr, nsMsgViewSortTypeValue sortType, + uint32_t* result, + nsIMsgCustomColumnHandler* colHandler = nullptr); + + static int FnSortIdKey(const IdKey* pItem1, const IdKey* pItem2, + viewSortInfo* sortInfo); + static int FnSortIdUint32(const IdUint32* pItem1, const IdUint32* pItem2, + viewSortInfo* sortInfo); + + nsresult GetStatusSortValue(nsIMsgDBHdr* msgHdr, uint32_t* result); + nsresult GetLocationCollationKey(nsIMsgDBHdr* msgHdr, + nsTArray<uint8_t>& result); + void PushSort(const MsgViewSortColumnInfo& newSort); + nsresult EncodeColumnSort(nsString& columnSortString); + nsresult DecodeColumnSort(nsString& columnSortString); + // For view navigation. + nsresult NavigateFromPos(nsMsgNavigationTypeValue motion, + nsMsgViewIndex startIndex, nsMsgKey* pResultKey, + nsMsgViewIndex* pResultIndex, + nsMsgViewIndex* pThreadIndex, bool wrap); + nsresult FindNextFlagged(nsMsgViewIndex startIndex, + nsMsgViewIndex* pResultIndex); + nsresult FindFirstNew(nsMsgViewIndex* pResultIndex); + nsresult FindPrevUnread(nsMsgKey startKey, nsMsgKey* pResultKey, + nsMsgKey* resultThreadId); + nsresult FindFirstFlagged(nsMsgViewIndex* pResultIndex); + nsresult FindPrevFlagged(nsMsgViewIndex startIndex, + nsMsgViewIndex* pResultIndex); + nsresult MarkThreadOfMsgRead(nsMsgKey msgId, nsMsgViewIndex msgIndex, + nsTArray<nsMsgKey>& idsMarkedRead, bool bRead); + nsresult MarkThreadRead(nsIMsgThread* threadHdr, nsMsgViewIndex threadIndex, + nsTArray<nsMsgKey>& idsMarkedRead, bool bRead); + bool IsValidIndex(nsMsgViewIndex index); + nsresult ToggleIgnored(nsTArray<nsMsgViewIndex> const& selection, + nsMsgViewIndex* resultIndex, bool* resultToggleState); + nsresult ToggleMessageKilled(nsTArray<nsMsgViewIndex> const& selection, + nsMsgViewIndex* resultIndex, + bool* resultToggleState); + bool OfflineMsgSelected(nsTArray<nsMsgViewIndex> const& selection); + bool NonDummyMsgSelected(nsTArray<nsMsgViewIndex> const& selection); + static void GetString(const char16_t* aStringName, nsAString& aValue); + static nsresult GetPrefLocalizedString(const char* aPrefName, + nsString& aResult); + nsresult AppendKeywordProperties(const nsACString& keywords, + nsAString& properties, bool* tagAdded); + static nsresult InitLabelStrings(void); + nsresult CopyDBView(nsMsgDBView* aNewMsgDBView, + nsIMessenger* aMessengerInstance, + nsIMsgWindow* aMsgWindow, + nsIMsgDBViewCommandUpdater* aCmdUpdater); + static void InitializeLiterals(); + virtual int32_t FindLevelInThread(nsIMsgDBHdr* msgHdr, + nsMsgViewIndex startOfThread, + nsMsgViewIndex viewIndex); + nsresult GetImapDeleteModel(nsIMsgFolder* folder); + nsresult UpdateDisplayMessage(nsMsgViewIndex viewPosition); + nsresult GetDBForHeader(nsIMsgDBHdr* msgHdr, nsIMsgDatabase** db); + + bool AdjustReadFlag(nsIMsgDBHdr* msgHdr, uint32_t* msgFlags); + void FreeAll(nsTArray<void*>* ptrs); + void ClearHdrCache(); + + // The message held in each row. + nsTArray<nsMsgKey> m_keys; + // Flags for each row, combining nsMsgMessageFlags and MSG_VIEW_FLAGS. + nsTArray<uint32_t> m_flags; + // Threading level of each row (1=top) + nsTArray<uint8_t> m_levels; + + nsMsgImapDeleteModel mDeleteModel; + + // Cache the most recently asked for header and corresponding msgKey. + nsCOMPtr<nsIMsgDBHdr> m_cachedHdr; + nsMsgKey m_cachedMsgKey; + + // We need to store the message key for the message we are currently + // displaying to ensure we don't try to redisplay the same message just + // because the selection changed (i.e. after a sort). + nsMsgKey m_currentlyDisplayedMsgKey; + nsCString m_currentlyDisplayedMsgUri; + nsMsgViewIndex m_currentlyDisplayedViewIndex; + // If we're deleting messages, we want to hold off loading messages on + // selection changed until the delete is done and we want to batch + // notifications. + bool m_deletingRows; + // For certain special folders and descendants of those folders + // (like the "Sent" folder, "Sent/Old Sent"). + // The Sender column really shows recipients. + + // Server types for this view's folder + bool mIsNews; // We have special icons for news. + bool mIsRss; // RSS affects enabling of junk commands. + bool mIsXFVirtual; // A virtual folder with multiple folders. + + bool mShowSizeInLines; // For news we show lines instead of size when true. + bool mSortThreadsByRoot; // As opposed to by the newest message. + bool m_sortValid; + bool m_checkedCustomColumns; + bool mSelectionSummarized; + // We asked the front end to summarize the selection and it did not. + bool mSummarizeFailed; + uint8_t m_saveRestoreSelectionDepth; + + nsCOMPtr<nsIMsgDatabase> m_db; + nsCOMPtr<nsIMsgFolder> m_folder; + // For virtual folders, the VF db. + nsCOMPtr<nsIMsgFolder> m_viewFolder; + nsString mMessageType; + nsTArray<MsgViewSortColumnInfo> m_sortColumns; + nsMsgViewSortTypeValue m_sortType; + nsMsgViewSortOrderValue m_sortOrder; + nsString m_curCustomColumn; + nsMsgViewSortTypeValue m_secondarySort; + nsMsgViewSortOrderValue m_secondarySortOrder; + nsString m_secondaryCustomColumn; + nsMsgViewFlagsTypeValue m_viewFlags; + + // I18N date formatter service which we'll want to cache locally. + nsCOMPtr<nsIMsgTagService> mTagService; + nsWeakPtr mMessengerWeak; + nsWeakPtr mMsgWindowWeak; + // We push command update notifications to the UI from this. + nsWeakPtr mCommandUpdater; + static nsCOMPtr<nsIStringBundle> mMessengerStringBundle; + + // Used to determine when to start and end junk plugin batches. + uint32_t mNumMessagesRemainingInBatch; + + // These are the headers of the messages in the current + // batch/series of batches of messages manually marked + // as junk. + nsTArray<RefPtr<nsIMsgDBHdr>> mJunkHdrs; + + nsTArray<uint32_t> mIndicesToNoteChange; + + nsTHashtable<nsCStringHashKey> mEmails; + + // The saved search views keep track of the XX most recently deleted msg ids, + // so that if the delete is undone, we can add the msg back to the search + // results, even if it no longer matches the search criteria (e.g., a saved + // search over unread messages). We use mRecentlyDeletedArrayIndex to treat + // the array as a list of the XX most recently deleted msgs. + nsTArray<nsCString> mRecentlyDeletedMsgIds; + uint32_t mRecentlyDeletedArrayIndex; + void RememberDeletedMsgHdr(nsIMsgDBHdr* msgHdr); + bool WasHdrRecentlyDeleted(nsIMsgDBHdr* msgHdr); + + // These hold pointers (and IDs) for the nsIMsgCustomColumnHandler object + // that constitutes the custom column handler. + nsCOMArray<nsIMsgCustomColumnHandler> m_customColumnHandlers; + nsTArray<nsString> m_customColumnHandlerIDs; + + nsIMsgCustomColumnHandler* GetColumnHandler(const nsAString& colID); + nsIMsgCustomColumnHandler* GetCurColumnHandler(); + bool CustomColumnsInSortAndNotRegistered(); + void EnsureCustomColumnsValid(); + +#ifdef DEBUG_David_Bienvenu + void InitEntryInfoForIndex(nsMsgViewIndex i, IdKey& EntryInfo); + void ValidateSort(); +#endif + + protected: + static nsresult InitDisplayFormats(); + + private: + static bool m_dateFormatsInitialized; + static nsDateFormatSelectorComm m_dateFormatDefault; + static nsDateFormatSelectorComm m_dateFormatThisWeek; + static nsDateFormatSelectorComm m_dateFormatToday; + static nsString m_connectorPattern; + + bool ServerSupportsFilterAfterTheFact(); + + nsresult PerformActionsOnJunkMsgs(bool msgsAreJunk); + nsresult DetermineActionsForJunkChange(bool msgsAreJunk, + nsIMsgFolder* srcFolder, + bool& moveMessages, + bool& changeReadState, + nsIMsgFolder** targetFolder); + + class nsMsgViewHdrEnumerator final : public nsBaseMsgEnumerator { + public: + explicit nsMsgViewHdrEnumerator(nsMsgDBView* view); + + // nsIMsgEnumerator support. + NS_IMETHOD GetNext(nsIMsgDBHdr** aItem) override; + NS_IMETHOD HasMoreElements(bool* aResult) override; + + RefPtr<nsMsgDBView> m_view; + nsMsgViewIndex m_curHdrIndex; + + private: + virtual ~nsMsgViewHdrEnumerator() override; + }; +}; + +#endif |