Back to index

lightning-sunbird  0.9+nobinonly
nsMsgSearchDBView.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 2001
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   Seth Spitzer <sspitzer@netscape.com>
00024  *
00025  * Alternatively, the contents of this file may be used under the terms of
00026  * either of the GNU General Public License Version 2 or later (the "GPL"),
00027  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00028  * in which case the provisions of the GPL or the LGPL are applicable instead
00029  * of those above. If you wish to allow use of your version of this file only
00030  * under the terms of either the GPL or the LGPL, and not to allow others to
00031  * use your version of this file under the terms of the MPL, indicate your
00032  * decision by deleting the provisions above and replace them with the notice
00033  * and other provisions required by the GPL or the LGPL. If you do not delete
00034  * the provisions above, a recipient may use your version of this file under
00035  * the terms of any one of the MPL, the GPL or the LGPL.
00036  *
00037  * ***** END LICENSE BLOCK ***** */
00038 
00039 #include "msgCore.h"
00040 #include "nsMsgSearchDBView.h"
00041 #include "nsIMsgHdr.h"
00042 #include "nsIMsgThread.h"
00043 #include "nsQuickSort.h"
00044 #include "nsIDBFolderInfo.h"
00045 #include "nsXPIDLString.h"
00046 #include "nsMsgBaseCID.h"
00047 #include "nsIMsgCopyService.h"
00048 #include "nsICopyMsgStreamListener.h"
00049 #include "nsMsgUtils.h"
00050 #include "nsITreeColumns.h"
00051 #include "nsIMsgMessageService.h"
00052 
00053 nsMsgSearchDBView::nsMsgSearchDBView()
00054 {
00055   // don't try to display messages for the search pane.
00056   mSuppressMsgDisplay = PR_TRUE;
00057 }
00058 
00059 nsMsgSearchDBView::~nsMsgSearchDBView()
00060 {      
00061 }
00062 
00063 NS_IMPL_ISUPPORTS_INHERITED3(nsMsgSearchDBView, nsMsgDBView, nsIMsgDBView, nsIMsgCopyServiceListener, nsIMsgSearchNotify)
00064 
00065 NS_IMETHODIMP nsMsgSearchDBView::Open(nsIMsgFolder *folder, nsMsgViewSortTypeValue sortType, nsMsgViewSortOrderValue sortOrder, nsMsgViewFlagsTypeValue viewFlags, PRInt32 *pCount)
00066 {
00067     nsresult rv;
00068     m_folders = do_CreateInstance(NS_SUPPORTSARRAY_CONTRACTID, &rv);
00069     NS_ENSURE_SUCCESS(rv, rv);
00070 
00071     rv = nsMsgDBView::Open(folder, sortType, sortOrder, viewFlags, pCount);
00072     NS_ENSURE_SUCCESS(rv, rv);
00073 
00074     if (pCount)
00075       *pCount = 0;
00076     m_folder = nsnull;
00077     return rv;
00078 }
00079 
00080 NS_IMETHODIMP
00081 nsMsgSearchDBView::CopyDBView(nsMsgDBView *aNewMsgDBView, nsIMessenger *aMessengerInstance, 
00082                                        nsIMsgWindow *aMsgWindow, nsIMsgDBViewCommandUpdater *aCmdUpdater)
00083 {
00084   nsMsgDBView::CopyDBView(aNewMsgDBView, aMessengerInstance, aMsgWindow, aCmdUpdater);
00085   nsMsgSearchDBView* newMsgDBView = (nsMsgSearchDBView *) aNewMsgDBView;
00086 
00087   // now copy all of our private member data
00088   newMsgDBView->mDestFolder = mDestFolder;
00089   newMsgDBView->mCommand = mCommand;
00090   newMsgDBView->mTotalIndices = mTotalIndices;
00091   newMsgDBView->mCurIndex = mCurIndex; 
00092 
00093   if (m_folders)
00094     m_folders->Clone(getter_AddRefs(newMsgDBView->m_folders));
00095 
00096   if (m_hdrsForEachFolder)
00097     m_hdrsForEachFolder->Clone(getter_AddRefs(newMsgDBView->m_hdrsForEachFolder));
00098 
00099   if (m_copyListenerList)
00100     m_copyListenerList->Clone(getter_AddRefs(newMsgDBView->m_copyListenerList));
00101 
00102   if (m_uniqueFoldersSelected)
00103     m_uniqueFoldersSelected->Clone(getter_AddRefs(newMsgDBView->m_uniqueFoldersSelected));
00104 
00105 
00106   PRInt32 count = m_dbToUseList.Count(); 
00107   for(PRInt32 i = 0; i < count; i++)
00108   {
00109     newMsgDBView->m_dbToUseList.AppendObject(m_dbToUseList[i]);
00110     // register the new view with the database so it gets notifications
00111     m_dbToUseList[i]->AddListener(newMsgDBView);
00112   }
00113 
00114   // nsUInt32Array* mTestIndices;
00115 
00116   return NS_OK;
00117 }
00118 
00119 NS_IMETHODIMP nsMsgSearchDBView::Close()
00120 {
00121   PRInt32 count = m_dbToUseList.Count();
00122   
00123   for(PRInt32 i = 0; i < count; i++)
00124     m_dbToUseList[i]->RemoveListener(this);
00125 
00126   m_dbToUseList.Clear();
00127 
00128   return NS_OK;
00129 }
00130 
00131 NS_IMETHODIMP nsMsgSearchDBView::GetCellText(PRInt32 aRow, nsITreeColumn* aCol, nsAString& aValue)
00132 {
00133   const PRUnichar* colID;
00134   aCol->GetIdConst(&colID);
00135   if (colID[0] == 'l' && colID[1] == 'o') // location, need to check for "lo" not just "l" to avoid "label" column
00136   {
00137     // XXX fix me by converting Fetch* to take an nsAString& parameter
00138     nsXPIDLString valueText;
00139     nsresult rv = FetchLocation(aRow, getter_Copies(valueText));
00140     aValue.Assign(valueText);
00141     return rv;
00142   }
00143   else
00144     return nsMsgDBView::GetCellText(aRow, aCol, aValue);
00145 }
00146 
00147 nsresult nsMsgSearchDBView::FetchLocation(PRInt32 aRow, PRUnichar ** aLocationString)
00148 {
00149   nsCOMPtr <nsIMsgFolder> folder;
00150   nsresult rv = GetFolderForViewIndex(aRow, getter_AddRefs(folder));
00151   NS_ENSURE_SUCCESS(rv,rv);
00152 
00153   rv = folder->GetPrettiestName(aLocationString);
00154   NS_ENSURE_SUCCESS(rv,rv);
00155   return NS_OK;
00156 }
00157 
00158 nsresult nsMsgSearchDBView::OnNewHeader(nsIMsgDBHdr *newHdr, nsMsgKey aParentKey, PRBool /*ensureListed*/)
00159 {
00160    return NS_OK;
00161 }
00162 
00163 nsresult nsMsgSearchDBView::GetMsgHdrForViewIndex(nsMsgViewIndex index, nsIMsgDBHdr **msgHdr)
00164 {
00165   nsresult rv = NS_MSG_INVALID_DBVIEW_INDEX;
00166   nsCOMPtr<nsIMsgFolder> folder = do_QueryElementAt(m_folders, index);
00167   if (folder)
00168     {
00169       nsCOMPtr <nsIMsgDatabase> db;
00170       rv = folder->GetMsgDatabase(mMsgWindow, getter_AddRefs(db));
00171       NS_ENSURE_SUCCESS(rv, rv);
00172       if (db)
00173         rv = db->GetMsgHdrForKey(m_keys.GetAt(index), msgHdr);
00174     }
00175   return rv;
00176 }
00177 
00178 NS_IMETHODIMP nsMsgSearchDBView::GetFolderForViewIndex(nsMsgViewIndex index, nsIMsgFolder **aFolder)
00179 {
00180   return m_folders->QueryElementAt(index, NS_GET_IID(nsIMsgFolder), (void **) aFolder);
00181 }
00182 
00183 nsresult nsMsgSearchDBView::GetDBForViewIndex(nsMsgViewIndex index, nsIMsgDatabase **db)
00184 {
00185   nsCOMPtr <nsIMsgFolder> aFolder;
00186   GetFolderForViewIndex(index, getter_AddRefs(aFolder));
00187   if (aFolder)
00188     return aFolder->GetMsgDatabase(nsnull, db);
00189   else
00190     return NS_MSG_INVALID_DBVIEW_INDEX;
00191 }
00192 
00193 nsresult nsMsgSearchDBView::AddHdrFromFolder(nsIMsgDBHdr *msgHdr, nsISupports *folder)
00194 {
00195   m_folders->AppendElement(folder);
00196   nsMsgKey msgKey;
00197   PRUint32 msgFlags;
00198   msgHdr->GetMessageKey(&msgKey);
00199   // nsMsgKey_None means it's not a valid hdr.
00200   if (msgKey != nsMsgKey_None)
00201   {
00202     msgHdr->GetFlags(&msgFlags);
00203     m_keys.Add(msgKey);
00204     m_levels.Add(0);
00205     m_flags.Add(msgFlags);
00206     
00207     // this needs to be called after we add the key, since RowCountChanged() will call our GetRowCount()
00208     if (mTree)
00209       mTree->RowCountChanged(GetSize() - 1, 1);
00210   }
00211   return NS_OK;
00212   }
00213 
00214 NS_IMETHODIMP
00215 nsMsgSearchDBView::OnSearchHit(nsIMsgDBHdr* aMsgHdr, nsIMsgFolder *folder)
00216 {
00217   NS_ENSURE_ARG(aMsgHdr);
00218   NS_ENSURE_ARG(folder);
00219 
00220   nsCOMPtr <nsISupports> supports = do_QueryInterface(folder);
00221   if (m_folders->IndexOf(supports) < 0 ) //do this just for new folder
00222   {
00223     nsCOMPtr<nsIMsgDatabase> dbToUse;
00224     nsCOMPtr<nsIDBFolderInfo> folderInfo;
00225     folder->GetDBFolderInfoAndDB(getter_AddRefs(folderInfo), getter_AddRefs(dbToUse));
00226     if (dbToUse)
00227     {
00228       dbToUse->AddListener(this);
00229       m_dbToUseList.AppendObject(dbToUse);
00230     }
00231   }
00232 
00233   return AddHdrFromFolder(aMsgHdr, supports);
00234 }
00235 
00236 NS_IMETHODIMP
00237 nsMsgSearchDBView::OnSearchDone(nsresult status)
00238 {
00239   //we want to set imap delete model once the search is over because setting next
00240   //message after deletion will happen before deleting the message and search scope
00241   //can change with every search.
00242   mDeleteModel = nsMsgImapDeleteModels::MoveToTrash;  //set to default in case it is non-imap folder
00243   nsCOMPtr <nsIMsgFolder> curFolder = do_QueryElementAt(m_folders, 0);
00244   if (curFolder)   
00245     GetImapDeleteModel(curFolder);
00246   return NS_OK;
00247 }
00248 
00249 
00250 // for now also acts as a way of resetting the search datasource
00251 NS_IMETHODIMP
00252 nsMsgSearchDBView::OnNewSearch()
00253 {
00254   PRInt32 oldSize = GetSize();
00255 
00256   PRInt32 count = m_dbToUseList.Count();
00257   for(PRInt32 j = 0; j < count; j++) 
00258     m_dbToUseList[j]->RemoveListener(this);
00259 
00260   m_dbToUseList.Clear();
00261 
00262   m_folders->Clear();
00263   m_keys.RemoveAll();
00264   m_levels.RemoveAll();
00265   m_flags.RemoveAll();
00266 
00267   // needs to happen after we remove the keys, since RowCountChanged() will call our GetRowCount()
00268   if (mTree) 
00269     mTree->RowCountChanged(0, -oldSize);
00270 
00271 //    mSearchResults->Clear();
00272     return NS_OK;
00273 }
00274 
00275 NS_IMETHODIMP nsMsgSearchDBView::OnAnnouncerGoingAway(nsIDBChangeAnnouncer *instigator)
00276 {
00277   nsIMsgDatabase *db = NS_STATIC_CAST(nsIMsgDatabase *, instigator);
00278   if (db)
00279   {
00280     db->RemoveListener(this);
00281     m_dbToUseList.RemoveObject(db);
00282   }
00283   return NS_OK;
00284 }
00285 
00286 nsresult nsMsgSearchDBView::GetFolders(nsISupportsArray **aFolders)
00287 {
00288   NS_ENSURE_ARG_POINTER(aFolders);
00289   NS_IF_ADDREF(*aFolders = m_folders);
00290   return NS_OK;
00291 }
00292 
00293 NS_IMETHODIMP 
00294 nsMsgSearchDBView::DoCommandWithFolder(nsMsgViewCommandTypeValue command, nsIMsgFolder *destFolder)
00295 {
00296     mCommand = command;
00297     mDestFolder = destFolder;
00298 
00299     return nsMsgDBView::DoCommandWithFolder(command, destFolder);
00300 }
00301 
00302 NS_IMETHODIMP nsMsgSearchDBView::DoCommand(nsMsgViewCommandTypeValue command)
00303 {
00304   mCommand = command;
00305   if (command == nsMsgViewCommandType::deleteMsg || command == nsMsgViewCommandType::deleteNoTrash
00306     || command == nsMsgViewCommandType::selectAll)
00307     return nsMsgDBView::DoCommand(command);
00308   nsresult rv = NS_OK;
00309   nsUInt32Array selection;
00310   GetSelectedIndices(&selection);
00311 
00312   nsMsgViewIndex *indices = selection.GetData();
00313   PRInt32 numIndices = selection.GetSize();
00314 
00315   // we need to break apart the selection by folders, and then call
00316   // ApplyCommandToIndices with the command and the indices in the
00317   // selection that are from that folder.
00318 
00319   nsUInt32Array *indexArrays;
00320   PRInt32 numArrays;
00321   rv = PartitionSelectionByFolder(indices, numIndices, &indexArrays, &numArrays);
00322   NS_ENSURE_SUCCESS(rv, rv);
00323   for (PRInt32 folderIndex = 0; folderIndex < numArrays; folderIndex++)
00324   {
00325     rv = ApplyCommandToIndices(command, indexArrays[folderIndex].GetData(), indexArrays[folderIndex].GetSize());
00326     NS_ENSURE_SUCCESS(rv, rv);
00327   }
00328 
00329   return rv;
00330 }
00331 
00332 // This method just removes the specified line from the view. It does
00333 // NOT delete it from the database.
00334 nsresult nsMsgSearchDBView::RemoveByIndex(nsMsgViewIndex index)
00335 {
00336     if (!IsValidIndex(index))
00337         return NS_MSG_INVALID_DBVIEW_INDEX;
00338 
00339     m_folders->RemoveElementAt(index);
00340     
00341     return nsMsgDBView::RemoveByIndex(index);
00342 }
00343 
00344 nsresult nsMsgSearchDBView::DeleteMessages(nsIMsgWindow *window, nsMsgViewIndex *indices, PRInt32 numIndices, PRBool deleteStorage)
00345 {
00346     nsresult rv;
00347     GetFoldersAndHdrsForSelection(indices, numIndices);
00348     if (mDeleteModel != nsMsgImapDeleteModels::MoveToTrash)
00349       deleteStorage = PR_TRUE;
00350     if (!deleteStorage)
00351       rv = ProcessRequestsInOneFolder(window);
00352     else
00353       rv = ProcessRequestsInAllFolders(window);
00354     return rv;
00355 }
00356 
00357 nsresult 
00358 nsMsgSearchDBView::CopyMessages(nsIMsgWindow *window, nsMsgViewIndex *indices, PRInt32 numIndices, PRBool isMove, nsIMsgFolder *destFolder)
00359 {
00360     nsresult rv;
00361     GetFoldersAndHdrsForSelection(indices, numIndices);
00362 
00363     rv = ProcessRequestsInOneFolder(window);
00364 
00365     return rv;
00366 }
00367 
00368 nsresult
00369 nsMsgSearchDBView::PartitionSelectionByFolder(nsMsgViewIndex *indices, PRInt32 numIndices, nsUInt32Array **indexArrays, PRInt32 *numArrays)
00370 {
00371   nsresult rv = NS_OK; 
00372   nsCOMPtr <nsISupportsArray> uniqueFoldersSelected = do_CreateInstance(NS_SUPPORTSARRAY_CONTRACTID, &rv);
00373   mCurIndex = 0;
00374 
00375   //Build unique folder list based on headers selected by the user
00376   for (nsMsgViewIndex i = 0; i < (nsMsgViewIndex) numIndices; i++)
00377   {
00378      nsCOMPtr <nsISupports> curSupports = getter_AddRefs(m_folders->ElementAt(indices[i]));
00379      if ( uniqueFoldersSelected->IndexOf(curSupports) < 0)
00380        uniqueFoldersSelected->AppendElement(curSupports); 
00381   }
00382 
00383   PRUint32 numFolders =0; 
00384   rv = uniqueFoldersSelected->Count(&numFolders);   //group the headers selected by each folder 
00385   *indexArrays = new nsUInt32Array[numFolders];
00386   *numArrays = numFolders;
00387   NS_ENSURE_TRUE(*indexArrays, NS_ERROR_OUT_OF_MEMORY);
00388   for (PRUint32 folderIndex=0; folderIndex < numFolders; folderIndex++)
00389   {
00390      nsCOMPtr <nsIMsgFolder> curFolder =
00391          do_QueryElementAt(uniqueFoldersSelected, folderIndex, &rv);
00392      for (nsMsgViewIndex i = 0; i < (nsMsgViewIndex) numIndices; i++) 
00393      {
00394        nsCOMPtr <nsIMsgFolder> msgFolder = do_QueryElementAt(m_folders,
00395                                                              indices[i], &rv);
00396        if (NS_SUCCEEDED(rv) && msgFolder && msgFolder == curFolder) 
00397           (*indexArrays)[folderIndex].Add(indices[i]);
00398      }
00399   }
00400   return rv;
00401 
00402 }
00403 
00404 nsresult
00405 nsMsgSearchDBView::GetFoldersAndHdrsForSelection(nsMsgViewIndex *indices, PRInt32 numIndices)
00406 {
00407   nsresult rv = NS_OK; 
00408   mCurIndex = 0;
00409                     //initialize and clear from the last usage
00410   if (!m_uniqueFoldersSelected)
00411   {
00412     m_uniqueFoldersSelected = do_CreateInstance(NS_SUPPORTSARRAY_CONTRACTID, &rv);
00413     NS_ENSURE_SUCCESS(rv, rv); 
00414   }
00415   else
00416     m_uniqueFoldersSelected->Clear();
00417   
00418   if (!m_hdrsForEachFolder)
00419   {
00420     m_hdrsForEachFolder = do_CreateInstance(NS_SUPPORTSARRAY_CONTRACTID, &rv);
00421     NS_ENSURE_SUCCESS(rv,rv);
00422   }
00423   else
00424     m_hdrsForEachFolder->Clear();
00425 
00426   //Build unique folder list based on headers selected by the user
00427   for (nsMsgViewIndex i = 0; i < (nsMsgViewIndex) numIndices; i++)
00428   {
00429      nsCOMPtr <nsISupports> curSupports = getter_AddRefs(m_folders->ElementAt(indices[i]));
00430      if ( m_uniqueFoldersSelected->IndexOf(curSupports) < 0)
00431        m_uniqueFoldersSelected->AppendElement(curSupports); 
00432   }
00433 
00434   PRUint32 numFolders =0; 
00435   rv = m_uniqueFoldersSelected->Count(&numFolders);   //group the headers selected by each folder 
00436   NS_ENSURE_SUCCESS(rv,rv);
00437   for (PRUint32 folderIndex=0; folderIndex < numFolders; folderIndex++)
00438   {
00439      nsCOMPtr <nsIMsgFolder> curFolder =
00440          do_QueryElementAt(m_uniqueFoldersSelected, folderIndex, &rv);
00441      nsCOMPtr <nsISupportsArray> msgHdrsForOneFolder;
00442      NS_NewISupportsArray(getter_AddRefs(msgHdrsForOneFolder));
00443      for (nsMsgViewIndex i = 0; i < (nsMsgViewIndex) numIndices; i++) 
00444      {
00445        nsCOMPtr <nsIMsgFolder> msgFolder = do_QueryElementAt(m_folders,
00446                                                              indices[i], &rv);
00447        if (NS_SUCCEEDED(rv) && msgFolder && msgFolder == curFolder) 
00448        {
00449           nsCOMPtr<nsIMsgDBHdr> msgHdr; 
00450           rv = GetMsgHdrForViewIndex(indices[i],getter_AddRefs(msgHdr));
00451           NS_ENSURE_SUCCESS(rv,rv);
00452           nsCOMPtr <nsISupports> hdrSupports = do_QueryInterface(msgHdr);
00453           msgHdrsForOneFolder->AppendElement(hdrSupports);
00454        }
00455      }
00456      nsCOMPtr <nsISupports> supports = do_QueryInterface(msgHdrsForOneFolder, &rv);
00457      if (NS_SUCCEEDED(rv) && supports)
00458        m_hdrsForEachFolder->AppendElement(supports);
00459   }
00460   return rv;
00461 
00462 
00463 }
00464 
00465 nsresult
00466 nsMsgSearchDBView::ApplyCommandToIndicesWithFolder(nsMsgViewCommandTypeValue command, nsMsgViewIndex* indices,
00467                     PRInt32 numIndices, nsIMsgFolder *destFolder)
00468 {
00469   mCommand = command;
00470   mDestFolder = destFolder;
00471   return nsMsgDBView::ApplyCommandToIndicesWithFolder(command, indices, numIndices, destFolder);
00472 }
00473 
00474 // nsIMsgCopyServiceListener methods
00475 
00476 NS_IMETHODIMP
00477 nsMsgSearchDBView::OnStartCopy()
00478 {
00479   return NS_OK;
00480 }
00481 
00482 NS_IMETHODIMP
00483 nsMsgSearchDBView::OnProgress(PRUint32 aProgress, PRUint32 aProgressMax)
00484 {
00485   return NS_OK;
00486 }
00487 
00488 // believe it or not, these next two are msgcopyservice listener methods!
00489 NS_IMETHODIMP
00490 nsMsgSearchDBView::SetMessageKey(PRUint32 aMessageKey)
00491 {
00492   return NS_OK;
00493 }
00494 
00495 NS_IMETHODIMP
00496 nsMsgSearchDBView::GetMessageId(nsCString* aMessageId)
00497 {
00498   return NS_OK;
00499 }
00500   
00501 NS_IMETHODIMP
00502 nsMsgSearchDBView::OnStopCopy(nsresult aStatus)
00503 {
00504     nsresult rv = NS_OK;
00505 
00506     if (NS_SUCCEEDED(aStatus))
00507     {
00508         mCurIndex++;
00509         PRUint32 numFolders =0;
00510         rv = m_uniqueFoldersSelected->Count(&numFolders);
00511         if ( mCurIndex < numFolders)
00512           ProcessRequestsInOneFolder(mMsgWindow);
00513     }
00514 
00515     return rv;
00516 }
00517 
00518 // end nsIMsgCopyServiceListener methods
00519 
00520 nsresult nsMsgSearchDBView::ProcessRequestsInOneFolder(nsIMsgWindow *window)
00521 {
00522     nsresult rv = NS_OK;
00523 
00524     nsCOMPtr<nsIMsgFolder> curFolder =
00525         do_QueryElementAt(m_uniqueFoldersSelected, mCurIndex);
00526     NS_ASSERTION(curFolder, "curFolder is null");
00527     nsCOMPtr <nsISupportsArray> messageArray =
00528         do_QueryElementAt(m_hdrsForEachFolder, mCurIndex);
00529     NS_ASSERTION(messageArray, "messageArray is null");
00530 
00531     // called for delete with trash, copy and move
00532     if (mCommand == nsMsgViewCommandType::deleteMsg)
00533         curFolder->DeleteMessages(messageArray, window, PR_FALSE /* delete storage */, PR_FALSE /* is move*/, this, PR_TRUE /*allowUndo*/);
00534     else 
00535     {
00536       NS_ASSERTION(!(curFolder == mDestFolder), "The source folder and the destination folder are the same");
00537       if (NS_SUCCEEDED(rv) && curFolder != mDestFolder)
00538       {
00539          nsCOMPtr<nsIMsgCopyService> copyService = do_GetService(NS_MSGCOPYSERVICE_CONTRACTID, &rv);
00540          if (NS_SUCCEEDED(rv))
00541          {
00542            if (mCommand == nsMsgViewCommandType::moveMessages)
00543              copyService->CopyMessages(curFolder, messageArray, mDestFolder, PR_TRUE /* isMove */, this, window, PR_TRUE /*allowUndo*/);
00544            else if (mCommand == nsMsgViewCommandType::copyMessages)
00545              copyService->CopyMessages(curFolder, messageArray, mDestFolder, PR_FALSE /* isMove */, this, window, PR_TRUE /*allowUndo*/);
00546          }
00547       }
00548     }
00549     return rv;
00550 }
00551 
00552 nsresult nsMsgSearchDBView::ProcessRequestsInAllFolders(nsIMsgWindow *window)
00553 {
00554     PRUint32 numFolders =0;
00555     nsresult rv = m_uniqueFoldersSelected->Count(&numFolders);
00556     NS_ENSURE_SUCCESS(rv,rv);
00557     for (PRUint32 folderIndex=0; folderIndex < numFolders; folderIndex++)
00558     {
00559        nsCOMPtr<nsIMsgFolder> curFolder =
00560            do_QueryElementAt(m_uniqueFoldersSelected, folderIndex);
00561        NS_ASSERTION (curFolder, "curFolder is null");
00562 
00563        nsCOMPtr <nsISupportsArray> messageArray =
00564            do_QueryElementAt(m_hdrsForEachFolder, folderIndex);
00565        NS_ASSERTION(messageArray, "messageArray is null");
00566 
00567        curFolder->DeleteMessages(messageArray, window, PR_TRUE /* delete storage */, PR_FALSE /* is move*/, nsnull/*copyServListener*/, PR_FALSE /*allowUndo*/ );
00568     }
00569 
00570     return NS_OK;
00571 }
00572 
00573 NS_IMETHODIMP nsMsgSearchDBView::Sort(nsMsgViewSortTypeValue sortType, nsMsgViewSortOrderValue sortOrder)
00574 {
00575     nsresult rv;
00576     PRInt32 rowCountBeforeSort = GetSize();
00577 
00578     if (!rowCountBeforeSort)
00579         return NS_OK;
00580 
00581     nsMsgKey preservedKey;
00582     nsMsgKeyArray preservedSelection;
00583     SaveAndClearSelection(&preservedKey, &preservedSelection);
00584 
00585     rv = nsMsgDBView::Sort(sortType,sortOrder);
00586 
00587     // the sort may have changed the number of rows
00588     // before we restore the selection, tell the tree
00589     // do this before we call restore selection
00590     // this is safe when there is no selection. 
00591     rv = AdjustRowCount(rowCountBeforeSort, GetSize());
00592 
00593     RestoreSelection(preservedKey, &preservedSelection);
00594     if (mTree) mTree->Invalidate();
00595 
00596     NS_ENSURE_SUCCESS(rv,rv);
00597     return rv;
00598 }
00599 
00600 
00601 // if nothing selected, return an NS_ERROR
00602 NS_IMETHODIMP
00603 nsMsgSearchDBView::GetHdrForFirstSelectedMessage(nsIMsgDBHdr **hdr)
00604 {
00605   NS_ENSURE_ARG_POINTER(hdr);
00606   PRInt32 index;
00607   if (!mTreeSelection)
00608     return NS_ERROR_NULL_POINTER;
00609   nsresult rv = mTreeSelection->GetCurrentIndex(&index);
00610   NS_ENSURE_SUCCESS(rv,rv);
00611 
00612   rv = GetMsgHdrForViewIndex(index, hdr);
00613   NS_ENSURE_SUCCESS(rv,rv);
00614   return NS_OK;
00615 }
00616 
00617 nsresult
00618 nsMsgSearchDBView::GetFolderFromMsgURI(const char *aMsgURI, nsIMsgFolder **aFolder)
00619 {
00620   nsCOMPtr <nsIMsgMessageService> msgMessageService;
00621   nsresult rv = GetMessageServiceFromURI(aMsgURI, getter_AddRefs(msgMessageService));
00622   NS_ENSURE_SUCCESS(rv,rv);
00623   
00624   nsCOMPtr <nsIMsgDBHdr> msgHdr;
00625   rv = msgMessageService->MessageURIToMsgHdr(aMsgURI, getter_AddRefs(msgHdr));
00626   NS_ENSURE_SUCCESS(rv,rv);
00627   
00628   return msgHdr->GetFolder(aFolder);
00629 }
00630