From 9c0a34ecc8bd3281ea0dff9ff52bbcf8ecf5498a Mon Sep 17 00:00:00 2001 From: "gayatrib%netscape.com" Date: Sat, 24 Mar 2001 09:08:26 +0000 Subject: [PATCH] Implementing deleting/filing messages on single and multiple folders in search. Fixed regression introduced after merging performance branch that search does not display number of search hits. r=bhuvan,bienvenu. sr=bienvenu. git-svn-id: svn://10.0.0.236/trunk@90338 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/mailnews/base/public/nsIMsgFolder.idl | 3 +- .../search/public/nsIMsgSearchSession.idl | 3 + .../search/resources/content/SearchDialog.js | 164 +++++++- .../search/resources/content/SearchDialog.xul | 85 +++- .../resources/locale/en-US/SearchDialog.dtd | 3 + .../base/search/src/nsMsgSearchSession.cpp | 112 +++++- .../base/search/src/nsMsgSearchSession.h | 7 +- .../base/src/nsCopyMessageStreamListener.cpp | 2 +- mozilla/mailnews/base/src/nsMsgDBView.cpp | 48 ++- mozilla/mailnews/base/src/nsMsgDBView.h | 7 +- .../base/src/nsMsgFolderDataSource.cpp | 2 +- .../mailnews/base/src/nsMsgSearchDBView.cpp | 364 +++++++++++++++++- mozilla/mailnews/base/src/nsMsgSearchDBView.h | 28 +- .../mailnews/compose/src/nsMsgSendLater.cpp | 2 +- .../mailnews/imap/src/nsImapMailFolder.cpp | 11 +- mozilla/mailnews/imap/src/nsImapMailFolder.h | 4 +- .../mailnews/local/src/nsLocalMailFolder.cpp | 7 +- .../mailnews/local/src/nsLocalMailFolder.h | 3 +- mozilla/mailnews/news/src/nsNewsFolder.cpp | 3 +- mozilla/mailnews/news/src/nsNewsFolder.h | 3 +- 20 files changed, 820 insertions(+), 41 deletions(-) diff --git a/mozilla/mailnews/base/public/nsIMsgFolder.idl b/mozilla/mailnews/base/public/nsIMsgFolder.idl index 22b57367b90..0f2a319d6f5 100644 --- a/mozilla/mailnews/base/public/nsIMsgFolder.idl +++ b/mozilla/mailnews/base/public/nsIMsgFolder.idl @@ -279,7 +279,8 @@ const nsMsgBiffState nsMsgBiffState_Unknown = 2; // We dunno whether there is ne void deleteMessages(in nsISupportsArray message, in nsIMsgWindow msgWindow, - in boolean deleteStorage, in boolean isMove); + in boolean deleteStorage, in boolean isMove, + in nsIMsgCopyServiceListener listener); void copyMessages(in nsIMsgFolder srcFolder, in nsISupportsArray messages, in boolean isMove, in nsIMsgWindow msgWindow, diff --git a/mozilla/mailnews/base/search/public/nsIMsgSearchSession.idl b/mozilla/mailnews/base/search/public/nsIMsgSearchSession.idl index 870ac9df80c..f30c4e0f39b 100644 --- a/mozilla/mailnews/base/search/public/nsIMsgSearchSession.idl +++ b/mozilla/mailnews/base/search/public/nsIMsgSearchSession.idl @@ -23,6 +23,7 @@ #include "nsISupports.idl" #include "nsMsgSearchCore.idl" #include "nsIMsgSearchValue.idl" +#include "nsIFolderListener.idl" interface nsMsgResultElement; interface nsIMsgSearchAdapter; @@ -118,4 +119,6 @@ interface nsIMsgSearchSession : nsISupports { const long BooleanOR=0; const long BooleanAND=1; + void addFolderListener(in nsIFolderListener listener); + void removeFolderListener(in nsIFolderListener listener); }; diff --git a/mozilla/mailnews/base/search/resources/content/SearchDialog.js b/mozilla/mailnews/base/search/resources/content/SearchDialog.js index 9e4901c01c8..7136f19c945 100644 --- a/mozilla/mailnews/base/search/resources/content/SearchDialog.js +++ b/mozilla/mailnews/base/search/resources/content/SearchDialog.js @@ -39,14 +39,16 @@ var gStatusFeedback = new nsMsgStatusFeedback; var gNumOfSearchHits = 0; var RDF; var gSearchBundle; +var gNextMessageViewIndexAfterDelete = -1; // Datasource search listener -- made global as it has to be registered // and unregistered in different functions. var gDataSourceSearchListener; var gViewSearchListener; -var gIsSearchHit = false; var gButton; +var gSearchSessionFolderListener; +var gMailSession; // Controller object for search results thread pane var nsSearchResultsController = @@ -55,6 +57,8 @@ var nsSearchResultsController = { switch(command) { case "cmd_open": + case "cmd_delete": + case "file_message_button": return true; default: return false; @@ -80,6 +84,10 @@ var nsSearchResultsController = MsgOpenSelectedMessages(gSearchView); return true; + case "cmd_delete": + MsgDeleteSelectedMessages(); + return true; + default: return false; } @@ -105,13 +113,17 @@ var gSearchNotificationListener = var statusMsg; // if there are no hits, it means no matches were found in the search. - if (!gIsSearchHit) { - gStatusFeedback.showStatusString(gSearchBundle.getString("searchFailureMessage")); + if (gNumOfSearchHits == 0) { + statusMsg = gSearchBundle.getString("searchFailureMessage"); } - else + else { - gStatusFeedback.showStatusString(gSearchBundle.getString("searchSuccessMessage")); - gIsSearchHit = false; + if (gNumOfSearchHits == 1) + statusMsg = gSearchBundle.getString("searchSuccessMessage"); + else + statusMsg = gSearchBundle.getFormattedString("searchSuccessMessages", [gNumOfSearchHits]); + + gNumOfSearchHits = 0; } gStatusFeedback.showProgress(100); @@ -132,6 +144,34 @@ var gSearchNotificationListener = } } +// the folderListener object +var gFolderListener = { + OnItemAdded: function(parentItem, item, view) {}, + + OnItemRemoved: function(parentItem, item, view){}, + + OnItemPropertyChanged: function(item, property, oldValue, newValue) {}, + + OnItemIntPropertyChanged: function(item, property, oldValue, newValue) {}, + + OnItemBoolPropertyChanged: function(item, property, oldValue, newValue) {}, + + OnItemUnicharPropertyChanged: function(item, property, oldValue, newValue){}, + OnItemPropertyFlagChanged: function(item, property, oldFlag, newFlag) {}, + + OnItemEvent: function(folder, event) { + var eventType = event.GetUnicode(); + + if (eventType == "DeleteOrMoveMsgCompleted") { + HandleDeleteOrMoveMessageCompleted(folder); + } + else if (eventType == "DeleteOrMoveMsgFailed") { + HandleDeleteOrMoveMessageFailed(folder); + } + + } +} + function searchOnLoad() { initializeSearchWidgets(); @@ -156,6 +196,12 @@ function searchOnUnload() gSearchSession.unregisterListener(gViewSearchListener); gSearchSession.unregisterListener(gSearchNotificationListener); + gMailSession.RemoveFolderListener(gSearchSessionFolderListener); + gSearchSession.removeFolderListener(gFolderListener); + + gSearchView.close(); + gSearchView = null; + // release this early because msgWindow holds a weak reference msgWindow.rootDocShell = null; } @@ -362,10 +408,14 @@ function setupDatasource() { // attributes about each message) gSearchSession = Components.classes[searchSessionContractID].createInstance(Components.interfaces.nsIMsgSearchSession); + gSearchSessionFolderListener = gSearchSession.QueryInterface(Components.interfaces.nsIFolderListener); + gMailSession = Components.classes[mailSessionContractID].getService(Components.interfaces.nsIMsgMailSession); + gMailSession.AddFolderListener(gSearchSessionFolderListener); // the datasource is a listener on the search results gViewSearchListener = gSearchView.QueryInterface(Components.interfaces.nsIMsgSearchNotify); gSearchSession.registerListener(gViewSearchListener); + gSearchSession.addFolderListener(gFolderListener); } @@ -450,3 +500,105 @@ function GetDBView() { return gSearchView; } + +function MsgDeleteSelectedMessages() +{ + // we don't delete news messages, we just return in that case + if (isNewsURI(gSearchView.getURIForViewIndex(0))) + return; + + // if mail messages delete + SetNextMessageAfterDelete(); + gSearchView.doCommand(nsMsgViewCommandType.deleteMsg); +} + +function SetNextMessageAfterDelete() +{ + dump("setting next msg view index after delete to " + gSearchView.firstSelected + "\n"); + gNextMessageViewIndexAfterDelete = gSearchView.firstSelected; +} + +function HandleDeleteOrMoveMessageFailed(folder) +{ + gNextMessageViewIndexAfterDelete = -1; +} + + +function HandleDeleteOrMoveMessageCompleted(folder) +{ + if(gNextMessageViewIndexAfterDelete != -1) + { + var outlinerView = gSearchView.QueryInterface(Components.interfaces.nsIOutlinerView); + var outlinerSelection = outlinerView.selection; + viewSize = outlinerView.rowCount; + + if (gNextMessageViewIndexAfterDelete >= viewSize) + { + if (viewSize > 0) + gNextMessageViewIndexAfterDelete = viewSize - 1; + else + gNextMessageViewIndexAfterDelete = -1; + } + + // 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 != -1) { + outlinerSelection.select(gNextMessageViewIndexAfterDelete); + // since gNextMessageViewIndexAfterDelete probably has the same value + // as the last index we had selected, the outliner isn't generating a new + // selectionChanged notification for the outliner view. So we aren't loading the + // next message. to fix this, force the selection changed update. + var outlinerView = gSearchView.QueryInterface(Components.interfaces.nsIOutlinerView); + if (outlinerView) + outlinerView.selectionChanged(); + + EnsureRowInThreadOutlinerIsVisible(gNextMessageViewIndexAfterDelete); + } + else + outlinerSelection.clearSelection(); /* clear selection in either case */ + + gNextMessageViewIndexAfterDelete = -1; + } +} + +function SetDatasources() +{ + dump("XXX SetDatasources\n"); + + var button = document.getElementById("fileMessageButton"); + var datasourceContractIDPrefix = "@mozilla.org/rdf/datasource;1?name="; + var accountManagerDSContractID = datasourceContractIDPrefix + "msgaccountmanager"; + var folderDSContractID = datasourceContractIDPrefix + "mailnewsfolders"; + var accountManagerDataSource = Components.classes[accountManagerDSContractID].createInstance(); + var folderDataSource = Components.classes[folderDSContractID].createInstance(); + accountManagerDataSource = accountManagerDataSource.QueryInterface(Components.interfaces.nsIRDFDataSource); + folderDataSource = folderDataSource.QueryInterface(Components.interfaces.nsIRDFDataSource); + button.database.AddDataSource(accountManagerDataSource); + button.database.AddDataSource(folderDataSource); + button.setAttribute('ref', 'msgaccounts:/'); +} + +function MoveMessageInSearch(destFolder) +{ + try { + // get the msg folder we're moving messages into + destUri = destFolder.getAttribute('id'); + destResource = RDF.GetResource(destUri); + + destMsgFolder = destResource.QueryInterface(Components.interfaces.nsIMsgFolder); + + // we don't move news messages, we copy them + if (isNewsURI(gSearchView.getURIForViewIndex(0))) { + gSearchView.doCommandWithFolder(nsMsgViewCommandType.copyMessages, destMsgFolder); + } + else { + SetNextMessageAfterDelete(); + gSearchView.doCommandWithFolder(nsMsgViewCommandType.moveMessages, destMsgFolder); + } + } + catch (ex) { + dump("MsgMoveMessage failed: " + ex + "\n"); + } +} diff --git a/mozilla/mailnews/base/search/resources/content/SearchDialog.xul b/mozilla/mailnews/base/search/resources/content/SearchDialog.xul index f242ac89895..3fdae880fa8 100644 --- a/mozilla/mailnews/base/search/resources/content/SearchDialog.xul +++ b/mozilla/mailnews/base/search/resources/content/SearchDialog.xul @@ -32,7 +32,7 @@ Rights Reserved. -