diff --git a/mozilla/mailnews/base/resources/content/msgMail3PaneWindow.js b/mozilla/mailnews/base/resources/content/msgMail3PaneWindow.js index 934f67e0295..dd676fa1541 100644 --- a/mozilla/mailnews/base/resources/content/msgMail3PaneWindow.js +++ b/mozilla/mailnews/base/resources/content/msgMail3PaneWindow.js @@ -396,7 +396,7 @@ function HandleDeleteOrMoveMsgCompleted(folder) else { if (gNextMessageViewIndexAfterDelete != nsMsgViewIndex_None) { - viewSize = treeView.rowCount; + var viewSize = treeView.rowCount; if (gNextMessageViewIndexAfterDelete >= viewSize) { if (viewSize > 0) @@ -405,7 +405,7 @@ function HandleDeleteOrMoveMsgCompleted(folder) { gNextMessageViewIndexAfterDelete = nsMsgViewIndex_None; - // there is nothing to select viewSize is 0 + // there is nothing to select since viewSize is 0 treeSelection.clearSelection(); setTitleFromFolder(folder, null); ClearMessagePane(); diff --git a/mozilla/mailnews/base/resources/content/searchBar.js b/mozilla/mailnews/base/resources/content/searchBar.js index 34c09166e73..b01cad6941f 100644 --- a/mozilla/mailnews/base/resources/content/searchBar.js +++ b/mozilla/mailnews/base/resources/content/searchBar.js @@ -27,7 +27,6 @@ var gSearchSession = null; var gPreQuickSearchView = null; var gSearchTimer = null; var gViewSearchListener; -var gNumOfSearchHits = 0; var gSearchBundle; var gStatusBar = null; var gSearchInProgress = false; @@ -36,34 +35,36 @@ var gClearButton = null; var gDefaultSearchViewTerms = null; var gQSViewIsDirty = false; +function SetQSStatusText(aNumHits) +{ + var statusMsg; + // if there are no hits, it means no matches were found in the search. + if (aNumHits == 0) + statusMsg = gSearchBundle.getString("searchFailureMessage"); + else + { + if (aNumHits == 1) + statusMsg = gSearchBundle.getString("searchSuccessMessage"); + else + statusMsg = gSearchBundle.getFormattedString("searchSuccessMessages", [aNumHits]); + } + + statusFeedback.showStatusString(statusMsg); +} + // nsIMsgSearchNotify object var gSearchNotificationListener = { onSearchHit: function(header, folder) { - gNumOfSearchHits++; + // XXX todo + // update status text? }, onSearchDone: function(status) { - - var statusMsg; - // if there are no hits, it means no matches were found in the search. - if (gNumOfSearchHits == 0) { - statusMsg = gSearchBundle.getString("searchFailureMessage"); - } - else - { - if (gNumOfSearchHits == 1) - statusMsg = gSearchBundle.getString("searchSuccessMessage"); - else - statusMsg = gSearchBundle.getFormattedString("searchSuccessMessages", [gNumOfSearchHits]); - - gNumOfSearchHits = 0; - } - + SetQSStatusText(gDBView.QueryInterface(Components.interfaces.nsITreeView).rowCount) statusFeedback.showProgress(0); - statusFeedback.showStatusString(statusMsg); gStatusBar.setAttribute("mode","normal"); gSearchInProgress = false; }, @@ -113,7 +114,7 @@ function initializeGlobalListeners() function createQuickSearchView() { - if(gDBView.viewType != nsMsgViewType.eShowQuickSearchResults) //otherwise we are already in quick search view + if (gDBView.viewType != nsMsgViewType.eShowQuickSearchResults) //otherwise we are already in quick search view { var treeView = gDBView.QueryInterface(Components.interfaces.nsITreeView); //clear selection treeView.selection.clearSelection(); diff --git a/mozilla/mailnews/base/search/resources/content/SearchDialog.js b/mozilla/mailnews/base/search/resources/content/SearchDialog.js index 67dc3b8e513..333cca83260 100644 --- a/mozilla/mailnews/base/search/resources/content/SearchDialog.js +++ b/mozilla/mailnews/base/search/resources/content/SearchDialog.js @@ -38,7 +38,6 @@ var gFolderDatasource; var gFolderPicker; var gStatusBar = null; var gStatusFeedback = new nsMsgStatusFeedback; -var gNumOfSearchHits = 0; var RDF; var gSearchBundle; var gNextMessageViewIndexAfterDelete = -2; @@ -115,42 +114,50 @@ var nsSearchResultsController = } } +function UpdateMailSearch(caller) +{ + //dump("XXX update mail-search " + caller + "\n"); + document.commandDispatcher.updateCommands('mail-search'); +} + +function SetAdvancedSearchStatusText(aNumHits) +{ + var statusMsg; + // if there are no hits, it means no matches were found in the search. + if (aNumHits == 0) + statusMsg = gSearchBundle.getString("searchFailureMessage"); + else + { + if (aNumHits == 1) + statusMsg = gSearchBundle.getString("searchSuccessMessage"); + else + statusMsg = gSearchBundle.getFormattedString("searchSuccessMessages", [aNumHits]); + } + + gStatusFeedback.showStatusString(statusMsg); +} + // nsIMsgSearchNotify object var gSearchNotificationListener = { onSearchHit: function(header, folder) { - gNumOfSearchHits++; + // XXX TODO + // update status text? }, onSearchDone: function(status) { gSearchStopButton.setAttribute("label", gSearchBundle.getString("labelForSearchButton")); - - var statusMsg; - // if there are no hits, it means no matches were found in the search. - if (gNumOfSearchHits == 0) { - statusMsg = gSearchBundle.getString("searchFailureMessage"); - } - else - { - if (gNumOfSearchHits == 1) - statusMsg = gSearchBundle.getString("searchSuccessMessage"); - else - statusMsg = gSearchBundle.getFormattedString("searchSuccessMessages", [gNumOfSearchHits]); - - gNumOfSearchHits = 0; - } - + SetAdvancedSearchStatusText(gSearchView.QueryInterface(Components.interfaces.nsITreeView).rowCount); gStatusFeedback.showProgress(0); - gStatusFeedback.showStatusString(statusMsg); gStatusBar.setAttribute("mode","normal"); }, onNewSearch: function() { gSearchStopButton.setAttribute("label", gSearchBundle.getString("labelForStopButton")); - document.commandDispatcher.updateCommands('mail-search'); + UpdateMailSearch("new-search"); gStatusFeedback.showProgress(0); gStatusFeedback.showStatusString(gSearchBundle.getString("searchingMessage")); gStatusBar.setAttribute("mode","undetermined"); @@ -216,8 +223,8 @@ function searchOnLoad() selectFolder(window.arguments[0].folder); onMore(null); - document.commandDispatcher.updateCommands('mail-search'); - + UpdateMailSearch("onload"); + // hide and remove these columns from the column picker. you can't thread search results HideSearchColumn("threadCol"); // since you can't thread search results HideSearchColumn("totalCol"); // since you can't thread search results @@ -545,49 +552,103 @@ function MsgDeleteSelectedMessages() function SetNextMessageAfterDelete() { - gNextMessageViewIndexAfterDelete = gSearchView.msgToSelectAfterDelete; + gNextMessageViewIndexAfterDelete = gSearchView.msgToSelectAfterDelete; } function HandleDeleteOrMoveMessageFailed(folder) { - gNextMessageViewIndexAfterDelete = nsMsgViewIndex_None; + gNextMessageViewIndexAfterDelete = -2; } - function HandleDeleteOrMoveMessageCompleted(folder) { - var treeView = gSearchView.QueryInterface(Components.interfaces.nsITreeView); - var treeSelection = treeView.selection; - viewSize = treeView.rowCount; + var treeView = gSearchView.QueryInterface(Components.interfaces.nsITreeView); + var treeSelection = treeView.selection; + var viewSize = treeView.rowCount; - if (gNextMessageViewIndexAfterDelete != nsMsgViewIndex_None && gNextMessageViewIndexAfterDelete >= viewSize) - { - if (viewSize > 0) - gNextMessageViewIndexAfterDelete = viewSize - 1; - else - { - gNextMessageViewIndexAfterDelete = nsMsgViewIndex_None; - //clear the selection - treeSelection.clearSelection(); - } - } + 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 three 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 #185147 + treeSelection.clearSelection(); - // 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) { - treeSelection.select(gNextMessageViewIndexAfterDelete); - // since gNextMessageViewIndexAfterDelete probably has the same value - // as the last index we had selected, the tree isn't generating a new - // selectionChanged notification for the tree view. So we aren't loading the - // next message. to fix this, force the selection changed update. - if (treeView) - treeView.selectionChanged(); + UpdateMailSearch("delete from another view, 0 rows now selected"); + } + else if (treeSelection.count == 1) { + // this can happen if you had two messages selected + // in the search results pane, and you deleted one of them from another view + // (like the view in the stand alone msg window or the three pane) + // 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(gNextMessageViewIndexAfterDelete); - } + EnsureRowInThreadTreeIsVisible(startIndex.value); + UpdateMailSearch("delete from another view, 1 row now selected"); + } + else { + // this can happen if you have more than 2 messages selected + // in the search results pane, and you deleted one of them from another view + // (like the view in the stand alone msg window or the three pane) + // since multiple messages are still selected, do nothing. + } + } + else { + if (gNextMessageViewIndexAfterDelete != nsMsgViewIndex_None && gNextMessageViewIndexAfterDelete >= viewSize) + { + if (viewSize > 0) + gNextMessageViewIndexAfterDelete = viewSize - 1; + else + { + gNextMessageViewIndexAfterDelete = nsMsgViewIndex_None; + // there is nothing to select since viewSize is 0 + treeSelection.clearSelection(); + + UpdateMailSearch("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) + { + treeSelection.select(gNextMessageViewIndexAfterDelete); + // since gNextMessageViewIndexAfterDelete probably has the same value + // as the last index we had selected, the tree isn't generating a new + // selectionChanged notification for the tree view. So we aren't loading the + // next message. to fix this, force the selection changed update. + if (treeView) + treeView.selectionChanged(); + + EnsureRowInThreadTreeIsVisible(gNextMessageViewIndexAfterDelete); + + // 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? + UpdateMailSearch("delete from current view, at least one row selected"); + } + } + + // default value after delete/move/copy is over + gNextMessageViewIndexAfterDelete = -2; + + // something might have been deleted, so update the status text + SetAdvancedSearchStatusText(viewSize); } function MoveMessageInSearch(destFolder)