pjs/penelope/base/content/messengerOverlay.js

1210 строки
40 KiB
JavaScript
Executable File

/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Mozilla Penelope project.
*
* The Initial Developer of the Original Code is
* QUALCOMM incorporated.
* Portions created by the Initial Developer are Copyright (C) 2006
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Mark Charlebois <mcharleb@qualcomm.com> original author
* Jeff Beckley <beckley@qualcomm.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
var PenelopeMessenger = {
onLoad: function()
{
// TODO If the window has already been created, close the new one and focus the old one
// quit if this function has already been called
if (arguments.callee.done) return;
// flag this function so we don't do the same thing twice
arguments.callee.done = true;
// update the mailbox and transfer menus
setTimeout(delayedOnLoadPenelopeMessenger, 50);
// perform column remapping once
setTimeout(delayedOnLoadPenelopeColumns, 60);
// We only need to set the sound once
setNewMailSound();
// Set up an observer for when the view has been created
// in order to register the Group Select column
var ObserverService = Components.classes["@mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService);
ObserverService.addObserver(CreateDbObserver, "MsgCreateDBView", false);
}
};
//load event handler
window.addEventListener("DOMContentLoaded", function(e) { PenelopeMessenger.onLoad(e); }, false);
function delayedOnLoadPenelopeMessenger()
{
// Add a listener for handling double-click and Enter key on a folder
var folderTree = document.getElementById("folderTree");
folderTree.addEventListener("click",FolderTreeOnClick,true);
folderTree.addEventListener("keypress",FolderTreeOnKeyPress,true);
// Add a listener for handling Alt+click
var threadTree = document.getElementById("threadTree");
threadTree.addEventListener("mousedown",ThreadTreeOnMouseDown,true);
threadTree.addEventListener("click",ThreadTreeOnMouseClick,true);
threadTree.addEventListener("keypress",ThreadTreeOnKeyPress,true);
}
function checkIfWindowOpen(folderURL, bDontCheckSelf)
{
var mediator = Components.classes["@mozilla.org/appshell/window-mediator;1"].getService(Components.interfaces.nsIWindowMediator);
// Grab window list; for all windows, pass null as the parameter.
var windows = mediator.getXULWindowEnumerator(null);
while (windows.hasMoreElements())
{
var win = windows.getNext();
var ifaces = Components.interfaces;
if(!(win instanceof ifaces.nsIXULWindow))
{
dump("Found invalid item\n");
continue;
}
var requestor = win.docShell.QueryInterface(Components.interfaces.nsIInterfaceRequestor);
var mywin = requestor.getInterface(Components.interfaces.nsIDOMWindow);
var topwin = mywin.document.getElementById("messengerWindow");
dump("topwin "+topwin+"\n");
if (topwin)
{
if (topwin.getAttribute("folderwin") == "true")
{
dump("topwin found\n");
continue;
}
if (bDontCheckSelf && mywin == window)
{
continue;
}
var url = GetSelectedFolderURIForWin(mywin);
dump("Folder URL for window = "+url+"\n");
if (url == folderURL)
{
return mywin;
}
}
}
return null;
}
function penelopeMessengerOnLoad()
{
dump("In penelopeMessengerOnLoad\n");
// Get the preferences for the window instance
var prefs = Components.classes["@mozilla.org/preferences-service;1"].
getService(Components.interfaces.nsIPrefBranch);
var uri = null;
if (window.arguments.length)
{
dump("arguements.length "+window.arguments.length+"\n");
// filter our any feed urls that came in as arguments to the new window...
if (/^feed:/i.test(window.arguments[0]))
{
// Leave uri=null
}
else
{
uri = window.arguments[0];
dump("Folder URI = "+uri+"\n");
}
}
// If the user wants the 2-Pane UI colapse the folder
var use3PaneUI = prefs.getBoolPref("penelope.ui3pane");
// This call does nothing if in 2-pane mode and the current win is the folder win
initializeFolderWin(uri, use3PaneUI, prefs);
OnLoadMessenger();
// if we are in 2-pane mode, the first window is the folder window
if (!uri && !use3PaneUI)
{
// This is the 2-pane folder summary window
initializeSummaryFolderWin(prefs);
}
}
function initializeSummaryFolderWin(prefs)
{
var topwin = document.getElementById("messengerWindow");
topwin.setAttribute("folderwin", "true");
dump("set topwin "+topwin+"\n");
// reconfigure for 2-pane mode folder window
var toolbar = document.getElementById('mail-bar2');
toolbar.collapsed = true;
// Add flex to the folder pane
document.getElementById('folderPaneBox').setAttribute('flex', '1');
// Remove flex from vbox with no ID
document.getElementById('folderpane_splitter').nextSibling.removeAttribute('flex');
document.getElementById('folderpane_splitter').nextSibling.collapsed = true;
document.getElementById('threadPaneBox').removeAttribute('flex');
document.getElementById('threadTree').removeAttribute('flex');
document.getElementById('threadTree').setAttribute("flags", "dont-build-content");
document.getElementById('threadTree').disabled=true;
//var splitter = document.getElementById('threadpane-splitter');
//splitter.collapsed = false;
document.documentElement.setAttribute("width", 300);
document.documentElement.setAttribute("height", 700);
var menuitem = document.getElementById('menu_customizeToolbar');
menuitem.hidden = true;
menuitem = document.getElementById('menu_saveAs');
menuitem.disabled = true;
menuitem = document.getElementById('printSetupMenuItem');
menuitem.disabled = true;
menuitem = document.getElementById('printMenuItem');
menuitem.disabled = true;
menuitem = document.getElementById('menu_delete');
menuitem.disabled = true;
menuitem = document.getElementById('penelopeTransferMenu');
menuitem.hidden = true;
menuitem = document.getElementById('messageMenu');
menuitem.hidden = true;
// View menu
menuitem = document.getElementById('menu_Toolbars');
menuitem.hidden = true;
menuitem = document.getElementById('menu_MessagePaneLayout');
menuitem.hidden = true;
menuitem = document.getElementById('viewSortMenuSeparator');
menuitem.hidden = true;
menuitem = document.getElementById('viewMessagesMenu');
menuitem.hidden = true;
menuitem = document.getElementById('viewheadersmenu');
menuitem.hidden = true;
// hide the separator with no ID
menuitem.previousSibling.hidden = true;
menuitem = document.getElementById('viewMessageViewMenu');
menuitem.hidden = true;
menuitem = document.getElementById('viewAttachmentsInlineMenuitem');
menuitem.hidden = true;
menuitem = document.getElementById('viewTextSizeMenu');
// hide the separator with no ID
menuitem.previousSibling.hidden = true;
menuitem.hidden = true;
menuitem = document.getElementById('viewBodyMenu');
menuitem.hidden = true;
menuitem = document.getElementById('mailviewCharsetMenu');
menuitem.hidden = true;
menuitem = document.getElementById('pageSourceMenuItem');
menuitem.hidden = true;
// hide the separator with no ID
menuitem.previousSibling.hidden = true;
menuitem = document.getElementById('viewSortMenu');
menuitem.hidden = true;
menuitem = document.getElementById('viewSortMenuSeparator');
menuitem.hidden = true;
// Get the Go menu
menuitem = document.getElementById('goNextMenu').parentNode.parentNode;
menuitem.hidden = true;
try
{
// printPreviewMenuItem is only defined on non-Mac
menuitem = document.getElementById('printPreviewMenuItem');
menuitem.disabled = true;
}
catch(e)
{
}
try
{
dump("Folder Window Dimentions:\n");
var width = prefs.getIntPref("penelope.__folderwindow.width");
var height = prefs.getIntPref("penelope.__folderwindow.height");
var screenX = prefs.getIntPref("penelope.__folderwindow.screenX");
var screenY = prefs.getIntPref("penelope.__folderwindow.screenY");
dump("Moving to: "+screenX+", "+screenY+"\n");
window.moveTo(screenX, screenY);
dump("Resize to: "+width+", "+height+"\n");
document.documentElement.setAttribute("width", width);
document.documentElement.setAttribute("height", height);
}
catch(e)
{
dump("Error setting folder pane attributes: "+e+"\n");
}
}
// Init 2-pane or 3-pane window depending on the UI mode
function initializeFolderWin(uri, use3PaneUI, prefs)
{
if (!uri)
{
if (use3PaneUI)
{
// This is the folder pane
// Get the last set of opened windows
dump("Opened 1st 3-pane window\n");
try
{
var defaultAccount = accountManager.defaultAccount;
defaultServer = defaultAccount.incomingServer;
var inboxFolder = GetInboxFolder(defaultServer);
uri = inboxFolder.URI;
}
catch(e)
{
dump("Could not determine default folder\n");
}
}
// 2-pane handling is below call to OnLoadMessenger()
}
if (uri)
{
if (checkIfWindowOpen(uri, false))
{
dump("Window "+uri+" is already open\n");
}
else
{
dump("Window "+uri+" is not open\n");
}
try
{
dump("FolderURI: "+uri+"\n");
var width = prefs.getIntPref("penelope."+uri+".window.width");
var height = prefs.getIntPref("penelope."+uri+".window.height");
var screenX = prefs.getIntPref("penelope."+uri+".window.screenX");
var screenY = prefs.getIntPref("penelope."+uri+".window.screenY");
dump("Moving to: "+screenX+", "+screenY+"\n");
window.moveTo(screenX, screenY);
dump("Resize to: "+width+", "+height+"\n");
document.documentElement.setAttribute("width", width);
document.documentElement.setAttribute("height", height);
var folderPane = document.getElementById("folderPaneBox");
if (use3PaneUI)
{
dump("Using 3-pane UI\n");
var fpcollapsed = prefs.getBoolPref("penelope."+uri+".window.fpcollapsed");
var fpwidth = prefs.getIntPref("penelope."+uri+".window.fpwidth");
var folderPaneSplitter = document.getElementById("folderpane_splitter");
var fpsplitter = prefs.getCharPref("penelope."+uri+".window.fpsplitter");
dump("Setting fpwidth = "+fpwidth+"\n");
dump("Setting fpcollapsed = "+fpcollapsed+"\n");
dump("Setting fpsplitter = "+fpsplitter+"\n");
if (fpwidth)
{
folderPane.width = fpwidth;
}
if (fpcollapsed)
{
folderPane.collapsed = true;
}
else
{
folderPane.collapsed = false;
}
if (fpsplitter != "")
{
folderPaneSplitter.setAttribute("state", fpsplitter);
}
}
else
{
dump("Using 2-pane UI\n");
folderPane.collapsed = true;
var folderPaneSplitter = document.getElementById("folderpane_splitter");
folderPaneSplitter.setAttribute("state", "collapsed");
}
}
catch(e)
{
dump("Error setting folder pane attributes: "+e+"\n");
}
try
{
var messagePane = document.getElementById("messagepanebox");
var mpwidth = prefs.getIntPref("penelope."+uri+".window.mpwidth");
var mpheight = prefs.getIntPref("penelope."+uri+".window.mpheight");
var threadPaneSplitter = document.getElementById("threadpane-splitter");
var tpsplitter = prefs.getCharPref("penelope."+uri+".window.tpsplitter");
dump("Setting tpsplitter = "+tpsplitter+"\n");
dump("Setting mpwidth = "+mpwidth+"\n");
dump("Setting mpheight = "+mpheight+"\n");
if (mpwidth)
{
messagePane.width = mpwidth;
}
if (mpheight)
{
messagePane.height = mpheight;
}
if (tpsplitter != "")
{
threadPaneSplitter.setAttribute("state", tpsplitter);
}
}
catch(e)
{
dump("Error setting thread pane attributes: "+e+"\n");
}
}
}
function GetSelectedFolderURIForWin(win)
{
try
{
dump("WINDOW: "+document.title+"");
var folderTree = win.document.getElementById("folderTree");
var folderResource = folderTree.builderView.getResourceAtIndex(folderTree.currentIndex);
var url = folderResource.Value;
//var msgFolder = folderResource.QueryInterface(Components.interfaces.nsIMsgFolder);
//var url = msgFolder.folderURL;
dump("WIN URL = "+url+"\n");
return url;
}
catch(e)
{
dump("Caught exception in GetSelectedFolderURIForWin\n");
}
}
function penelopeMessengerOnUnload()
{
dump("In penelopeMessengerOnUnload\n");
var uri = null;
var folderwin = document.getElementById("messengerWindow");
// See if this window is the main folder window
if (folderwin)
{
if (folderwin.getAttribute("folderwin") != "true")
{
// This is not the 2-pane folder window
uri = GetSelectedFolderURI();
}
}
var prefs = Components.classes["@mozilla.org/preferences-service;1"].
getService(Components.interfaces.nsIPrefBranch);
// If this is not the main folder pane
if (uri)
{
// If the user wants the 2-Pane UI ignore folder settings
var use3PaneUI = prefs.getBoolPref("penelope.ui3pane");
// Set the preferences for the window instance
dump("Saving dimentions as: "+window.innerWidth+", "+window.innerHeight+"\n");
dump("Saving position as: "+window.screenX+", "+window.screenY+"\n");
prefs.setIntPref("penelope."+uri+".window.width", window.innerWidth);
prefs.setIntPref("penelope."+uri+".window.height", window.innerHeight);
prefs.setIntPref("penelope."+uri+".window.screenX", window.screenX);
prefs.setIntPref("penelope."+uri+".window.screenY", window.screenY);
// Only store foldre pane settings if in 3 pane mode
if (use3PaneUI)
{
try
{
var folderPane = document.getElementById("folderPaneBox");
var fpcollapsed = folderPane.collapsed;
var fpwidth = folderPane.width;
var folderPaneSplitter = document.getElementById("folderpane_splitter");
var fpsplitter = folderPaneSplitter.getAttribute("state");
if (fpcollapsed == null)
{
fpcollapsed = false;
}
dump("Saving fpcollapsed = "+fpcollapsed+"\n");
prefs.setBoolPref("penelope."+uri+".window.fpcollapsed", fpcollapsed);
dump("Saving fpwidth = "+fpwidth+"\n");
prefs.setIntPref("penelope."+uri+".window.fpwidth", fpwidth);
dump("Saving fpsplitter = "+fpsplitter+"\n");
prefs.setCharPref("penelope."+uri+".window.fpsplitter", fpsplitter);
}
catch(e)
{
dump("Caught folder pane exception: "+e+"\n");
}
}
try
{
var messagePane = document.getElementById("messagepanebox");
var mpwidth = messagePane.width;
var mpheight = messagePane.height;
var threadPaneSplitter = document.getElementById("threadpane-splitter");
var tpsplitter = threadPaneSplitter.getAttribute("state");
dump("Saving tpsplitter = "+tpsplitter+"\n");
prefs.setCharPref("penelope."+uri+".window.tpsplitter", tpsplitter);
dump("Saving mpwidth = "+mpwidth+"\n");
prefs.setIntPref("penelope."+uri+".window.mpwidth", mpwidth);
dump("Saving mpheight = "+mpheight+"\n");
prefs.setIntPref("penelope."+uri+".window.mpheight", mpheight);
}
catch(e)
{
dump("Caught thread pane exception: "+e+"\n");
}
}
else
{
try
{
// Set the preferences for the folder window
dump("Saving dimentions as: "+window.innerWidth+", "+window.innerHeight+"\n");
dump("Saving position as: "+window.screenX+", "+window.screenY+"\n");
prefs.setIntPref("penelope.__folderwindow.width", window.innerWidth);
prefs.setIntPref("penelope.__folderwindow.height", window.innerHeight);
prefs.setIntPref("penelope.__folderwindow.screenX", window.screenX);
prefs.setIntPref("penelope.__folderwindow.screenY", window.screenY);
}
catch(e)
{
dump("Exception: In folder win - "+ e+"\n");
}
}
OnUnloadMessenger();
}
function FolderTreeOnClick(event)
{
// we only care about button 0 (left click) events, and double-click
//
// We have to catch this during the single click event because otherwise
// the mailnews code will get the single click event before we get the
// double-click event, and we need to prevent further handling of the event.
if (event.button != 0 || event.detail != 2)
return;
var folderTree = GetFolderTree();
var row = {};
var col = {};
var elt = {};
folderTree.treeBoxObject.getCellAt(event.clientX, event.clientY, row, col, elt);
if (row.value >= 0 && elt.value != "twisty")
FolderTreeDoubleClick(row.value, event);
}
function FolderTreeDoubleClick(folderIndex, event)
{
var folderResource = GetFolderResource(GetFolderTree(), folderIndex);
// Open a new msg window only if we are double clicking on
// folders or newsgroups, not top-level servers
if (folderResource && folderResource.isServer == false)
{
goMailbox(folderResource.Value, true);
event.stopPropagation();
}
}
function FolderTreeOnKeyPress(event)
{
if (event.keyCode == event.DOM_VK_ENTER || event.keyCode == event.DOM_VK_RETURN)
{
var folderTree = GetFolderTree();
FolderTreeDoubleClick(folderTree.currentIndex, event);
}
}
var eatNextMouseClick = false;
function ThreadTreeOnMouseDown(event)
{
// See if user Alt+clicked on a message summary
if (event.button == 0 && event.altKey)
{
var threadTree = document.getElementById("threadTree");
var treeBoxObj = threadTree.treeBoxObject;
var row = {}, col= {}, type = {};
treeBoxObj.getCellAt(event.clientX, event.clientY, row, col, type);
if (row.value >= 0)
{
MailboxGroupSelect(threadTree, row.value, col.value, !event.shiftKey);
// Don't let the mouse down continue as it will cause the
// clicked item in some columns (e.g. Starred and Junk) to
// change state
event.stopPropagation();
// Also, we need to eat the resulting mouse click as otherwise
// it will cause the clicked item to only be selected after
// we've done all of the special selection work
eatNextMouseClick = true;
}
}
}
function ThreadTreeOnMouseClick(event)
{
if (event.button == 0 && eatNextMouseClick)
{
eatNextMouseClick = false;
event.stopPropagation();
}
}
var lastKeyPress = 0;
var ttsBuffer;
function ThreadTreeOnKeyPress(event)
{
if (!event.ctrlKey && !event.altKey)
{
var charCode = event.charCode;
if (charCode >= 32)
{
event.stopPropagation();
var now = Date.now();
var findAgain = false;
// Start search criteria from the beginning if it's
// been more than a second since a key was pressed
if (now > lastKeyPress + 1000)
{
// Period key after timeout is the "find again" hotkey
//
// Yeah, yeah, yeah, Shift+<period> is not necessarily the greater-than character (62)
// on all keyboards, but key presses don't give you the key code and I don't feel like
// writing an additional key down event handler for such a minor thing. ;^>
if (charCode == 46 || (event.shiftKey && charCode == 62 && ttsBuffer))
findAgain = true;
else
ttsBuffer = "";
}
if (!findAgain)
{
lastKeyPress = now;
// Encode the characters so as to not to be interpreted as RegEx specials (e.g. '*')
ttsBuffer += "\\x" + charCode.toString(16);
}
var tree = document.getElementById("threadTree");
var view = tree.view;
var treeBoxObj = tree.treeBoxObject;
var selection = view.selection;
var numItems = view.rowCount;
var subjectCol = treeBoxObj.columns.getNamedColumn("subjectCol");
// If the mailbox is ascending sorted then search from top to bottom.
// If descending or not sorted, then go bottom to top.
// Reverse it for Date sorting as we want to search more recent messages first.
var bSubjectSorted = (gDBView.sortType == nsMsgViewSortType.bySubject);
var bWhoSorted = (gDBView.sortType == nsMsgViewSortType.byAuthor || gDBView.sortType == nsMsgViewSortType.byRecipient);
var bAscendingSort = (gDBView.sortOrder == nsMsgViewSortOrder.ascending);
var bDateSorted = (gDBView.sortType == nsMsgViewSortType.byDate);
var row, inc;
if (bAscendingSort && !bDateSorted)
{
row = 0;
inc = 1;
}
else
{
row = numItems - 1;
inc = -1;
}
// If doing a find again (user hit period key) then start at the item after the currently selected one
if (findAgain)
{
// Shift key held down means go the opposite direction
if (event.shiftKey)
inc = -inc;
row = selection.currentIndex + inc;
}
// Match the beginning of the text or white space, followed by zero or more punctuation characters, followed by the match string
var matchExpression = new RegExp("(?:^|\\s)[\\x21-\\x2F\\x3A-\\x40\\x5B-\\x60\\x7B-\\x7E]*" + ttsBuffer, "i");
var matchRow = -1;
var senderColElement = document.getElementById("senderCol");
var recipientColElement = document.getElementById("recipientCol");
var whoCol;
if (recipientColElement.hidden == false)
whoCol = treeBoxObj.columns.getNamedColumn("recipientCol");
else if (senderColElement.hidden == false)
whoCol = treeBoxObj.columns.getNamedColumn("senderCol");
for (; row >= 0 && row < numItems; row += inc)
{
// Don't bother searching Subject if its a secondary column
// and we've already found a secondary match, or if
// it isn't currently being shown
if ((!bWhoSorted || matchRow < 0) && subjectCol)
{
var subject = GetItemValue(view, row, subjectCol, nsMsgViewSortType.bySubject);
if (matchExpression.exec(subject))
{
if (!bWhoSorted)
{
matchRow = row;
break;
}
if (matchRow < 0)
matchRow = row;
}
}
// Don't bother searching Who if its a secondary column
// and we've already found a secondary match, or if
// it isn't currently being shown
if ((bWhoSorted || matchRow < 0) && whoCol)
{
var who = GetItemValue(view, row, whoCol, nsMsgViewSortType.byNone);
if (matchExpression.exec(who))
{
if (bWhoSorted)
{
matchRow = row;
break;
}
if (matchRow < 0)
matchRow = row;
}
}
}
if (matchRow >= 0)
{
selection.select(matchRow);
treeBoxObj.ensureRowIsVisible(matchRow);
}
else
{
var sound = Components.classes["@mozilla.org/sound;1"].createInstance(Components.interfaces.nsISound);
sound.playSystemSound("beep");
}
}
}
}
var groupSelectIndexArray;
var groupSelectColumnHandler =
{
getCellText: function(row, col) {},
getSortStringForRow: function(hdr) {},
isString: function() { return false; },
getCellProperties: function(row, col, props) {},
getImageSrc: function(row, col) { return null; },
getRowProperties: function(row, properties) {},
getSortLongForRow: function(hdr) { return groupSelectIndexArray[hdr.messageKey]; }
}
var CreateDbObserver =
{
observe: function(aMsgFolder, aTopic, aData)
{
gDBView.addColumnHandler("groupSelectCol", groupSelectColumnHandler);
}
}
function GetCoreSubject(text)
{
// Can't do this with a single reg ex as the "[Fwd: subject]" format
// needs to strip off the trailing square bracket character
var fwdRegEx = /\[fwd?:\s*(.*)\]/i;
var initialBracketsRegEx = /^\[.*\]\s*(\S+.*)/i;
var prefixRegEx = /^\s*(?:(?:re|fwd?)[^a-z]*:\s*)+(.*)/i;
while (true)
{
while (match = fwdRegEx.exec(text))
text = match[1];
while (match = initialBracketsRegEx.exec(text))
text = match[1];
if (match = prefixRegEx.exec(text))
text = match[1];
else
break;
}
return text;
}
function GetItemValue(view, row, col, sortType)
{
switch (sortType)
{
case nsMsgViewSortType.bySubject:
return GetCoreSubject(view.getCellText(row, col));
case nsMsgViewSortType.byThread:
return view.isContainer(row);
case nsMsgViewSortType.byPriority:
var msgKey = gDBView.getKeyAt(row);
var hdr = gDBView.db. GetMsgHdrForKey(msgKey);
return hdr.priority;
case nsMsgViewSortType.byFlagged:
var msgKey = gDBView.getKeyAt(row);
var hdr = gDBView.db. GetMsgHdrForKey(msgKey);
return hdr.isFlagged;
case nsMsgViewSortType.byJunkStatus:
var msgKey = gDBView.getKeyAt(row);
var hdr = gDBView.db. GetMsgHdrForKey(msgKey);
var junkScoreStr = hdr.getStringProperty("junkscore");
var junkThreshold = pref.getIntPref("mail.adaptivefilters.junk_threshold");
return parseInt(junkScoreStr, 10) >= junkThreshold;
case nsMsgViewSortType.byAttachments:
var msgKey = gDBView.getKeyAt(row);
var hdr = gDBView.db. GetMsgHdrForKey(msgKey);
return (hdr.flags & 0x10000000); // 0x10000000 is MSG_FLAG_ATTACHMENT
default:
return view.getCellText(row, col);
}
}
function MailboxGroupSelect(tree, row, col, moveItems)
{
var view = tree.view;
var treeBoxObj = tree.treeBoxObject;
var selection = view.selection;
var sortType = ConvertColumnIDToSortType(col.id);
var compareValue = GetItemValue(view, row, col, sortType);
var numItems = view.rowCount;
selection.selectEventsSuppressed = true;
selection.clearSelection();
var MatchBeforeNum = 0;
var MatchAfterNum = 0;
for (var r = 0; r < numItems; r++)
{
if (GetItemValue(view, r, col, sortType) == compareValue)
{
// Need to use rangedSelect() as it doesn't affect existing selection
selection.rangedSelect(r, r, true);
if (r < row)
{
MatchBeforeNum++;
}
else if (r > row)
{
MatchAfterNum++;
}
}
}
if (moveItems && (MatchBeforeNum || MatchAfterNum))
{
var NonMatchBeforeIndex = 0;
var MatchBeforeIndex = row - MatchBeforeNum;
var NonMatchAfterIndex = row + MatchAfterNum + 1;
var MatchAfterIndex = row + 1;
groupSelectIndexArray = new Array();
for (var r = 0; r < numItems; r++)
{
var newIndex = 0;
if (GetItemValue(view, r, col, sortType) == compareValue)
{
if (r < row)
{
newIndex = MatchBeforeIndex++;
}
else if (r > row)
{
newIndex = MatchAfterIndex++;
}
else
{
newIndex = row;
}
}
else
{
if (r < row)
{
newIndex = NonMatchBeforeIndex++;
}
else
{
newIndex = NonMatchAfterIndex++;
}
}
var msgKey = gDBView.getKeyAt(r);
groupSelectIndexArray[msgKey] = newIndex;
}
var sortType = ConvertColumnIDToSortType("groupSelectCol");
// Force sort to occur by thinking that the view is currently not sorted
gDBView.sortType = nsMsgViewSortType.byNone;
MsgSortThreadPane(sortType);
// Consider not sorted when done
gDBView.sortType = nsMsgViewSortType.byNone;
groupSelectIndexArray = null;
}
selection.currentIndex = row;
selection.selectEventsSuppressed = false;
}
function setNewMailSound()
{
// Get the install location of the extension
const id= "{D1D37B8A-4F3C-11DB-8373-B622A1EF5492}";
var extDir = Components.classes["@mozilla.org/extensions/manager;1"]
.getService(Components.interfaces.nsIExtensionManager)
.getInstallLocation(id)
.getItemLocation(id);
// Get the preferences object
var prefs = Components.classes["@mozilla.org/preferences-service;1"].
getService(Components.interfaces.nsIPrefBranch);
// Set the preferences for the sound to play for new mail
var newmail = "file://"+extDir.path+"/newmail.wav";
prefs.setIntPref("mail.biff.play_sound.type", 1);
prefs.setCharPref("mail.biff.play_sound.url", newmail);
}
function goMailbox(folderUri, bUserAction)
{
dump("selecting folder " + folderUri + "\n");
// If this is a user action (e.g. double-click or Enter/Return), then don't consider the current
// window a match because it will always match (because it is selected on the right)
var win = checkIfWindowOpen(folderUri, bUserAction);
if (win)
{
// focus the existing window
dump("Window "+folderUri+" is open... changing focus\n");
win.focus();
return;
}
else
{
dump("Window "+folderUri+" is not open... creating\n");
}
// TODO - Decide whether to open a new window or just change the selection of the current window
if (0)
{
var folderTree = GetFolderTree();
var folderResource = RDF.GetResource(folderUri);
var msgFolder = folderResource.QueryInterface(Components.interfaces.nsIMsgFolder);
// before we can select a folder, we need to make sure it is "visible"
// in the tree. to do that, we need to ensure that all its
// ancestors are expanded
var folderIndex = EnsureFolderIndex(folderTree.builderView, msgFolder);
ChangeSelection(folderTree, folderIndex);
}
else
{
toOpenWindowByType("mail:3pane", "chrome://messenger/content/messenger.xul");
MsgOpenNewWindowForFolder(folderUri, -1);
}
}
function OpenSpecialMailbox(flag)
{
try
{
if (iterateSubfolders(gDBView.msgFolder.server.rootMsgFolder, flag))
{
return true;
}
}
catch(e)
{
}
return iterateSubfolders(accountManager.localFoldersServer.rootMsgFolder, flag);
}
function openInbox()
{
OpenSpecialMailbox(MSG_FOLDER_FLAG_INBOX);
}
function openOutbox()
{
OpenSpecialMailbox(MSG_FOLDER_FLAG_SENTMAIL);
}
function openJunk()
{
OpenSpecialMailbox(MSG_FOLDER_FLAG_JUNK);
}
function openTrash()
{
OpenSpecialMailbox(MSG_FOLDER_FLAG_TRASH);
}
function iterateSubfolders(folder, flag)
{
var isMatch = folder.flags & flag;
if (isMatch > 0)
{
var folderTree = GetFolderTree();
var idx = folderTree.builderView.getIndexOfResource(folder);
ChangeSelection(folderTree, idx);
return true;
}
if (folder.hasSubFolders)
{
var subfolders = folder.GetSubFolders();
var done = false;
while (!done)
{
var subfolder = subfolders.currentItem().QueryInterface(Components.interfaces.nsIMsgFolder);
if (iterateSubfolders(subfolder, flag))
{
return true;
}
try
{
subfolders.next();
}
catch(e)
{
done = true;
}
}
}
return false;
}
function addEmail()
{
try
{
if (gDBView.URIForFirstSelectedMessage)
{
var hdr = messenger.msgHdrFromURI(gDBView.URIForFirstSelectedMessage);
var hdrParser = Components.classes["@mozilla.org/messenger/headerparser;1"].getService(Components.interfaces.nsIMsgHeaderParser);
var addresses = {};
var names = {};
var fullNames = {};
var numAddresses = hdrParser.parseHeadersWithArray(hdr.author, addresses, names, fullNames);
if (numAddresses <= 0)
{
alert("Add email to Addressbook failed");
}
var emailAddress = addresses.value[0];
var displayName = names.value[0];
window.openDialog("chrome://messenger/content/addressbook/abNewCardDialog.xul",
"",
"chrome,resizable=no,titlebar,modal,centerscreen",
{primaryEmail: emailAddress, displayName:displayName});
}
}
catch(e) { alert("No message selected"); }
}
function delayedOnLoadPenelopeColumns()
{
// Get the element nodes for the messanger window columns
var threadTree = document.getElementById("threadTree");
var sizeCol = document.getElementById("sizeCol");
var priorityCol = document.getElementById("priorityCol");
var senderCol = document.getElementById("senderCol");
var recipientCol = document.getElementById("recipientCol");
var subjectCol = document.getElementById("subjectCol");
var attachmentCol = document.getElementById("attachmentCol");
var statusCol = document.getElementById("statusCol");
var dateCol = document.getElementById("dateCol");
var threadCol = document.getElementById("threadCol");
var tagsCol = document.getElementById("tagsCol");
var junkCol = document.getElementById("junkStatusCol");
var unreadCol = document.getElementById("unreadButtonColHeader");
var idCol = document.getElementById("idCol");
var flaggedCol = document.getElementById("flaggedCol");
try
{
// Remap the messanger window columns to the Penelope defaults
// and change the visibility status of some of the columns
statusCol.setAttribute("hidden","false");
sizeCol.setAttribute("hidden","false");
priorityCol.setAttribute("hidden","false");
threadCol.setAttribute("hidden","true");
tagsCol.setAttribute("hidden","false");
flaggedCol.setAttribute("hidden","true");
unreadCol.setAttribute("hidden","true");
// Get the localized "Who" string
//var strbundle=document.getElementById("penelopeStrings");
//var who=strbundle.getString("who");
// Update the sender and recipient columns to display "Who"
//senderCol.setAttribute("label", who);
//recipientCol.setAttribute("label", who);
// FIXME Somehow the junk column gets remapped after this
threadTree._reorderColumn(subjectCol, idCol, true);
threadTree._reorderColumn(junkCol, subjectCol, true);
threadTree._reorderColumn(sizeCol, junkCol, true);
threadTree._reorderColumn(dateCol, sizeCol, true);
threadTree._reorderColumn(recipientCol, dateCol, true);
threadTree._reorderColumn(senderCol, recipientCol, true);
threadTree._reorderColumn(tagsCol, senderCol, true);
threadTree._reorderColumn(attachmentCol, tagsCol, true);
threadTree._reorderColumn(priorityCol, attachmentCol, true);
threadTree._reorderColumn(unreadCol, priorityCol, true);
threadTree._reorderColumn(statusCol, unreadCol, true);
}
catch(e)
{
dump("Column reorder error:"+e+"\n");
}
}
function penelopeUpdatePriorityMenu()
{
try
{
if (gDBView.nsIMsgDBHdr)
{
var priorityMenu = document.getElementById('penelopePriorityMenu' );
priorityMenu.getElementsByAttribute( "checked", 'true' )[0].removeAttribute('checked');
priorityMenu.getElementsByAttribute( "value", gDBView.nsIMsgDBHdr.priority )[0].setAttribute('checked', 'true');
}
}
catch(e)
{
dump("Error in penelopeUpdatePriorityMenu:"+e+"\n");
}
}
function penelopePriorityMenuSelect(target)
{
gDBView.nsIMsgDBHdr.setPriorityString(target.getAttribute('value'));
}
function penelopeStatusMenuSelect(target)
{
switch (target.getAttribute('value'))
{
case "Unread":
case "Read":
case "Replied":
case "Forwarded":
case "Redirected":
case "Sent":
case "Unsent":
alert("Not implemented");
break;
default:
alert("Unknown status");
}
}
function penelopeRedirect()
{
alert("Not implemented");
}
function penelopeFolderPaneSelectionChange()
{
FolderPaneSelectionChange();
var topwin = document.getElementById("messengerWindow");
if (topwin.getAttribute("folderwin") == "true")
{
document.title = "Penelope";
}
}