diff options
Diffstat (limited to 'mailnews/base/util/folderUtils.jsm')
-rw-r--r-- | mailnews/base/util/folderUtils.jsm | 234 |
1 files changed, 234 insertions, 0 deletions
diff --git a/mailnews/base/util/folderUtils.jsm b/mailnews/base/util/folderUtils.jsm new file mode 100644 index 000000000..62fb7700b --- /dev/null +++ b/mailnews/base/util/folderUtils.jsm @@ -0,0 +1,234 @@ +/* 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/. */ + +/** + * This file contains helper methods for dealing with nsIMsgFolders. + */ + +this.EXPORTED_SYMBOLS = ["getFolderProperties", "getSpecialFolderString", + "getFolderFromUri", "allAccountsSorted", + "getMostRecentFolders", "folderNameCompare"]; + +Components.utils.import("resource:///modules/mailServices.js"); +Components.utils.import("resource:///modules/iteratorUtils.jsm"); + +/** + * Returns a string representation of a folder's "special" type. + * + * @param aFolder the nsIMsgFolder whose special type should be returned + */ +function getSpecialFolderString(aFolder) { + const nsMsgFolderFlags = Components.interfaces.nsMsgFolderFlags; + let flags = aFolder.flags; + if (flags & nsMsgFolderFlags.Inbox) + return "Inbox"; + if (flags & nsMsgFolderFlags.Trash) + return "Trash"; + if (flags & nsMsgFolderFlags.Queue) + return "Outbox"; + if (flags & nsMsgFolderFlags.SentMail) + return "Sent"; + if (flags & nsMsgFolderFlags.Drafts) + return "Drafts"; + if (flags & nsMsgFolderFlags.Templates) + return "Templates"; + if (flags & nsMsgFolderFlags.Junk) + return "Junk"; + if (flags & nsMsgFolderFlags.Archive) + return "Archive"; + if (flags & nsMsgFolderFlags.Virtual) + return "Virtual"; + return "none"; +} + +/** + * This function is meant to be used with trees. It returns the property list + * for all of the common properties that css styling is based off of. + * + * @param nsIMsgFolder aFolder the folder whose properties should be returned + * as a string + * @param bool aOpen true if the folder is open/expanded + * + * @return A string of the property names, delimited by space. + */ +function getFolderProperties(aFolder, aOpen) { + const nsIMsgFolder = Components.interfaces.nsIMsgFolder; + let properties = []; + + properties.push("folderNameCol"); + + properties.push("serverType-" + aFolder.server.type); + + // set the SpecialFolder attribute + properties.push("specialFolder-" + getSpecialFolderString(aFolder)); + + // Now set the biffState + switch (aFolder.biffState) { + case nsIMsgFolder.nsMsgBiffState_NewMail: + properties.push("biffState-NewMail"); + break; + case nsIMsgFolder.nsMsgBiffState_NoMail: + properties.push("biffState-NoMail"); + break; + default: + properties.push("biffState-UnknownMail"); + } + + properties.push("isSecure-" + aFolder.server.isSecure); + + // A folder has new messages, or a closed folder or any subfolder has new messages. + if (aFolder.hasNewMessages || + (!aOpen && aFolder.hasSubFolders && aFolder.hasFolderOrSubfolderNewMessages)) + properties.push("newMessages-true"); + + if (aFolder.isServer) { + properties.push("isServer-true"); + } + else + { + // We only set this if we're not a server + let shallowUnread = aFolder.getNumUnread(false); + if (shallowUnread > 0) { + properties.push("hasUnreadMessages-true"); + } + else + { + // Make sure that shallowUnread isn't negative + shallowUnread = 0; + } + let deepUnread = aFolder.getNumUnread(true); + if (deepUnread - shallowUnread > 0) + properties.push("subfoldersHaveUnreadMessages-true"); + } + + properties.push("noSelect-" + aFolder.noSelect); + properties.push("imapShared-" + aFolder.imapShared); + + return properties.join(" "); +} + +/** + * Returns a folder for a particular uri + * + * @param aUri the rdf uri of the folder to return + */ +function getFolderFromUri(aUri) { + const Cc = Components.classes; + const Ci = Components.interfaces; + return Cc["@mozilla.org/mail/folder-lookup;1"]. + getService(Ci.nsIFolderLookupService).getFolderById(aUri); +} + +/** + * Returns the sort order value based on the server type to be used for sorting. + * The servers (accounts) go in the following order: + * (0) default account, (1) other mail accounts, (2) Local Folders, + * (3) IM accounts, (4) RSS, (5) News, (9) others (no server) + * This ordering is encoded in the .sortOrder property of each server type. + * + * @param aServer the server object to be tested + */ +function getServerSortOrder(aServer) { + // If there is no server sort this object to the end. + if (!aServer) + return 999999999; + + // Otherwise get the server sort order from the Account manager. + return MailServices.accounts.getSortOrder(aServer); +} + +/** + * Compares the passed in accounts according to their precedence. + */ +function compareAccounts(aAccount1, aAccount2) { + return getServerSortOrder(aAccount1.incomingServer) + - getServerSortOrder(aAccount2.incomingServer); +} + +/** + * Returns a list of accounts sorted by server type. + * + * @param aExcludeIMAccounts Remove IM accounts from the list? + */ +function allAccountsSorted(aExcludeIMAccounts) { + // Get the account list, and add the proper items. + let accountList = toArray(fixIterator(MailServices.accounts.accounts, + Components.interfaces.nsIMsgAccount)); + + // This is a HACK to work around bug 41133. If we have one of the + // dummy "news" accounts there, that account won't have an + // incomingServer attached to it, and everything will blow up. + accountList = accountList.filter(function hasServer(a) { + return a.incomingServer; + }); + + // Remove IM servers. + if (aExcludeIMAccounts) { + accountList = accountList.filter(function(a) { + return a.incomingServer.type != "im"; + }); + } + + return accountList.sort(compareAccounts); +} + +/** + * Returns the most recently used/modified folders from the passed in list. + * + * @param aFolderList The array of nsIMsgFolders to search for recent folders. + * @param aMaxHits How many folders to return. + * @param aTimeProperty Which folder time property to use. + * Use "MRMTime" for most recently modified time. + * Use "MRUTime" for most recently used time. + */ +function getMostRecentFolders(aFolderList, aMaxHits, aTimeProperty) { + let recentFolders = []; + + /** + * This sub-function will add a folder to the recentFolders array if it + * is among the aMaxHits most recent. If we exceed aMaxHits folders, + * it will pop the oldest folder, ensuring that we end up with the + * right number. + * + * @param aFolder The folder to check for recency. + */ + let oldestTime = 0; + function addIfRecent(aFolder) { + let time = 0; + try { + time = Number(aFolder.getStringProperty(aTimeProperty)) || 0; + } catch(e) {} + if (time <= oldestTime) + return; + + if (recentFolders.length == aMaxHits) { + recentFolders.sort(function sort_folders_by_time(a, b) { + return a.time < b.time; }); + recentFolders.pop(); + oldestTime = recentFolders[recentFolders.length - 1].time; + } + recentFolders.push({ folder: aFolder, time: time }); + } + + for (let folder of aFolderList) { + addIfRecent(folder); + } + + return recentFolders.map(function (f) { return f.folder; }); +} + +/** + * A locale dependent comparison function to produce a case-insensitive sort order + * used to sort folder names. + * Returns positive number if aString1 > aString2, negative number if aString1 > aString2, + * otherwise 0. + * + * @param aString1 first string to compare + * @param aString2 second string to compare + */ +function folderNameCompare(aString1, aString2) { + // TODO: improve this as described in bug 992651. + return aString1.toLocaleLowerCase() + .localeCompare(aString2.toLocaleLowerCase()); +} |