msgmail3panewindow.js

来自「现在很火的邮件客户端软件thunderbird的源码」· JavaScript 代码 · 共 1,852 行 · 第 1/5 页

JS
1,852
字号
      var folderResource = GetFolderResource(folderTree, index);      if (folderTree.view.getLevel(index) == 0)      {        // (Imap/Nntp/Pop) Account item.        folderResource.QueryInterface(Components.interfaces.nsIMsgFolder)                      .server.performExpand(msgWindow);      }      else if (folderResource instanceof Components.interfaces.nsIMsgImapMailFolder)      {        // Imap message folder item.        folderResource.performExpand(msgWindow);      }    },    onCycleHeader: function(colID, elt)    {    },    onCycleCell: function(row, colID)    {    },    onSelectionChanged: function()    {    },    onPerformAction: function(action)    {    },    onPerformActionOnRow: function(action, row)    {    },    onPerformActionOnCell: function(action, row, col)    {    }}function HandleDeleteOrMoveMsgFailed(folder){  gDBView.onDeleteCompleted(false);  if(IsCurrentLoadedFolder(folder)) {    if(gNextMessageAfterDelete) {      gNextMessageAfterDelete = null;      gNextMessageViewIndexAfterDelete = -2;    }  }  // fix me???  // ThreadPaneSelectionChange(true);}// WARNING// this is a fragile and complicated function.// be careful when hacking on it.// don't forget about things like different imap // delete models, multiple views (from multiple thread panes, // search windows, stand alone message windows)function HandleDeleteOrMoveMsgCompleted(folder){  // you might not have a db view.  this can happen if  // biff fires when the 3 pane is set to account central.  if (!gDBView)    return;  gDBView.onDeleteCompleted(true);  if (!IsCurrentLoadedFolder(folder)) {    // default value after delete/move/copy is over    gNextMessageViewIndexAfterDelete = -2;    return;  }  var treeView = gDBView.QueryInterface(Components.interfaces.nsITreeView);  var treeSelection = treeView.selection;            if (gNextMessageViewIndexAfterDelete == -2) {    // a move or delete can cause our selection can change underneath us.    // this can happen when the user    // deletes message from the stand alone msg window    // or the search view, or another 3 pane    if (treeSelection.count == 0) {      // this can happen if you double clicked a message      // in the thread pane, and deleted it from the stand alone msg window      // see bug #172392      treeSelection.clearSelection();      setTitleFromFolder(folder, null);      ClearMessagePane();      UpdateMailToolbar("delete from another view, 0 rows now selected");    }    else if (treeSelection.count == 1) {      // this can happen if you had two messages selected      // in the thread pane, and you deleted one of them from another view      // (like the view in the stand alone msg window)      // since one item is selected, we should load it.      var startIndex = {};      var endIndex = {};      treeSelection.getRangeAt(0, startIndex, endIndex);              // select the selected item, so we'll load it      treeSelection.select(startIndex.value);       treeView.selectionChanged();      EnsureRowInThreadTreeIsVisible(startIndex.value);       UpdateMailToolbar("delete from another view, 1 row now selected");    }    else {      // this can happen if you have more than 2 messages selected      // in the thread pane, and you deleted one of them from another view      // (like the view in the stand alone msg window)      // since multiple messages are still selected, do nothing.    }  }  else {    if (gNextMessageViewIndexAfterDelete != nsMsgViewIndex_None)     {      var viewSize = treeView.rowCount;      if (gNextMessageViewIndexAfterDelete >= viewSize)       {        if (viewSize > 0)          gNextMessageViewIndexAfterDelete = viewSize - 1;        else        {                     gNextMessageViewIndexAfterDelete = nsMsgViewIndex_None;          // there is nothing to select since viewSize is 0          treeSelection.clearSelection();          setTitleFromFolder(folder, null);          ClearMessagePane();          UpdateMailToolbar("delete from current view, 0 rows left");        }      }    }    // if we are about to set the selection with a new element then DON'T clear    // the selection then add the next message to select. This just generates    // an extra round of command updating notifications that we are trying to    // optimize away.    if (gNextMessageViewIndexAfterDelete != nsMsgViewIndex_None)     {      // when deleting a message we don't update the commands       // when the selection goes to 0      // (we have a hack in nsMsgDBView which prevents that update)       // so there is no need to      // update commands when we select the next message after the delete;       // the commands already      // have the right update state...      gDBView.suppressCommandUpdating = true;      // This check makes sure that the tree does not perform a      // selection on a non selected row (row < 0), else assertions will      // be thrown.      if (gNextMessageViewIndexAfterDelete >= 0)        treeSelection.select(gNextMessageViewIndexAfterDelete);              // if gNextMessageViewIndexAfterDelete has the same value       // as the last index we had selected, the tree won't generate a      // selectionChanged notification for the tree view. So force a manual      // selection changed call.       // (don't worry it's cheap if we end up calling it twice).      if (treeView)        treeView.selectionChanged();      EnsureRowInThreadTreeIsVisible(gNextMessageViewIndexAfterDelete);       gDBView.suppressCommandUpdating = false;      // hook for extra toolbar items      // XXX TODO      // I think there is a bug in the suppression code above.      // what if I have two rows selected, and I hit delete,       // and so we load the next row.      // what if I have commands that only enable where       // exactly one row is selected?      UpdateMailToolbar("delete from current view, at least one row selected");    }  }  // default value after delete/move/copy is over  gNextMessageViewIndexAfterDelete = -2;}function HandleCompactCompleted(folder){  if (folder)  {    var resource = folder.QueryInterface(Components.interfaces.nsIRDFResource);    if (resource)    {      var uri = resource.Value;      var msgFolder = msgWindow.openFolder;      if (msgFolder && uri == msgFolder.URI)      {        var msgdb = msgFolder.getMsgDatabase(msgWindow);        if (msgdb)        {          var dbFolderInfo = msgdb.dBFolderInfo;          sortType = dbFolderInfo.sortType;          sortOrder = dbFolderInfo.sortOrder;          viewFlags = dbFolderInfo.viewFlags;          viewType = dbFolderInfo.viewType;          dbFolderInfo = null;        }                RerootFolder(uri, msgFolder, viewType, viewFlags, sortType, sortOrder);        LoadCurrentlyDisplayedMessage();      }    }  }}function LoadCurrentlyDisplayedMessage(){  if (gCurrentlyDisplayedMessage != nsMsgViewIndex_None)  {    var treeView = gDBView.QueryInterface(Components.interfaces.nsITreeView);    var treeSelection = treeView.selection;    treeSelection.select(gCurrentlyDisplayedMessage);    if (treeView)      treeView.selectionChanged();    EnsureRowInThreadTreeIsVisible(gCurrentlyDisplayedMessage);    SetFocusThreadPane();    gCurrentlyDisplayedMessage = nsMsgViewIndex_None; //reset  }}function IsCurrentLoadedFolder(folder){  var msgfolder = folder.QueryInterface(Components.interfaces.nsIMsgFolder);  if(msgfolder)  {    var folderResource = msgfolder.QueryInterface(Components.interfaces.nsIRDFResource);    if(folderResource)    {      var folderURI = folderResource.Value;      var currentLoadedFolder = GetThreadPaneFolder();      if (currentLoadedFolder.flags & MSG_FOLDER_FLAG_VIRTUAL)      {        var msgDatabase = currentLoadedFolder.getMsgDatabase(msgWindow);        var dbFolderInfo = msgDatabase.dBFolderInfo;        var srchFolderUri = dbFolderInfo.getCharPtrProperty("searchFolderUri");        var re = new RegExp("^" + folderURI + "$|^" + folderURI + "\||\|" + folderURI + "$|\|" + folderURI +"\|");        var retval = (currentLoadedFolder.URI.match(re));        return retval;      }      var currentURI = currentLoadedFolder.URI;      return(currentURI == folderURI);    }  }  return false;}function ServerContainsFolder(server, folder){  if (!folder || !server)    return false;  return server.equals(folder.server);}function SelectServer(server){  SelectFolder(server.rootFolder.URI);}// we have this incoming server listener in case we need to// alter the folder pane selection when a server is removed// or changed (currently, when the real username or real hostname change)var gThreePaneIncomingServerListener = {    onServerLoaded: function(server) {},    onServerUnloaded: function(server) {      var selectedFolders = GetSelectedMsgFolders();      for (var i = 0; i < selectedFolders.length; i++) {        if (ServerContainsFolder(server, selectedFolders[i])) {          SelectServer(accountManager.defaultAccount.incomingServer);          // we've made a new selection, we're done          return;        }      }         // if nothing is selected at this point, better go select the default      // this could happen if nothing was selected when the server was removed      selectedFolders = GetSelectedMsgFolders();      if (selectedFolders.length == 0) {        SelectServer(accountManager.defaultAccount.incomingServer);      }    },    onServerChanged: function(server) {      // if the current selected folder is on the server that changed      // and that server is an imap or news server,       // we need to update the selection.       // on those server types, we'll be reconnecting to the server      // and our currently selected folder will need to be reloaded      // or worse, be invalid.      if (server.type != "imap" && server.type !="nntp")        return;      var selectedFolders = GetSelectedMsgFolders();      for (var i = 0; i < selectedFolders.length; i++) {        // if the selected item is a server, we don't have to update        // the selection        if (!(selectedFolders[i].isServer) && ServerContainsFolder(server, selectedFolders[i])) {          SelectServer(server);          // we've made a new selection, we're done          return;        }      }    }}// aMsgWindowInitialized: false if we are calling from the onload handler, otherwise truefunction UpdateMailPaneConfig(aMsgWindowInitialized) {  var paneConfig = pref.getIntPref("mail.pane_config.dynamic");    if (paneConfig == kStandardPaneConfig)    document.getElementById('messagepanebox').setAttribute('flex', 1);  else     document.getElementById('messagepanebox').removeAttribute('flex');        // don't do anything if we are already in the correct configuration  if (paneConfig == gCurrentPaneConfig)    return;  var mailContentWrapper = document.getElementById("mailContentWrapper");  var messagesBox = document.getElementById("messagesBox");  var messengerBox = document.getElementById("messengerBox");  var messagePaneBox = GetMessagePane();  var msgPaneReRooted = false;  var threadPaneSplitter = GetThreadAndMessagePaneSplitter();  // the only element we need to re-root is the message pane.  var desiredMsgPaneParentId = (paneConfig == "0" || paneConfig == "2" || paneConfig == "3") ? "messagesBox" : "mailContentWrapper";  if (messagePaneBox.parentNode.id != desiredMsgPaneParentId)  {     var messagePaneParent = document.getElementById(messagePaneBox.parentNode.id);     messagePaneParent.removeChild(threadPaneSplitter);     messagePaneParent.removeChild(messagePaneBox);     var messagePaneNewParent = document.getElementById(desiredMsgPaneParentId);     messagePaneNewParent.appendChild(threadPaneSplitter);      messagePaneNewParent.appendChild(messagePaneBox);      msgPaneReRooted = true;  }    /* this code doesn't work yet, see the comment below about kWideThreadPaneConfig  if (gCurrentPaneConfig == kWideThreadPaneConfig)  {       threadPaneSplitter.setAttribute("orient", "vertical");    mailContentWrapper.setAttribute("orient", "horizontal");    mailContentWrapper.removeChild(threadPaneSplitter);    mailContentWrapper.removeChild(messagePaneBox);    messagesBox.insertBefore(threadPaneSplitter, messagesBox.firstChild);    messagesBox.insertBefore(messengerBox, messagesBox.firstChild);    messagePaneBox.removeAttribute("flex");    msgPaneReRooted = true;  }  */  // now for each config, handle any extra clean up to create that view (such as changing a box orientation)  if (paneConfig == kStandardPaneConfig) // standard 3-Pane Layout  {         threadPaneSplitter.setAttribute("orient", "vertical");

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?