!import
1 //@line 44 "/home/visbrero/mnt/roisin/rev_control/hg/mozilla/mail/base/content/msgMail3PaneWindow.js"
2
3 /* This is where functions related to the 3 pane window are kept */
4
5 // from MailNewsTypes.h
6 const nsMsgKey_None = 0xFFFFFFFF;
7 const nsMsgViewIndex_None = 0xFFFFFFFF;
8 const kMailCheckOncePrefName = "mail.startup.enabledMailCheckOnce";
9
10 const kStandardPaneConfig = 0;
11 const kWidePaneConfig = 1;
12 const kVerticalPaneConfig = 2;
13
14 const kNumFolderViews = 4; // total number of folder views
15
16 // from nsMsgFolderFlags.h
17 const MSG_FOLDER_FLAG_ELIDED = 0x10;
18
19 var gFolderTree;
20 var gMessagePane;
21 var gThreadTree;
22 var gSearchInput;
23
24 var gThreadAndMessagePaneSplitter = null;
25 var gUnreadCount = null;
26 var gTotalCount = null;
27 var gCurrentFolderView;
28 var gCurrentLoadingFolderURI;
29 var gCurrentFolderToReroot;
30 var gCurrentLoadingFolderSortType = 0;
31 var gCurrentLoadingFolderSortOrder = 0;
32 var gCurrentLoadingFolderViewType = 0;
33 var gCurrentLoadingFolderViewFlags = 0;
34 var gRerootOnFolderLoad = false;
35 var gNextMessageAfterDelete = null;
36 var gNextMessageAfterLoad = null;
37 var gNextMessageViewIndexAfterDelete = -2;
38 var gSelectedIndexWhenDeleting = -1;
39 var gCurrentlyDisplayedMessage=nsMsgViewIndex_None;
40 var gStartFolderUri = null;
41 var gStartMsgKey = nsMsgKey_None;
42 var gSearchEmailAddress = null;
43 var gRightMouseButtonDown = false;
44 // Global var to keep track of which row in the thread pane has been selected
45 // This is used to make sure that the row with the currentIndex has the selection
46 // after a Delete or Move of a message that has a row index less than currentIndex.
47 var gThreadPaneCurrentSelectedIndex = -1;
48 var gLoadStartFolder = true;
49 var gNewAccountToLoad = null;
50
51 // Global var to keep track of if the 'Delete Message' or 'Move To' thread pane
52 // context menu item was triggered. This helps prevent the tree view from
53 // not updating on one of those menu item commands.
54 var gThreadPaneDeleteOrMoveOccurred = false;
55
56 //If we've loaded a message, set to true. Helps us keep the start page around.
57 var gHaveLoadedMessage;
58
59 var gDisplayStartupPage = false;
60
61 var gNotifyDefaultInboxLoadedOnStartup = false;
62
SelectAndScrollToKey
63 function SelectAndScrollToKey(aMsgKey)
64 {
65 // select the desired message
66 // if the key isn't found, we won't select anything
67 gDBView.selectMsgByKey(aMsgKey);
68
69 // is there a selection?
70 // if not, bail out.
71 var indicies = GetSelectedIndices(gDBView);
72 if (!indicies || !indicies.length)
73 return false;
74
75 // now scroll to it
76 EnsureRowInThreadTreeIsVisible(indicies[0]);
77 return true;
78 }
79
80 // A helper routine called after a folder is loaded to make sure
81 // we select and scroll to the correct message (could be the first new message,
82 // could be the last displayed message, etc.)
ScrollToMessageAfterFolderLoad
83 function ScrollToMessageAfterFolderLoad(folder)
84 {
85 var scrolled = gPrefBranch.getBoolPref("mailnews.scroll_to_new_message") &&
86 ScrollToMessage(nsMsgNavigationType.firstNew, true, false /* selectMessage */);
87 if (!scrolled && folder && gPrefBranch.getBoolPref("mailnews.remember_selected_message"))
88 {
89 // If we failed to scroll to a new message,
90 // reselect the last selected message
91 var lastMessageLoaded = folder.lastMessageLoaded;
92 if (lastMessageLoaded != nsMsgKey_None)
93 scrolled = SelectAndScrollToKey(lastMessageLoaded);
94 }
95
96 if (!scrolled)
97 {
98 // if we still haven't scrolled,
99 // scroll to the newest, which might be the top or the bottom
100 // depending on our sort order and sort type
101 if (gDBView.sortOrder == nsMsgViewSortOrder.ascending)
102 {
103 switch (gDBView.sortType)
104 {
105 case nsMsgViewSortType.byDate:
106 case nsMsgViewSortType.byReceived:
107 case nsMsgViewSortType.byId:
108 case nsMsgViewSortType.byThread:
109 scrolled = ScrollToMessage(nsMsgNavigationType.lastMessage, true, false /* selectMessage */);
110 break;
111 }
112 }
113
114 // if still we haven't scrolled,
115 // scroll to the top.
116 if (!scrolled)
117 EnsureRowInThreadTreeIsVisible(0);
118 }
119 }
120
121 // the folderListener object
122 var folderListener = {
OnItemAdded
123 OnItemAdded: function(parentItem, item) { },
124
OnItemRemoved
125 OnItemRemoved: function(parentItem, item) { },
126
OnItemPropertyChanged
127 OnItemPropertyChanged: function(item, property, oldValue, newValue) { },
128
OnItemIntPropertyChanged
129 OnItemIntPropertyChanged: function(item, property, oldValue, newValue) {
130 if (item == gMsgFolderSelected) {
131 if(property.toString() == "TotalMessages" || property.toString() == "TotalUnreadMessages") {
132 UpdateStatusMessageCounts(gMsgFolderSelected);
133 UpdateFolderLocationPicker(item);
134 }
135 }
136 },
137
OnItemBoolPropertyChanged
138 OnItemBoolPropertyChanged: function(item, property, oldValue, newValue) { },
139
OnItemUnicharPropertyChanged
140 OnItemUnicharPropertyChanged: function(item, property, oldValue, newValue) { },
OnItemPropertyFlagChanged
141 OnItemPropertyFlagChanged: function(item, property, oldFlag, newFlag) { },
142
OnItemEvent
143 OnItemEvent: function(folder, event) {
144 var eventType = event.toString();
145 if (eventType == "FolderLoaded") {
146 if (folder) {
147 var scrolled = false;
148 var msgFolder = folder.QueryInterface(Components.interfaces.nsIMsgFolder);
149 var uri = folder.URI;
150 var rerootingFolder = (uri == gCurrentFolderToReroot);
151 if (rerootingFolder) {
152 viewDebug("uri = gCurrentFolderToReroot, setting gQSViewIsDirty\n");
153 gQSViewIsDirty = true;
154 gCurrentFolderToReroot = null;
155 if (msgFolder) {
156 msgFolder.endFolderLoading();
157 UpdateStatusQuota(msgFolder);
158 // Suppress command updating when rerooting the folder.
159 // When rerooting, we'll be clearing the selection
160 // which will cause us to update commands.
161 if (gDBView) {
162 gDBView.suppressCommandUpdating = true;
163 // If the db's view isn't set, something went wrong and we
164 // should reroot the folder, which will re-open the view.
165 if (!gDBView.db)
166 gRerootOnFolderLoad = true;
167 }
168 if (gRerootOnFolderLoad)
169 RerootFolder(uri, msgFolder, gCurrentLoadingFolderViewType, gCurrentLoadingFolderViewFlags, gCurrentLoadingFolderSortType, gCurrentLoadingFolderSortOrder);
170
171 var db = msgFolder.getMsgDatabase(msgWindow);
172 if (db)
173 db.resetHdrCacheSize(100);
174
175 if (gDBView) {
176 gDBView.suppressCommandUpdating = false;
177 }
178
179 gCurrentLoadingFolderSortType = 0;
180 gCurrentLoadingFolderSortOrder = 0;
181 gCurrentLoadingFolderViewType = 0;
182 gCurrentLoadingFolderViewFlags = 0;
183
184 // Used for rename folder msg loading after folder is loaded.
185 scrolled = LoadCurrentlyDisplayedMessage();
186
187 if (gStartMsgKey != nsMsgKey_None) {
188 scrolled = SelectAndScrollToKey(gStartMsgKey);
189 gStartMsgKey = nsMsgKey_None;
190 }
191
192 if (gNextMessageAfterLoad) {
193 var type = gNextMessageAfterLoad;
194 gNextMessageAfterLoad = null;
195
196 // Scroll to and select the proper message.
197 scrolled = ScrollToMessage(type, true, true /* selectMessage */);
198 }
199 }
200 }
201 if (uri == gCurrentLoadingFolderURI) {
202 viewDebug("uri == current loading folder uri\n");
203 gCurrentLoadingFolderURI = "";
204 // Scroll to message for virtual folders is done in
205 // gSearchNotificationListener.OnSearchDone (see searchBar.js).
206 if (!scrolled && !(gMsgFolderSelected.flags & MSG_FOLDER_FLAG_VIRTUAL))
207 ScrollToMessageAfterFolderLoad(msgFolder);
208 SetBusyCursor(window, false);
209 }
210 if (gNotifyDefaultInboxLoadedOnStartup && (folder.flags & 0x1000))
211 {
212 var defaultAccount = accountManager.defaultAccount;
213 defaultServer = defaultAccount.incomingServer;
214 var inboxFolder = GetInboxFolder(defaultServer);
215 if (inboxFolder && inboxFolder.URI == folder.URI)
216 {
217 NotifyObservers(null,"defaultInboxLoadedOnStartup",null);
218 gNotifyDefaultInboxLoadedOnStartup = false;
219 }
220 }
221 // Folder loading is over,
222 // now issue quick search if there is an email address.
223 viewDebug("in folder loaded gVirtualFolderTerms = " + gVirtualFolderTerms + "\n");
224 viewDebug("in folder loaded gMsgFolderSelected = " + gMsgFolderSelected.URI + "\n");
225 if (rerootingFolder)
226 {
227 if (gSearchEmailAddress)
228 {
229 Search(gSearchEmailAddress);
230 gSearchEmailAddress = null;
231 }
232 else if (gVirtualFolderTerms)
233 {
234 gDefaultSearchViewTerms = null;
235 viewDebug("searching gVirtualFolderTerms\n");
236 gDBView.viewFolder = gMsgFolderSelected;
237 ViewChangeByFolder(gMsgFolderSelected);
238 }
239 else if (gMsgFolderSelected.flags & MSG_FOLDER_FLAG_VIRTUAL)
240 {
241 viewDebug("selected folder is virtual\n");
242 gDefaultSearchViewTerms = null;
243 }
244 else
245 {
246 // Get the view value from the folder.
247 if (msgFolder)
248 {
249 // If our new view is the same as the old view and we already
250 // have the list of search terms built up for the old view,
251 // just re-use it.
252 var result = GetMailViewForFolder(msgFolder);
253 if (GetSearchInput() && gCurrentViewValue == result && gDefaultSearchViewTerms)
254 {
255 viewDebug("searching gDefaultSearchViewTerms and rerootingFolder\n");
256 Search("");
257 }
258 else if (document.getElementById("mailviews-container")) // Only load the folder view if the views toolbar is visible.
259 {
260 viewDebug("changing view by value\n");
261 ViewChangeByValue(result);
262 }
263 }
264 }
265 }
266 }
267 }
268 else if (eventType == "ImapHdrDownloaded") {
269 if (folder) {
270 var imapFolder = folder.QueryInterface(Components.interfaces.nsIMsgImapMailFolder);
271 if (imapFolder) {
272 var hdrParser = imapFolder.hdrParser;
273 if (hdrParser) {
274 var msgHdr = hdrParser.GetNewMsgHdr();
275 if (msgHdr)
276 {
277 var hdrs = hdrParser.headers;
278 if (hdrs && hdrs.indexOf("X-attachment-size:") > 0) {
279 msgHdr.OrFlags(0x10000000); // 0x10000000 is MSG_FLAG_ATTACHMENT
280 }
281 if (hdrs && hdrs.indexOf("X-image-size:") > 0) {
282 msgHdr.setStringProperty("imageSize", "1");
283 }
284 }
285 }
286 }
287 }
288 }
289 else if (eventType == "DeleteOrMoveMsgCompleted") {
290 HandleDeleteOrMoveMsgCompleted(folder);
291 }
292 else if (eventType == "DeleteOrMoveMsgFailed") {
293 HandleDeleteOrMoveMsgFailed(folder);
294 }
295 else if (eventType == "AboutToCompact") {
296 if (gDBView)
297 gCurrentlyDisplayedMessage = gDBView.currentlyDisplayedMessage;
298 }
299 else if (eventType == "CompactCompleted") {
300 HandleCompactCompleted(folder);
301 }
302 else if (eventType == "RenameCompleted") {
303 SelectFolder(folder.URI);
304 }
305 else if (eventType == "JunkStatusChanged") {
306 HandleJunkStatusChanged(folder);
307 }
308 }
309 }
310
311 var folderObserver = {
canDrop
312 canDrop: function(index, orientation)
313 {
314 return CanDropOnFolderTree(index, orientation);
315 },
316
onDrop
317 onDrop: function(row, orientation)
318 {
319 DropOnFolderTree(row, orientation);
320 },
321
onToggleOpenState
322 onToggleOpenState: function(index)
323 {
324 var folderTree = GetFolderTree();
325
326 // Nothing to do when collapsing an item.
327 if (folderTree.view.isContainerOpen(index))
328 return;
329
330 var folderResource = GetFolderResource(folderTree, index);
331
332 if (folderTree.view.getLevel(index) == 0)
333 {
334 // (Imap/Nntp/Pop) Account item.
335
336 folderResource.QueryInterface(Components.interfaces.nsIMsgFolder)
337 .server.performExpand(msgWindow);
338 }
339 else if (folderResource instanceof Components.interfaces.nsIMsgImapMailFolder)
340 {
341 // Imap message folder item.
342
343 folderResource.performExpand(msgWindow);
344 }
345 },
346
347 onCycleHeader: function(colID, elt)
348 {
349 },
350
onCycleCell
351 onCycleCell: function(row, colID)
352 {
353 },
354
onSelectionChanged
355 onSelectionChanged: function()
356 {
357 },
358
onPerformAction
359 onPerformAction: function(action)
360 {
361 },
362
onPerformActionOnRow
363 onPerformActionOnRow: function(action, row)
364 {
365 },
366
onPerformActionOnCell
367 onPerformActionOnCell: function(action, row, col)
368 {
369 }
370 }
371
HandleDeleteOrMoveMsgFailed
372 function HandleDeleteOrMoveMsgFailed(folder)
373 {
374 gDBView.onDeleteCompleted(false);
375 if(IsCurrentLoadedFolder(folder)) {
376 if(gNextMessageAfterDelete) {
377 gNextMessageAfterDelete = null;
378 gNextMessageViewIndexAfterDelete = -2;
379 }
380 }
381
382 // fix me???
383 // ThreadPaneSelectionChange(true);
384 }
385
386 // WARNING
387 // this is a fragile and complicated function.
388 // be careful when hacking on it.
389 // Don't forget about things like different imap
390 // delete models, multiple views (from multiple thread panes,
391 // search windows, stand alone message windows)
HandleDeleteOrMoveMsgCompleted
Called: ChromeWindow:QueryInterface (1 calls, 14 v-uS)
ChromeWindow:clearSelection (1 calls, 7425 v-uS)
ChromeWindow:onDeleteCompleted (1 calls, 13730 v-uS)
commandglue.js:UpdateMailToolbar (1 calls, 4547 v-uS)
commandglue.js:setTitleFromFolder (1 calls, 381 v-uS)
msgMail3PaneWindow.js:ClearMessagePane (1 calls, 7 v-uS)
msgMail3PaneWindow.js:IsCurrentLoadedFolder (1 calls, 148 v-uS)
392 function HandleDeleteOrMoveMsgCompleted(folder)
393 {
394 // you might not have a db view. this can happen if
395 // biff fires when the 3 pane is set to account central.
396 if (!gDBView)
397 return;
398
399 gDBView.onDeleteCompleted(true);
400
401 if (!IsCurrentLoadedFolder(folder)) {
402 // default value after delete/move/copy is over
403 gNextMessageViewIndexAfterDelete = -2;
404 return;
405 }
406
407 var treeView = gDBView.QueryInterface(Components.interfaces.nsITreeView);
408 var treeSelection = treeView.selection;
409
410 if (gNextMessageViewIndexAfterDelete == -2) {
411 // a move or delete can cause our selection can change underneath us.
412 // this can happen when the user
413 // deletes message from the stand alone msg window
414 // or the search view, or another 3 pane
415 if (treeSelection.count == 0) {
416 // this can happen if you double clicked a message
417 // in the thread pane, and deleted it from the stand alone msg window
418 // see bug #172392
419 treeSelection.clearSelection();
420 setTitleFromFolder(folder, null);
421 ClearMessagePane();
422 UpdateMailToolbar("delete from another view, 0 rows now selected");
423 }
424 else if (treeSelection.count == 1) {
425 // this can happen if you had two messages selected
426 // in the thread pane, and you deleted one of them from another view
427 // (like the view in the stand alone msg window)
428 // since one item is selected, we should load it.
429 var startIndex = {};
430 var endIndex = {};
431 treeSelection.getRangeAt(0, startIndex, endIndex);
432
433 // select the selected item, so we'll load it
434 treeSelection.select(startIndex.value);
435 treeView.selectionChanged();
436
437 EnsureRowInThreadTreeIsVisible(startIndex.value);
438
439 UpdateMailToolbar("delete from another view, 1 row now selected");
440 }
441 else {
442 // this can happen if you have more than 2 messages selected
443 // in the thread pane, and you deleted one of them from another view
444 // (like the view in the stand alone msg window)
445 // since multiple messages are still selected, do nothing.
446 }
447 }
448 else {
449 if (gNextMessageViewIndexAfterDelete != nsMsgViewIndex_None)
450 {
451 var viewSize = treeView.rowCount;
452 if (gNextMessageViewIndexAfterDelete >= viewSize)
453 {
454 if (viewSize > 0)
455 gNextMessageViewIndexAfterDelete = viewSize - 1;
456 else
457 {
458 gNextMessageViewIndexAfterDelete = nsMsgViewIndex_None;
459
460 // there is nothing to select since viewSize is 0
461 treeSelection.clearSelection();
462 setTitleFromFolder(folder, null);
463 ClearMessagePane();
464 UpdateMailToolbar("delete from current view, 0 rows left");
465 }
466 }
467 }
468
469 // if we are about to set the selection with a new element then DON'T clear
470 // the selection then add the next message to select. This just generates
471 // an extra round of command updating notifications that we are trying to
472 // optimize away.
473 if (gNextMessageViewIndexAfterDelete != nsMsgViewIndex_None)
474 {
475 // When deleting a message we don't update the commands
476 // when the selection goes to 0
477 // (we have a hack in nsMsgDBView which prevents that update)
478 // so there is no need to
479 // update commands when we select the next message after the delete;
480 // the commands already
481 // have the right update state...
482 gDBView.suppressCommandUpdating = true;
483
484 // This check makes sure that the tree does not perform a
485 // selection on a non selected row (row < 0), else assertions will
486 // be thrown.
487 if (gNextMessageViewIndexAfterDelete >= 0)
488 treeSelection.select(gNextMessageViewIndexAfterDelete);
489
490 // If gNextMessageViewIndexAfterDelete has the same value
491 // as the last index we had selected, the tree won't generate a
492 // selectionChanged notification for the tree view. So force a manual
493 // selection changed call.
494 // (don't worry it's cheap if we end up calling it twice).
495 if (treeView)
496 treeView.selectionChanged();
497
498 EnsureRowInThreadTreeIsVisible(gNextMessageViewIndexAfterDelete);
499 gDBView.suppressCommandUpdating = false;
500
501 // hook for extra toolbar items
502 // XXX TODO
503 // I think there is a bug in the suppression code above.
504 // What if I have two rows selected, and I hit delete,
505 // and so we load the next row.
506 // What if I have commands that only enable where
507 // exactly one row is selected?
508 UpdateMailToolbar("delete from current view, at least one row selected");
509 }
510 }
511
512 // default value after delete/move/copy is over
513 gNextMessageViewIndexAfterDelete = -2;
514 }
515
HandleCompactCompleted
516 function HandleCompactCompleted(folder)
517 {
518 if (folder)
519 {
520 var resource = folder.QueryInterface(Components.interfaces.nsIRDFResource);
521 if (resource)
522 {
523 var uri = resource.Value;
524 var msgFolder = msgWindow.openFolder;
525 if (msgFolder && uri == msgFolder.URI)
526 {
527 var msgdb = msgFolder.getMsgDatabase(msgWindow);
528 if (msgdb)
529 {
530 var dbFolderInfo = msgdb.dBFolderInfo;
531 sortType = dbFolderInfo.sortType;
532 sortOrder = dbFolderInfo.sortOrder;
533 viewFlags = dbFolderInfo.viewFlags;
534 viewType = dbFolderInfo.viewType;
535 dbFolderInfo = null;
536 }
537
538 RerootFolder(uri, msgFolder, viewType, viewFlags, sortType, sortOrder);
539 LoadCurrentlyDisplayedMessage();
540 }
541 }
542 }
543 }
544
LoadCurrentlyDisplayedMessage
545 function LoadCurrentlyDisplayedMessage()
546 {
547 var scrolled = (gCurrentlyDisplayedMessage != nsMsgViewIndex_None);
548 if (scrolled)
549 {
550 var treeView = gDBView.QueryInterface(Components.interfaces.nsITreeView);
551 var treeSelection = treeView.selection;
552 treeSelection.select(gCurrentlyDisplayedMessage);
553 if (treeView)
554 treeView.selectionChanged();
555 EnsureRowInThreadTreeIsVisible(gCurrentlyDisplayedMessage);
556 SetFocusThreadPane();
557 gCurrentlyDisplayedMessage = nsMsgViewIndex_None; //reset
558 }
559 return scrolled;
560 }
561
IsCurrentLoadedFolder
Called: ChromeWindow:QueryInterface (2 calls, 27 v-uS)
threadPane.js:GetThreadPaneFolder (1 calls, 19 v-uS)
Called By: msgMail3PaneWindow.js:HandleDeleteOrMoveMsgCompleted (1 calls, 148 v-uS)
562 function IsCurrentLoadedFolder(folder)
563 {
564 var msgfolder = folder.QueryInterface(Components.interfaces.nsIMsgFolder);
565 if(msgfolder)
566 {
567 var folderResource = msgfolder.QueryInterface(Components.interfaces.nsIRDFResource);
568 if(folderResource)
569 {
570 var folderURI = folderResource.Value;
571 var currentLoadedFolder = GetThreadPaneFolder();
572 if (currentLoadedFolder.flags & MSG_FOLDER_FLAG_VIRTUAL)
573 {
574 var msgDatabase = currentLoadedFolder.getMsgDatabase(msgWindow);
575 var dbFolderInfo = msgDatabase.dBFolderInfo;
576 var srchFolderUri = dbFolderInfo.getCharProperty("searchFolderUri");
577 var re = new RegExp("^" + folderURI + "$|^" + folderURI + "\||\|" + folderURI + "$|\|" + folderURI +"\|");
578 var retval = (currentLoadedFolder.URI.match(re));
579 return retval;
580
581 }
582 var currentURI = currentLoadedFolder.URI;
583 return(currentURI == folderURI);
584 }
585 }
586
587 return false;
588 }
589
ServerContainsFolder
590 function ServerContainsFolder(server, folder)
591 {
592 if (!folder || !server)
593 return false;
594
595 return server.equals(folder.server);
596 }
597
SelectServer
598 function SelectServer(server)
599 {
600 SelectFolder(server.rootFolder.URI);
601 }
602
603 // we have this incoming server listener in case we need to
604 // alter the folder pane selection when a server is removed
605 // or changed (currently, when the real username or real hostname change)
606 var gThreePaneIncomingServerListener = {
onServerLoaded
607 onServerLoaded: function(server) {},
onServerUnloaded
608 onServerUnloaded: function(server) {
609 var selectedFolders = GetSelectedMsgFolders();
610 for (var i = 0; i < selectedFolders.length; i++) {
611 if (ServerContainsFolder(server, selectedFolders[i])) {
612 SelectServer(accountManager.defaultAccount.incomingServer);
613 // we've made a new selection, we're done
614 return;
615 }
616 }
617
618 // if nothing is selected at this point, better go select the default
619 // this could happen if nothing was selected when the server was removed
620 selectedFolders = GetSelectedMsgFolders();
621 if (selectedFolders.length == 0) {
622 SelectServer(accountManager.defaultAccount.incomingServer);
623 }
624 },
onServerChanged
625 onServerChanged: function(server) {
626 // if the current selected folder is on the server that changed
627 // and that server is an imap or news server,
628 // we need to update the selection.
629 // on those server types, we'll be reconnecting to the server
630 // and our currently selected folder will need to be reloaded
631 // or worse, be invalid.
632 if (server.type != "imap" && server.type !="nntp")
633 return;
634
635 var selectedFolders = GetSelectedMsgFolders();
636 for (var i = 0; i < selectedFolders.length; i++) {
637 // if the selected item is a server, we don't have to update
638 // the selection
639 if (!(selectedFolders[i].isServer) && ServerContainsFolder(server, selectedFolders[i])) {
640 SelectServer(server);
641 // we've made a new selection, we're done
642 return;
643 }
644 }
645 }
646 }
647
648 // aMsgWindowInitialized: false if we are calling from the onload handler, otherwise true
UpdateMailPaneConfig
649 function UpdateMailPaneConfig(aMsgWindowInitialized) {
650 const dynamicIds = ["messagesBox", "mailContent", "threadPaneBox"];
651 var desiredId = dynamicIds[gPrefBranch.getIntPref("mail.pane_config.dynamic")];
652 var messagePane = GetMessagePane();
653 if (messagePane.parentNode.id != desiredId) {
654 ClearAttachmentList();
655 var messagePaneSplitter = GetThreadAndMessagePaneSplitter();
656 var desiredParent = document.getElementById(desiredId);
657 // See Bug 381992. The ctor for the browser element will fire again when we
658 // re-insert the messagePaneBox back into the document.
659 // But the dtor doesn't fire when the element is removed from the document.
660 // Manually call destroy here to avoid a nasty leak.
661 getMessageBrowser().destroy();
662 desiredParent.appendChild(messagePaneSplitter);
663 desiredParent.appendChild(messagePane);
664 messagePaneSplitter.orient = desiredParent.orient;
665 if (aMsgWindowInitialized)
666 {
667 messenger.setWindow(null, null);
668 messenger.setWindow(window, msgWindow);
669 if (gDBView && GetNumSelectedMessages() == 1)
670 gDBView.reloadMessage();
671 }
672 }
673 }
674
675 const MailPrefObserver = {
observe
676 observe: function(subject, topic, prefName) {
677 // verify that we're changing the mail pane config pref
678 if (topic == "nsPref:changed")
679 {
680 if (prefName == "mail.pane_config.dynamic")
681 UpdateMailPaneConfig(true);
682 else if (prefName == "mail.showFolderPaneColumns")
683 UpdateFolderColumnVisibility();
684 }
685 }
686 };
687
OnLoadMessenger
688 function OnLoadMessenger()
689 {
690 // update the pane config before we exit onload otherwise the user may see a flicker if we poke the document
691 // in delayedOnLoadMessenger...
692 UpdateMailPaneConfig(false);
693 document.loadBindingDocument('chrome://global/content/bindings/textbox.xml');
694
695 // Set a sane starting width/height for all resolutions on new profiles. Do this before the window loads
696 if (!document.documentElement.hasAttribute("width"))
697 {
698 var defaultWidth, defaultHeight;
699 if (screen.availHeight <= 600)
700 {
701 document.documentElement.setAttribute("sizemode", "maximized");
702 defaultWidth = 800;
703 defaultHeight = 565;
704 }
705 else // for higher resolution displays, use larger values for height and width
706 {
707 defaultWidth = screen.availWidth <= 1024 ? screen.availWidth * .95 : screen.availWidth * .8;
708 defaultHeight = screen.availHeight * .8;
709 }
710
711 document.documentElement.setAttribute("width", defaultWidth);
712 document.documentElement.setAttribute("height", defaultHeight);
713 }
714
715
716 setTimeout(delayedOnLoadMessenger, 0); // when debugging, set this to 5000, so you can see what happens after the window comes up.
717 }
718
719 /* Functions related to startup */
delayedOnLoadMessenger
720 function delayedOnLoadMessenger()
721 {
722 gPrefBranch.QueryInterface(Components.interfaces.nsIPrefBranch2);
723 gPrefBranch.addObserver("mail.pane_config.dynamic", MailPrefObserver, false);
724 gPrefBranch.addObserver("mail.showFolderPaneColumns", MailPrefObserver, false);
725
726 MailOfflineMgr.init();
727 CreateMailWindowGlobals();
728 GetMessagePane().collapsed = true;
729 verifyAccounts(null);
730
731 InitMsgWindow();
732 messenger.setWindow(window, msgWindow);
733
734 InitializeDataSources();
735 InitPanes();
736 MigrateAttachmentDownloadStore();
737 MigrateJunkMailSettings();
738 MigrateFolderViews();
739
740 accountManager.setSpecialFolders();
741 accountManager.loadVirtualFolders();
742 accountManager.addIncomingServerListener(gThreePaneIncomingServerListener);
743
744 gPhishingDetector.init();
745
746 AddToSession();
747
748 //need to add to session before trying to load start folder otherwise listeners aren't
749 //set up correctly.
750 // argument[0] --> folder uri
751 // argument[1] --> optional message key
752 // argument[2] --> optional email address; // Will come from aim; needs to show msgs from buddy's email address.
753 if ("arguments" in window)
754 {
755 // filter our any feed urls that came in as arguments to the new window...
756 if (window.arguments.length && /^feed:/i.test(window.arguments[0] ))
757 {
758 var feedHandler = Components.classes["@mozilla.org/newsblog-feed-downloader;1"].getService(Components.interfaces.nsINewsBlogFeedDownloader);
759 if (feedHandler)
760 feedHandler.subscribeToFeed(window.arguments[0], null, msgWindow);
761 gStartFolderUri = null;
762 }
763 else
764 gStartFolderUri = (window.arguments.length > 0) ? window.arguments[0] : null;
765 gStartMsgKey = (window.arguments.length > 1) ? window.arguments[1]: nsMsgKey_None;
766 gSearchEmailAddress = (window.arguments.length > 2) ? window.arguments[2] : null;
767 }
768
769 //@line 812 "/home/visbrero/mnt/roisin/rev_control/hg/mozilla/mail/base/content/msgMail3PaneWindow.js"
770 var nsIShellService = Components.interfaces.nsIShellService;
771 var shellService;
772 var defaultAccount;
773 try {
774 shellService = Components.classes["@mozilla.org/mail/shell-service;1"].getService(nsIShellService);
775 defaultAccount = accountManager.defaultAccount;
776 } catch (ex) {}
777
778 // show the default client dialog only if we have at least one account,
779 // if we should check for the default client,
780 // and we aren't already the default for mail)
781 if (shellService && defaultAccount && shellService.shouldCheckDefaultClient
782 && !shellService.isDefaultClient(true, nsIShellService.MAIL))
783 window.openDialog("chrome://messenger/content/defaultClientDialog.xul", "DefaultClient",
784 "modal,centerscreen,chrome,resizable=no");
785 //@line 828 "/home/visbrero/mnt/roisin/rev_control/hg/mozilla/mail/base/content/msgMail3PaneWindow.js"
786
787 setTimeout("loadStartFolder(gStartFolderUri);", 0);
788
789 // FIX ME - later we will be able to use onload from the overlay
790 OnLoadMsgHeaderPane();
791
792 gHaveLoadedMessage = false;
793
794 gNotifyDefaultInboxLoadedOnStartup = true;
795
796 //Set focus to the Thread Pane the first time the window is opened.
797 SetFocusThreadPane();
798
799 // initialize the customizeDone method on the customizeable toolbar
800 var toolbox = document.getElementById("mail-toolbox");
801 toolbox.customizeDone = MailToolboxCustomizeDone;
802
803 var toolbarset = document.getElementById('customToolbars');
804 toolbox.toolbarset = toolbarset;
805 }
806
OnUnloadMessenger
807 function OnUnloadMessenger()
808 {
809 OnLeavingFolder(gMsgFolderSelected); // mark all read in current folder
810 accountManager.removeIncomingServerListener(gThreePaneIncomingServerListener);
811 gPrefBranch.QueryInterface(Components.interfaces.nsIPrefBranch2);
812 gPrefBranch.removeObserver("mail.pane_config.dynamic", MailPrefObserver);
813 gPrefBranch.removeObserver("mail.showFolderPaneColumns", MailPrefObserver);
814 document.getElementById('tabmail').closeTabs();
815
816 gPhishingDetector.shutdown();
817
818 // FIX ME - later we will be able to use onload from the overlay
819 OnUnloadMsgHeaderPane();
820
821 OnUnloadFolderPane();
822
823 OnMailWindowUnload();
824 }
825
NotifyObservers
826 function NotifyObservers(aSubject, aTopic, aData)
827 {
828 var observerService = Components.classes["@mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService);
829 observerService.notifyObservers(aSubject, aTopic, aData);
830 }
831
loadStartFolder
832 function loadStartFolder(initialUri)
833 {
834 var folderTree = GetFolderTree();
835 var defaultServer = null;
836 var startFolderResource = null;
837 var isLoginAtStartUpEnabled = false;
838
839 //First get default account
840 try
841 {
842 if(initialUri)
843 startFolderResource = RDF.GetResource(initialUri);
844 else
845 {
846 var defaultAccount = accountManager.defaultAccount;
847
848 defaultServer = defaultAccount.incomingServer;
849 var rootMsgFolder = defaultServer.rootMsgFolder;
850
851 startFolderResource = rootMsgFolder.QueryInterface(Components.interfaces.nsIRDFResource);
852
853 // Enable check new mail once by turning checkmail pref 'on' to bring
854 // all users to one plane. This allows all users to go to Inbox. User can
855 // always go to server settings panel and turn off "Check for new mail at startup"
856 if (!gPrefBranch.getBoolPref(kMailCheckOncePrefName))
857 {
858 gPrefBranch.setBoolPref(kMailCheckOncePrefName, true);
859 defaultServer.loginAtStartUp = true;
860 }
861
862 // Get the user pref to see if the login at startup is enabled for default account
863 isLoginAtStartUpEnabled = defaultServer.loginAtStartUp;
864
865 // Get Inbox only if login at startup is enabled.
866 if (isLoginAtStartUpEnabled)
867 {
868 //now find Inbox
869 var outNumFolders = new Object();
870 var inboxFolder = rootMsgFolder.getFoldersWithFlag(0x1000, 1, outNumFolders);
871 if (!inboxFolder) return;
872
873 startFolderResource = inboxFolder.QueryInterface(Components.interfaces.nsIRDFResource);
874 }
875 }
876
877 var startFolder = startFolderResource.QueryInterface(Components.interfaces.nsIMsgFolder);
878
879 // it is possible we were given an initial uri and we need to subscribe or try to add
880 // the folder. i.e. the user just clicked on a news folder they aren't subscribed to from a browser
881 // the news url comes in here.
882
883 // Perform biff on the server to check for new mail, except for imap
884 // or a pop3 account that is deferred or deferred to,
885 // or the case where initialUri is non-null (non-startup)
886 if (!initialUri && isLoginAtStartUpEnabled && gLoadStartFolder
887 && !defaultServer.isDeferredTo &&
888 defaultServer.rootFolder == defaultServer.rootMsgFolder)
889 defaultServer.performBiff(msgWindow);
890
891 SelectFolder(startFolder.URI);
892 }
893 catch(ex)
894 {
895 // this is the case where we're trying to auto-subscribe to a folder.
896 if (initialUri && !startFolder.parent)
897 {
898 // hack to force display of thread pane.
899 ShowingThreadPane();
900 messenger.loadURL(window, initialUri);
901 return;
902 }
903
904 dump(ex);
905 dump('Exception in LoadStartFolder caused by no default account. We know about this\n');
906 }
907
908 // if gLoadStartFolder is true, then we must have just created a POP3 account
909 // and we aren't supposed to initially download mail. (Bug #270743)
910 if (gLoadStartFolder)
911 MsgGetMessagesForAllServers(defaultServer);
912
913 // if appropriate, send unsent messages. This may end up prompting the user
914 if (MailOfflineMgr.isOnline() && MailOfflineMgr.shouldSendUnsentMessages())
915 SendUnsentMessages();
916 }
917
AddToSession
918 function AddToSession()
919 {
920 try {
921 var mailSession = Components.classes[mailSessionContractID]
922 .getService(Components.interfaces.nsIMsgMailSession);
923 var nsIFolderListener = Components.interfaces.nsIFolderListener;
924 var notifyFlags = nsIFolderListener.intPropertyChanged | nsIFolderListener.event;
925 mailSession.AddFolderListener(folderListener, notifyFlags);
926 } catch (ex) {
927 dump("Error adding to session\n");
928 }
929 }
930
InitPanes
931 function InitPanes()
932 {
933 OnLoadFolderPane();
934 OnLoadThreadPane();
935 SetupCommandUpdateHandlers();
936 }
937
InitializeDataSources
938 function InitializeDataSources()
939 {
940 //Setup common mailwindow stuff.
941 AddDataSources();
942 }
943
OnFolderUnreadColAttrModified
944 function OnFolderUnreadColAttrModified(event)
945 {
946 if (event.attrName == "hidden")
947 {
948 var folderNameCell = document.getElementById("folderNameCell");
949 var label = {"true": "?folderTreeName", "false": "?folderTreeSimpleName"};
950 folderNameCell.setAttribute("label", label[event.newValue]);
951 }
952 }
953
UpdateFolderColumnVisibility
954 function UpdateFolderColumnVisibility()
955 {
956 var folderNameCol = document.getElementById("folderNameCol");
957 var showColumns = gPrefBranch.getBoolPref("mail.showFolderPaneColumns");
958 var folderUnreadCol = document.getElementById("folderUnreadCol");
959 var folderColumnLabel = document.getElementById("folderColumnLabel");
960 if (!showColumns)
961 {
962 var folderTotalCol = document.getElementById("folderTotalCol");
963 var folderSizeCol = document.getElementById("folderSizeCol");
964 folderUnreadCol.setAttribute("hidden", "true");
965 folderTotalCol.setAttribute("hidden", "true");
966 folderSizeCol.setAttribute("hidden", "true");
967 folderNameCol.removeAttribute("label");
968 }
969 else
970 {
971 folderNameCol.setAttribute("label", folderColumnLabel.value);
972 }
973
974 folderNameCol.setAttribute("hideheader", showColumns ? "false" : "true");
975 var folderTree = document.getElementById("folderTree");
976 folderTree.setAttribute("hidecolumnpicker", showColumns ? "false" : "true");
977 var hidden = folderUnreadCol.getAttribute("hidden");
978 if (hidden != "true")
979 {
980 var folderNameCell = document.getElementById("folderNameCell");
981 folderNameCell.setAttribute("label", "?folderTreeSimpleName");
982 }
983 }
984
985 // loadFolderViewForTree -- a helper routine split away from
986 // loadFolderView.
987 // returns a localized string corresponding to the name of the new view
loadFolderViewForTree
988 function loadFolderViewForTree(aNewFolderView, aFolderTree)
989 {
990 var folderPaneHeader = document.getElementById('folderpane-title');
991 var database = aFolderTree.database;
992 var nsIRDFDataSource = Components.interfaces.nsIRDFDataSource;
993
994 // Each folder pane view has the following properties:
995 // ref-> the ref attribute for the folderTree
996 // label -> the UI label associated with the folder view
997 // datasources -> array of the data sources associated with the view
998
999 var folderViews = [
1000 {ref:"msgaccounts:/", label:"folderPaneHeader", dataSources: [accountManagerDataSource.QueryInterface(nsIRDFDataSource),
1001 folderDataSource.QueryInterface(nsIRDFDataSource)] },
1002 {ref:"mailnewsunreadfolders:/", label:"folderPaneHeader_unread", dataSources: [unreadFolderDataSource.QueryInterface(nsIRDFDataSource)]},
1003 {ref:"mailnewsfavefolders:/", label:"folderPaneHeader_favorites", dataSources: [favoriteFoldersDataSource.QueryInterface(nsIRDFDataSource)]},
1004 {ref:"mailnewsrecentfolders:/", label:"folderPaneHeader_recent", dataSources: [recentFoldersDataSource.QueryInterface(nsIRDFDataSource)]},
1005 ];
1006
1007 // unload the current data sources
1008 if (gCurrentFolderView != undefined)
1009 {
1010 var dataSourcesToUnload = folderViews[gCurrentFolderView].dataSources;
1011 for (index in dataSourcesToUnload)
1012 database.RemoveDataSource(dataSourcesToUnload[index]);
1013 }
1014
1015 // add the new data sources
1016 var dataSourcesToAdd = folderViews[aNewFolderView].dataSources;
1017 for (index in dataSourcesToAdd)
1018 {
1019 database.AddDataSource(dataSourcesToAdd[index]);
1020 var msgDS = dataSourcesToAdd[index].QueryInterface(Components.interfaces.nsIMsgRDFDataSource);
1021 msgDS.window = msgWindow;
1022 }
1023
1024 aFolderTree.setAttribute('ref', folderViews[aNewFolderView].ref);
1025 return gMessengerBundle.getString(folderViews[aNewFolderView].label);
1026 }
1027
loadFolderView
1028 function loadFolderView(aNewFolderView)
1029 {
1030 if (gCurrentFolderView && (gCurrentFolderView == aNewFolderView))
1031 return;
1032
1033 var folderTree = GetFolderTree();
1034
1035 var folderPaneHeader = document.getElementById('folderpane-title');
1036 var folderTree = GetFolderTree();
1037 var database = GetFolderDatasource();
1038
1039 // load the folder view into the folder pane
1040 folderPaneHeader.value = loadFolderViewForTree(aNewFolderView, GetFolderTree());
1041
1042 // if the folder location picker is visible, load the folder view into the location
1043 // picker as well.
1044 var folderLocationPicker = document.getElementById('folder-location-container');
1045 if (folderLocationPicker)
1046 loadFolderViewForTree(aNewFolderView, document.getElementById('folderLocationPopup').tree);
1047
1048 // now reflect the new value back into prefs
1049 gPrefBranch.setIntPref('mail.ui.folderpane.view', gCurrentFolderView = aNewFolderView);
1050 }
1051
1052 // we can cycle the folder view forward or backwards
CycleFolderView
1053 function CycleFolderView(aCycleForward)
1054 {
1055 // pass the call onto loadFolderView...
1056 var offset = aCycleForward ? 1 : kNumFolderViews - 1;
1057 loadFolderView((gCurrentFolderView + offset) % kNumFolderViews);
1058 }
1059
OnLoadFolderPane
1060 function OnLoadFolderPane()
1061 {
1062 // want to start up showing the folder pane, in case we shut down
1063 // with the 3-pane showing a single message.
1064 document.getElementById("folderpane_splitter").collapsed = false;
1065 document.getElementById("folderPaneBox").collapsed = false;
1066 UpdateFolderColumnVisibility();
1067 var folderUnreadCol = document.getElementById("folderUnreadCol");
1068 folderUnreadCol.addEventListener("DOMAttrModified", OnFolderUnreadColAttrModified, false);
1069
1070 loadFolderView(gPrefBranch.getIntPref('mail.ui.folderpane.view'));
1071
1072 var folderTree = GetFolderTree();
1073 var folderTreeBuilder = folderTree.builder.QueryInterface(Components.interfaces.nsIXULTreeBuilder);
1074 folderTreeBuilder.addObserver(folderObserver);
1075 folderTree.addEventListener("click",FolderPaneOnClick,true);
1076 folderTree.addEventListener("mousedown",TreeOnMouseDown,true);
1077 }
1078
OnUnloadFolderPane
1079 function OnUnloadFolderPane()
1080 {
1081 var folderTree = GetFolderTree();
1082 var folderTreeBuilder = folderTree.builder.QueryInterface(Components.interfaces.nsIXULTreeBuilder);
1083 folderTreeBuilder.removeObserver(folderObserver);
1084 var folderUnreadCol = document.getElementById("folderUnreadCol");
1085 folderUnreadCol.removeEventListener("DOMAttrModified", OnFolderUnreadColAttrModified, false);
1086 folderTree.removeEventListener("click",FolderPaneOnClick,true);
1087 folderTree.removeEventListener("mousedown",TreeOnMouseDown,true);
1088 }
1089
1090 // builds prior to 12-08-2001 did not have the labels column
1091 // in the thread pane. so if a user ran an old build, and then
1092 // upgraded, they get the new column, and this causes problems.
1093 // We're trying to avoid a similar problem to bug #96979.
1094 // to work around this, we hide the column once, using the
1095 // "mailnews.ui.threadpane.version" pref.
UpgradeThreadPaneUI
1096 function UpgradeThreadPaneUI()
1097 {
1098 var threadPaneUIVersion;
1099
1100 try {
1101
1102 threadPaneUIVersion = gPrefBranch.getIntPref("mailnews.ui.threadpane.version");
1103
1104 // Note: threadTree._reorderColumn will throw an ERROR if the columns specified are already in the same order!
1105
1106 if (threadPaneUIVersion < 6)
1107 {
1108 var threadTree = document.getElementById("threadTree");
1109 var dateCol = document.getElementById("dateCol");
1110 var receivedCol = document.getElementById("receivedCol");
1111 var junkCol = document.getElementById("junkStatusCol");
1112
1113 if (threadPaneUIVersion < 5)
1114 {
1115 if (threadPaneUIVersion < 4)
1116 {
1117 if (threadPaneUIVersion < 3)
1118 {
1119
1120 // in thunderbird, we are inserting the junk column just before the
1121 // date column.
1122 threadTree._reorderColumn(junkCol, dateCol, true);
1123 }
1124
1125 var senderCol = document.getElementById("senderCol");
1126 var recipientCol = document.getElementById("recipientCol");
1127 threadTree._reorderColumn(recipientCol, junkCol, true);
1128 threadTree._reorderColumn(senderCol, recipientCol, true);
1129
1130 } // version 4 upgrades
1131
1132 // version 5 adds a new column called attachments
1133 var attachmentCol = document.getElementById("attachmentCol");
1134 var subjectCol = document.getElementById("subjectCol");
1135
1136 threadTree._reorderColumn(attachmentCol, subjectCol, true);
1137
1138 } // version 5 upgrades
1139
1140 if (dateCol)
1141 threadTree._reorderColumn(receivedCol, dateCol, true);
1142 else
1143 threadTree._reorderColumn(receivedCol, junkCol, false);
1144
1145 gPrefBranch.setIntPref("mailnews.ui.threadpane.version", 6);
1146
1147 } // version 6 upgrades
1148 }
1149 catch (ex) {
1150 dump("UpgradeThreadPane: ex = " + ex + "\n");
1151 }
1152 }
1153
OnLoadThreadPane
1154 function OnLoadThreadPane()
1155 {
1156 UpgradeThreadPaneUI();
1157 }
1158
1159 // folderLocationPickerOnLoad can be called multiple times
1160 // and it can be called when the location picker isn't in the toolbar
folderLocationPickerOnLoad
1161 function folderLocationPickerOnLoad()
1162 {
1163 var folderLocationPicker = document.getElementById('folder-location-container');
1164 if (!folderLocationPicker)
1165 return;
1166
1167 var locationTree = document.getElementById('folderLocationPopup').tree;
1168 locationTree.database.AddDataSource(accountManagerDataSource);
1169 locationTree.database.AddDataSource(folderDataSource);
1170 locationTree.setAttribute("ref", "msgaccounts:/");
1171 }
1172
OnLocationTreeSelect
1173 function OnLocationTreeSelect(menulist)
1174 {
1175 SelectFolder(menulist.getAttribute('uri'));
1176 }
1177
UpdateFolderLocationPicker
Called: ChromeWindow:getElementById (1 calls, 15 v-uS)
1178 function UpdateFolderLocationPicker(resource)
1179 {
1180 var folderLocationPicker = document.getElementById('folder-location-container');
1181 if (!folderLocationPicker)
1182 return;
1183
1184 var tree = GetFolderTree();
1185 var folders = document.getElementById('locationFolders');
1186 var properties = ['BiffState', 'NewMessages', 'HasUnreadMessages',
1187 'SpecialFolder', 'IsServer', 'IsSecure', 'ServerType', 'NoSelect'];
1188 var label = GetFolderAttribute(tree, resource, 'FolderTreeName');
1189 folders.setAttribute("label", label);
1190 for (var i in properties)
1191 {
1192 var property = properties[i];
1193 var value = GetFolderAttribute(tree, resource, property);
1194 folders.setAttribute(property, value);
1195 }
1196 folders.setAttribute('uri', resource.Value);
1197 }
1198
GetFolderDatasource
1199 function GetFolderDatasource()
1200 {
1201 var folderTree = GetFolderTree();
1202 return folderTree.database;
1203 }
1204
1205 /* Functions for accessing particular parts of the window*/
GetFolderTree
Called By: mail3PaneWindowCommands.js:IsFolderSelected (2 calls, 15 v-uS)
1206 function GetFolderTree()
1207 {
1208 if (!gFolderTree)
1209 gFolderTree = document.getElementById("folderTree");
1210 return gFolderTree;
1211 }
1212
GetSearchInput
1213 function GetSearchInput()
1214 {
1215 if (!gSearchInput)
1216 gSearchInput = document.getElementById("searchInput");
1217 return gSearchInput;
1218 }
1219
GetMessagePane
1220 function GetMessagePane()
1221 {
1222 if (!gMessagePane)
1223 gMessagePane = document.getElementById("messagepanebox");
1224 return gMessagePane;
1225 }
1226
GetMessagePaneFrame
1227 function GetMessagePaneFrame()
1228 {
1229 return window.content;
1230 }
1231
getMailToolbox
1232 function getMailToolbox()
1233 {
1234 return document.getElementById("mail-toolbox");
1235 }
1236
1237 function FindInSidebar(currentWindow, id)
1238 {
1239 var item = currentWindow.document.getElementById(id);
1240 if (item)
1241 return item;
1242
1243 for (var i = 0; i < currentWindow.frames.length; ++i)
1244 {
1245 var frameItem = FindInSidebar(currentWindow.frames[i], id);
1246 if (frameItem)
1247 return frameItem;
1248 }
1249
1250 return null;
1251 }
1252
GetThreadAndMessagePaneSplitter
1253 function GetThreadAndMessagePaneSplitter()
1254 {
1255 if (!gThreadAndMessagePaneSplitter)
1256 gThreadAndMessagePaneSplitter = document.getElementById('threadpane-splitter');
1257 return gThreadAndMessagePaneSplitter;
1258 }
1259
GetUnreadCountElement
Called By: commandglue.js:UpdateStatusMessageCounts (22 calls, 159 v-uS)
1260 function GetUnreadCountElement()
1261 {
1262 if (!gUnreadCount)
1263 gUnreadCount = document.getElementById('unreadMessageCount');
1264 return gUnreadCount;
1265 }
1266
GetTotalCountElement
Called By: commandglue.js:UpdateStatusMessageCounts (22 calls, 160 v-uS)
1267 function GetTotalCountElement()
1268 {
1269 if (!gTotalCount)
1270 gTotalCount = document.getElementById('totalMessageCount');
1271 return gTotalCount;
1272 }
1273
IsMessagePaneCollapsed
1274 function IsMessagePaneCollapsed()
1275 {
1276 return GetMessagePane().collapsed;
1277 }
1278
IsFolderPaneCollapsed
1279 function IsFolderPaneCollapsed()
1280 {
1281 return GetFolderTree().parentNode.collapsed;
1282 }
1283
ClearThreadPaneSelection
1284 function ClearThreadPaneSelection()
1285 {
1286 try {
1287 if (gDBView) {
1288 var treeView = gDBView.QueryInterface(Components.interfaces.nsITreeView);
1289 var treeSelection = treeView.selection;
1290 if (treeSelection)
1291 treeSelection.clearSelection();
1292 }
1293 }
1294 catch (ex) {
1295 dump("ClearThreadPaneSelection: ex = " + ex + "\n");
1296 }
1297 }
1298
ClearMessagePane
Called By: msgMail3PaneWindow.js:HandleDeleteOrMoveMsgCompleted (1 calls, 7 v-uS)
1299 function ClearMessagePane()
1300 {
1301 if(gHaveLoadedMessage)
1302 {
1303 gHaveLoadedMessage = false;
1304 if (GetMessagePaneFrame().location.href != "about:blank")
1305 GetMessagePaneFrame().location.href = "about:blank";
1306
1307 // hide the message header view AND the message pane...
1308 HideMessageHeaderPane();
1309 gMessageNotificationBar.clearMsgNotifications();
1310 ClearPendingReadTimer();
1311 }
1312 }
1313
1314 // Function to change the highlighted row to where the mouse was clicked
1315 // without loading the contents of the selected row.
1316 // It will also keep the outline/dotted line in the original row.
ChangeSelectionWithoutContentLoad
1317 function ChangeSelectionWithoutContentLoad(event, tree)
1318 {
1319 var treeBoxObj = tree.treeBoxObject;
1320 var treeSelection = treeBoxObj.view.selection;
1321
1322 var row = treeBoxObj.getRowAt(event.clientX, event.clientY);
1323 // make sure that row.value is valid so that it doesn't mess up
1324 // the call to ensureRowIsVisible().
1325 if((row >= 0) && !treeSelection.isSelected(row))
1326 {
1327 var saveCurrentIndex = treeSelection.currentIndex;
1328 treeSelection.selectEventsSuppressed = true;
1329 treeSelection.select(row);
1330 treeSelection.currentIndex = saveCurrentIndex;
1331 treeBoxObj.ensureRowIsVisible(row);
1332 treeSelection.selectEventsSuppressed = false;
1333
1334 // Keep track of which row in the thread pane is currently selected.
1335 if(tree.id == "threadTree")
1336 gThreadPaneCurrentSelectedIndex = row;
1337 }
1338 event.stopPropagation();
1339 }
1340
TreeOnMouseDown
1341 function TreeOnMouseDown(event)
1342 {
1343 // Detect right mouse click and change the highlight to the row
1344 // where the click happened without loading the message headers in
1345 // the Folder or Thread Pane.
1346 if (event.button == 2)
1347 {
1348 gRightMouseButtonDown = true;
1349 ChangeSelectionWithoutContentLoad(event, event.target.parentNode);
1350 }
1351 else
1352 gRightMouseButtonDown = false;
1353 }
1354
FolderPaneOnClick
1355 function FolderPaneOnClick(event)
1356 {
1357 // we only care about button 0 (left click) events
1358 if (event.button != 0)
1359 return;
1360
1361 var folderTree = GetFolderTree();
1362 var row = {};
1363 var col = {};
1364 var elt = {};
1365 folderTree.treeBoxObject.getCellAt(event.clientX, event.clientY, row, col, elt);
1366 if (row.value == -1) {
1367 if (event.originalTarget.localName == "treecol")
1368 {
1369 // clicking on the name column in the folder pane should not sort
1370 event.stopPropagation();
1371 }
1372 }
1373 else if ((event.originalTarget.localName == "slider") ||
1374 (event.originalTarget.localName == "scrollbarbutton")) {
1375 event.stopPropagation();
1376 }
1377 else if ((event.detail == 2) && (elt.value != "twisty") &&
1378 (folderTree.view.getLevel(row.value) != 0)) {
1379 FolderPaneDoubleClick(row.value, event);
1380 }
1381 }
1382
FolderPaneDoubleClick
1383 function FolderPaneDoubleClick(folderIndex, event)
1384 {
1385 if (!gPrefBranch.getBoolPref("mailnews.reuse_thread_window2"))
1386 {
1387 var folderResource = GetFolderResource(GetFolderTree(), folderIndex);
1388 // Open a new msg window only if we are double clicking on
1389 // folders or newsgroups.
1390 MsgOpenNewWindowForFolder(folderResource.Value, -1 /* key */);
1391
1392 // double clicking should not toggle the open / close state of the
1393 // folder. this will happen if we don't prevent the event from
1394 // bubbling to the default handler in tree.xml
1395 event.stopPropagation();
1396 }
1397 }
1398
ChangeSelection
1399 function ChangeSelection(tree, newIndex)
1400 {
1401 if(newIndex >= 0)
1402 {
1403 tree.view.selection.select(newIndex);
1404 tree.treeBoxObject.ensureRowIsVisible(newIndex);
1405 }
1406 }
1407
GetSelectedFolders
1408 function GetSelectedFolders()
1409 {
1410 var folderArray = [];
1411 var k = 0;
1412 var folderTree = GetFolderTree();
1413 var rangeCount = folderTree.view.selection.getRangeCount();
1414
1415 for(var i = 0; i < rangeCount; i++)
1416 {
1417 var startIndex = {};
1418 var endIndex = {};
1419 folderTree.view.selection.getRangeAt(i, startIndex, endIndex);
1420 for (var j = startIndex.value; j <= endIndex.value; j++)
1421 {
1422 var folderResource = GetFolderResource(folderTree, j);
1423 folderArray[k++] = folderResource.Value;
1424 }
1425 }
1426
1427 return folderArray;
1428 }
1429
GetSelectedMsgFolders
1430 function GetSelectedMsgFolders()
1431 {
1432 var folderArray = [];
1433 var folderTree = GetFolderTree();
1434 var rangeCount = folderTree.view.selection.getRangeCount();
1435
1436 for (var i = 0; i < rangeCount; i++)
1437 {
1438 var startIndex = {};
1439 var endIndex = {};
1440 folderTree.view.selection.getRangeAt(i, startIndex, endIndex);
1441 for (var j = startIndex.value; j <= endIndex.value; j++)
1442 {
1443 var folderResource = GetFolderResource(folderTree, j);
1444 var msgFolder = folderResource.QueryInterface(Components.interfaces.nsIMsgFolder);
1445 folderArray.push(msgFolder);
1446 }
1447 }
1448
1449 return folderArray;
1450 }
1451
GetFirstSelectedMessage
Called By: mailWindowOverlay.js:UpdateDeleteCommand (4 calls, 181 v-uS)
1452 function GetFirstSelectedMessage()
1453 {
1454 try {
1455 return gDBView.URIForFirstSelectedMessage;
1456 }
1457 catch (ex) {
1458 return null;
1459 }
1460 }
1461
GetSelectedIndices
1462 function GetSelectedIndices(dbView)
1463 {
1464 try {
1465 var indicesArray = {};
1466 var length = {};
1467 dbView.getIndicesForSelection(indicesArray,length);
1468 return indicesArray.value;
1469 }
1470 catch (ex) {
1471 dump("ex = " + ex + "\n");
1472 return null;
1473 }
1474 }
1475
GetSelectedMessages
1476 function GetSelectedMessages()
1477 {
1478 try {
1479 var messageArray = {};
1480 var length = {};
1481 var view = GetDBView();
1482 view.getURIsForSelection(messageArray,length);
1483 if (length.value)
1484 return messageArray.value;
1485 else
1486 return null;
1487 }
1488 catch (ex) {
1489 dump("ex = " + ex + "\n");
1490 return null;
1491 }
1492 }
1493
GetLoadedMsgFolder
1494 function GetLoadedMsgFolder()
1495 {
1496 if (!gDBView) return null;
1497 return gDBView.msgFolder;
1498 }
1499
GetLoadedMessage
1500 function GetLoadedMessage()
1501 {
1502 try {
1503 return gDBView.URIForFirstSelectedMessage;
1504 }
1505 catch (ex) {
1506 return null;
1507 }
1508 }
1509
1510 //Clear everything related to the current message. called after load start page.
ClearMessageSelection
1511 function ClearMessageSelection()
1512 {
1513 ClearThreadPaneSelection();
1514 }
1515
1516 // Figures out how many messages are selected (hilighted - does not necessarily
1517 // have the dotted outline) above a given index row value in the thread pane.
NumberOfSelectedMessagesAboveCurrentIndex
1518 function NumberOfSelectedMessagesAboveCurrentIndex(index)
1519 {
1520 var numberOfMessages = 0;
1521 var indicies = GetSelectedIndices(gDBView);
1522
1523 if (indicies && indicies.length)
1524 {
1525 for (var i = 0; i < indicies.length; i++)
1526 {
1527 if (indicies[i] < index)
1528 ++numberOfMessages;
1529 else
1530 break;
1531 }
1532 }
1533 return numberOfMessages;
1534 }
1535
SetNextMessageAfterDelete
Called: ChromeWindow:isSelected (1 calls, 10 v-uS)
XULElement:QueryInterface (1 calls, 14 v-uS)
threadPane.js:GetThreadTree (1 calls, 8 v-uS)
Called By: ChromeWindow:doCommand (1 calls, 145 v-uS)
1536 function SetNextMessageAfterDelete()
1537 {
1538 var treeSelection = GetThreadTree().view.selection;
1539
1540 if (treeSelection.isSelected(treeSelection.currentIndex))
1541 {
1542 gNextMessageViewIndexAfterDelete = gDBView.msgToSelectAfterDelete;
1543 gSelectedIndexWhenDeleting = treeSelection.currentIndex;
1544 }
1545 else if(gDBView.removeRowOnMoveOrDelete)
1546 {
1547 // Only set gThreadPaneDeleteOrMoveOccurred to true if the message was
1548 // truly moved to the trash or deleted, as opposed to an IMAP delete
1549 // (where it is only "marked as deleted". This will prevent bug 142065.
1550 //
1551 // If it's an IMAP delete, then just set gNextMessageViewIndexAfterDelete
1552 // to treeSelection.currentIndex (where the outline is at) because nothing
1553 // was moved or deleted from the folder.
1554 gThreadPaneDeleteOrMoveOccurred = true;
1555 gNextMessageViewIndexAfterDelete = treeSelection.currentIndex - NumberOfSelectedMessagesAboveCurrentIndex(treeSelection.currentIndex);
1556 }
1557 else
1558 gNextMessageViewIndexAfterDelete = treeSelection.currentIndex;
1559 }
1560
EnsureFolderIndex
1561 function EnsureFolderIndex(builder, msgFolder)
1562 {
1563 // try to get the index of the folder in the tree
1564 var index = builder.getIndexOfResource(msgFolder);
1565 if (index == -1) {
1566 // if we couldn't find the folder, open the parent
1567 builder.toggleOpenState(EnsureFolderIndex(builder, msgFolder.parent));
1568 index = builder.getIndexOfResource(msgFolder);
1569 }
1570 return index;
1571 }
1572
SelectFolder
1573 function SelectFolder(folderUri)
1574 {
1575 var folderTree = GetFolderTree();
1576 var folderResource = RDF.GetResource(folderUri);
1577 var msgFolder = folderResource.QueryInterface(Components.interfaces.nsIMsgFolder);
1578
1579 // Before we can select a folder, we need to make sure it is "visible"
1580 // in the tree. To do that, we need to ensure that all its
1581 // ancestors are expanded.
1582 var folderIndex = EnsureFolderIndex(folderTree.builderView, msgFolder);
1583 ChangeSelection(folderTree, folderIndex);
1584 }
1585
SelectMessage
1586 function SelectMessage(messageUri)
1587 {
1588 var msgHdr = messenger.messageServiceFromURI(messageUri).messageURIToMsgHdr(messageUri);
1589 if (msgHdr)
1590 gDBView.selectMsgByKey(msgHdr.messageKey);
1591 }
1592
ReloadMessage
1593 function ReloadMessage()
1594 {
1595 gDBView.reloadMessage();
1596 }
1597
GetDBView
1598 function GetDBView()
1599 {
1600 return gDBView;
1601 }
1602
GetFolderResource
Called: ChromeWindow:getResourceAtIndex (2 calls, 42 v-uS)
XULElement:QueryInterface (2 calls, 23 v-uS)
Called By: mail3PaneWindowCommands.js:IsFolderSelected (2 calls, 164 v-uS)
1603 function GetFolderResource(tree, index)
1604 {
1605 return tree.builderView.getResourceAtIndex(index);
1606 }
1607
GetFolderAttribute
Called: ChromeWindow:GetResource (2 calls, 45 v-uS)
ChromeWindow:GetTarget (2 calls, 51 v-uS)
ChromeWindow:QueryInterface (2 calls, 32 v-uS)
Called By: mail3PaneWindowCommands.js:IsFolderSelected (2 calls, 346 v-uS)
1608 function GetFolderAttribute(tree, source, attribute)
1609 {
1610 var property = RDF.GetResource("http://home.netscape.com/NC-rdf#" + attribute);
1611 var target = tree.database.GetTarget(source, property, true);
1612 if (target)
1613 target = target.QueryInterface(Components.interfaces.nsIRDFLiteral).Value;
1614 return target;
1615 }
1616
LoadNavigatedToMessage
1617 function LoadNavigatedToMessage(msgHdr, folder, folderUri)
1618 {
1619 if (IsCurrentLoadedFolder(folder))
1620 {
1621 gDBView.selectMsgByKey(msgHdr.messageKey);
1622 }
1623 else
1624 {
1625 gStartMsgKey = msgHdr.messageKey;
1626 SelectFolder(folderUri);
1627 }
1628 }
1629
1630 // Some of the per account junk mail settings have been
1631 // converted to global prefs. Let's try to migrate some
1632 // of those settings from the default account.
MigrateJunkMailSettings
1633 function MigrateJunkMailSettings()
1634 {
1635 var junkMailSettingsVersion = gPrefBranch.getIntPref("mail.spam.version");
1636 if (!junkMailSettingsVersion)
1637 {
1638 // Get the default account, check to see if we have values for our
1639 // globally migrated prefs.
1640 var defaultAccount;
1641 try {
1642 defaultAccount = accountManager.defaultAccount;
1643 } catch (ex) {}
1644 if (defaultAccount && defaultAccount.incomingServer)
1645 {
1646 // we only care about
1647 var prefix = "mail.server." + defaultAccount.incomingServer.key + ".";
1648 if (gPrefBranch.prefHasUserValue(prefix + "manualMark"))
1649 gPrefBranch.setBoolPref("mail.spam.manualMark", pref.getBoolPref(prefix + "manualMark"));
1650 if (gPrefBranch.prefHasUserValue(prefix + "manualMarkMode"))
1651 gPrefBranch.setIntPref("mail.spam.manualMarkMode", pref.getIntPref(prefix + "manualMarkMode"));
1652 if (gPrefBranch.prefHasUserValue(prefix + "spamLoggingEnabled"))
1653 gPrefBranch.setBoolPref("mail.spam.logging.enabled", pref.getBoolPref(prefix + "spamLoggingEnabled"));
1654 if (gPrefBranch.prefHasUserValue(prefix + "markAsReadOnSpam"))
1655 gPrefBranch.setBoolPref("mail.spam.markAsReadOnSpam", pref.getBoolPref(prefix + "markAsReadOnSpam"));
1656 }
1657 // bump the version so we don't bother doing this again.
1658 gPrefBranch.setIntPref("mail.spam.version", 1);
1659 }
1660 }
1661
1662 // The first time a user runs a build that supports folder views, pre-populate the favorite folders list
1663 // with the existing INBOX folders.
MigrateFolderViews
1664 function MigrateFolderViews()
1665 {
1666 var folderViewsVersion = gPrefBranch.getIntPref("mail.folder.views.version");
1667 if (!folderViewsVersion)
1668 {
1669 var servers = accountManager.allServers;
1670 var server;
1671 var inbox;
1672 for (var index = 0; index < servers.Count(); index++)
1673 {
1674 server = servers.QueryElementAt(index, Components.interfaces.nsIMsgIncomingServer);
1675 if (server)
1676 {
1677 inbox = GetInboxFolder(server);
1678 if (inbox)
1679 inbox.setFlag(MSG_FOLDER_FLAG_FAVORITE);
1680 }
1681 }
1682 gPrefBranch.setIntPref("mail.folder.views.version", 1);
1683 }
1684 }
1685
1686 // Thunderbird has been storing old attachment download meta data in downloads.rdf
1687 // even though there was no way to show or clean up this data. Now that we are using
1688 // the new download manager in toolkit, we don't want to present this old data.
1689 // To migrate to the new download manager, remove downloads.rdf.
MigrateAttachmentDownloadStore
1690 function MigrateAttachmentDownloadStore()
1691 {
1692 var attachmentStoreVersion = gPrefBranch.getIntPref("mail.attachment.store.version");
1693 if (!attachmentStoreVersion)
1694 {
1695 var dirService = Components.classes["@mozilla.org/file/directory_service;1"]
1696 .getService(Components.interfaces.nsIProperties);
1697 var downloadsFile = dirService.get("DLoads", Components.interfaces.nsIFile);
1698 if (downloadsFile && downloadsFile.exists())
1699 downloadsFile.remove(false);
1700
1701 // bump the version so we don't bother doing this again.
1702 gPrefBranch.setIntPref("mail.attachment.store.version", 1);
1703 }
1704 }