diff --git a/mailnews/db/msgdb/src/nsMsgThread.cpp b/mailnews/db/msgdb/src/nsMsgThread.cpp index f1fe91cfc49..dfce8454cc4 100644 --- a/mailnews/db/msgdb/src/nsMsgThread.cpp +++ b/mailnews/db/msgdb/src/nsMsgThread.cpp @@ -198,13 +198,14 @@ nsresult nsMsgThread::RerootThread(nsIMsgDBHdr *newParentOfOldRoot, nsIMsgDBHdr do { ancestorHdr->GetThreadParent(&newHdrAncestor); - if (newHdrAncestor != nsMsgKey_None && newHdrAncestor != m_threadRootKey) + if (newHdrAncestor != nsMsgKey_None && newHdrAncestor != m_threadRootKey && newHdrAncestor != newRoot) { newRoot = newHdrAncestor; rv = m_mdbDB->GetMsgHdrForKey(newRoot, getter_AddRefs(ancestorHdr)); } } - while (NS_SUCCEEDED(rv) && ancestorHdr && newHdrAncestor != nsMsgKey_None && newHdrAncestor != m_threadRootKey); + while (NS_SUCCEEDED(rv) && ancestorHdr && newHdrAncestor != nsMsgKey_None && newHdrAncestor != m_threadRootKey + && newHdrAncestor != newRoot); SetThreadRootKey(newRoot); ReparentNonReferenceChildrenOf(oldRoot, newRoot, announcer); if (ancestorHdr) diff --git a/mailnews/imap/src/nsImapMailFolder.cpp b/mailnews/imap/src/nsImapMailFolder.cpp index c436e2643fb..c01c5a49940 100644 --- a/mailnews/imap/src/nsImapMailFolder.cpp +++ b/mailnews/imap/src/nsImapMailFolder.cpp @@ -2916,7 +2916,6 @@ NS_IMETHODIMP nsImapMailFolder::StoreImapFlags(PRInt32 flags, PRBool addFlags, n GetDatabase(nsnull); if (mDatabase) { -// UndoManager *undoManager = NULL; PRUint32 total = numKeys; for (PRUint32 keyIndex=0; keyIndex < total; keyIndex++) @@ -2926,25 +2925,6 @@ NS_IMETHODIMP nsImapMailFolder::StoreImapFlags(PRInt32 flags, PRBool addFlags, n SetFlag(MSG_FOLDER_FLAG_OFFLINEEVENTS); if (NS_SUCCEEDED(rv) && op) { -#if 0 - MailDB *originalDB = NULL; - if (op->GetOperationFlags() & kMoveResult) - { - // get the op in the source db and change the flags there - OfflineImapOperation *originalOp = GetOriginalOp(op, &originalDB); - if (originalOp) - { - if (undoManager && undoManager->GetState() == UndoIdle && NET_IsOffline()) { - OfflineIMAPUndoAction *undoAction = new - OfflineIMAPUndoAction(paneForFlagUrl, (MSG_FolderInfo*) this, op->GetMessageKey(), kFlagsChanged, - this, NULL, flags, NULL, addFlags); - if (undoAction) - undoManager->AddUndoAction(undoAction); - } - op = originalOp; - } - } -#endif imapMessageFlagsType newFlags; op->GetNewFlags(&newFlags); @@ -2952,13 +2932,6 @@ NS_IMETHODIMP nsImapMailFolder::StoreImapFlags(PRInt32 flags, PRBool addFlags, n op->SetFlagOperation(newFlags | flags); else op->SetFlagOperation(newFlags & ~flags); -#if 0 - if (originalDB) - { - originalDB->Close(); - originalDB = NULL; - } -#endif } } mDatabase->Commit(nsMsgDBCommitType::kLargeCommit); // flush offline flags @@ -4895,11 +4868,11 @@ nsresult nsImapMailFolder::CopyMessagesOffline(nsIMsgFolder* srcFolder, { NS_ENSURE_ARG(messages); nsresult rv = NS_OK; - nsresult stopit = 0; - nsCOMPtr sourceMailDB; + nsresult stopit = 0; + nsCOMPtr sourceMailDB; nsCOMPtr srcDbFolderInfo; srcFolder->GetDBFolderInfoAndDB(getter_AddRefs(srcDbFolderInfo), getter_AddRefs(sourceMailDB)); - PRBool deleteToTrash = PR_FALSE; + PRBool deleteToTrash = PR_FALSE; PRUint32 srcCount; messages->Count(&srcCount); nsCOMPtr imapServer; @@ -4913,18 +4886,13 @@ nsresult nsImapMailFolder::CopyMessagesOffline(nsIMsgFolder* srcFolder, } if (sourceMailDB) { -#ifdef DOING_OFFLINEUNDO_YET - UndoManager *undoManager = NULL; - - if (state && state->sourcePane) - undoManager = state->sourcePane->GetUndoManager(); - - PRBool shouldUndoOffline = undoManager && NET_IsOffline(); - if (shouldUndoOffline) - undoManager->StartBatch(); -#endif // save the future ops in the source DB, if this is not a imap->local copy/move + nsCOMPtr txnMgr; + if (msgWindow) + msgWindow->GetTransactionManager(getter_AddRefs(txnMgr)); + if (txnMgr) + txnMgr->BeginBatch(); GetDatabase(nsnull); if (mDatabase) { @@ -5013,16 +4981,28 @@ nsresult nsImapMailFolder::CopyMessagesOffline(nsIMsgFolder* srcFolder, } else sourceOp->AddMessageCopyOperation(folderURI); // offline copy -#ifdef DOING_OFFLINEUNDO_YET - if (shouldUndoOffline && undoManager->GetState() == UndoIdle) - { // only need undo if we're really offline and not pseudo offline - OfflineIMAPUndoAction *undoAction = new - OfflineIMAPUndoAction(state->sourcePane, (MSG_FolderInfo*) this, sourceOp->GetMessageKey(), opType, - sourceMailDB->GetFolderInfo(), dstFolder, 0, NULL, 0); - if (undoAction) - undoManager->AddUndoAction(undoAction); + + nsMsgKeyArray srcKeyArray; + nsCOMPtr urlListener; + + sourceOp->GetOperation(&opType); + srcKeyArray.Add(originalKey); + rv = QueryInterface(NS_GET_IID(nsIUrlListener), getter_AddRefs(urlListener)); + nsImapOfflineTxn *undoMsgTxn = new + nsImapOfflineTxn(srcFolder, &srcKeyArray, this, isMove, opType, message, + m_eventQueue, urlListener); + + if (undoMsgTxn) + { + if (isMove) + undoMsgTxn->SetTransactionType(nsIMessenger::eMoveMsg); + else + undoMsgTxn->SetTransactionType(nsIMessenger::eCopyMsg); + // we're adding this undo action before the delete is successful. This is evil, + // but 4.5 did it as well. + if (txnMgr) + txnMgr->DoTransaction(undoMsgTxn); } -#endif } PRBool hasMsgOffline = PR_FALSE; srcFolder->HasMsgOffline(originalKey, &hasMsgOffline); @@ -5075,16 +5055,21 @@ nsresult nsImapMailFolder::CopyMessagesOffline(nsIMsgFolder* srcFolder, SetFlag(MSG_FOLDER_FLAG_OFFLINEEVENTS); destOp->SetSourceFolderURI(originalSrcFolderURI); destOp->SetMessageKey(originalKey); -#ifdef DOING_OFFLINEUNDO_YET - if (shouldUndoOffline && undoManager->GetState() == UndoIdle) { - OfflineIMAPUndoAction *undoAction = new - OfflineIMAPUndoAction(state->sourcePane, (MSG_FolderInfo*) this, destOp->GetMessageKey(), kAddedHeader, - state->destDB->GetFolderInfo(), dstFolder, 0, newMailHdr); - if (undoAction) - undoManager->AddUndoAction(undoAction); + nsCOMPtr urlListener; + + QueryInterface(NS_GET_IID(nsIUrlListener), getter_AddRefs(urlListener)); + nsMsgKeyArray keyArray; + keyArray.Add(fakeBase + sourceKeyIndex); + nsImapOfflineTxn *undoMsgTxn = new + nsImapOfflineTxn(this, &keyArray, this, isMove, nsIMsgOfflineImapOperation::kAddedHeader, + newMailHdr, m_eventQueue, urlListener); + if (undoMsgTxn) + { + if (txnMgr) + txnMgr->DoTransaction(undoMsgTxn); + } } -#endif } } else @@ -5093,23 +5078,39 @@ nsresult nsImapMailFolder::CopyMessagesOffline(nsIMsgFolder* srcFolder, successfulCopy = NS_SUCCEEDED(stopit); + nsMsgKey msgKey; + mailHdr->GetMessageKey(&msgKey); if (isMove && successfulCopy) { + nsMsgKeyArray srcKeyArray; + nsCOMPtr urlListener; + + srcKeyArray.Add(msgKey); + rv = QueryInterface(NS_GET_IID(nsIUrlListener), getter_AddRefs(urlListener)); + nsOfflineImapOperationType opType = nsIMsgOfflineImapOperation::kDeletedMsg; if (!deleteToTrash) opType = nsIMsgOfflineImapOperation::kMsgMarkedDeleted; -#ifdef DOING_OFFLINEUNDO_YET - if (shouldUndoOffline && undoManager->GetState() == UndoIdle) - { - OfflineIMAPUndoAction *undoAction = new - OfflineIMAPUndoAction(state->sourcePane, (MSG_FolderInfo*) this, mailHdr->GetMessageKey(), opType, - sourceMailDB->GetFolderInfo(), dstFolder, 0, mailHdr); - if (undoAction) - undoManager->AddUndoAction(undoAction); - } -#endif - nsMsgKey msgKey; - mailHdr->GetMessageKey(&msgKey); + srcKeyArray.Add(msgKey); + nsImapOfflineTxn *undoMsgTxn = new + nsImapOfflineTxn(srcFolder, &srcKeyArray, this, isMove, opType, mailHdr, + m_eventQueue, urlListener); + if (undoMsgTxn) + { + if (isMove) + { + if (mFlags & MSG_FOLDER_FLAG_TRASH) + undoMsgTxn->SetTransactionType(nsIMessenger::eDeleteMsg); + else + undoMsgTxn->SetTransactionType(nsIMessenger::eMoveMsg); + } + else + { + undoMsgTxn->SetTransactionType(nsIMessenger::eCopyMsg); + } + if (txnMgr) + txnMgr->DoTransaction(undoMsgTxn); + } if (deleteToTrash) sourceMailDB->DeleteMessage(msgKey, nsnull, PR_FALSE); else @@ -5141,11 +5142,8 @@ nsresult nsImapMailFolder::CopyMessagesOffline(nsIMsgFolder* srcFolder, SummaryChanged(); srcFolder->SummaryChanged(); } - -#ifdef DOING_OFFLINEUNDO_YET - if (shouldUndoOffline) - undoManager->EndBatch(); -#endif + if (txnMgr) + txnMgr->EndBatch(); } if (NS_SUCCEEDED(rv) && isMove) srcFolder->NotifyFolderEvent(mDeleteOrMoveMsgCompletedAtom); diff --git a/mailnews/imap/src/nsImapUndoTxn.cpp b/mailnews/imap/src/nsImapUndoTxn.cpp index e78fe0df6e9..35b47540509 100644 --- a/mailnews/imap/src/nsImapUndoTxn.cpp +++ b/mailnews/imap/src/nsImapUndoTxn.cpp @@ -28,7 +28,7 @@ #include "nsXPIDLString.h" #include "nsIIMAPHostSessionList.h" #include "nsIMsgIncomingServer.h" - +#include "nsIDBFolderInfo.h" static NS_DEFINE_CID(kCImapService, NS_IMAPSERVICE_CID); static NS_DEFINE_CID(kCImapHostSessionList, NS_IIMAPHOSTSESSIONLIST_CID); @@ -57,62 +57,62 @@ nsImapMoveCopyMsgTxn::Init( PRBool idsAreUids, PRBool isMove, nsIEventQueue* eventQueue, nsIUrlListener* urlListener) { - nsresult rv; - NS_NewISupportsArray(getter_AddRefs(m_srcHdrs)); - m_srcMsgIdString = srcMsgIdString; - m_idsAreUids = idsAreUids; - m_isMove = isMove; - m_srcFolder = getter_AddRefs(NS_GetWeakReference(srcFolder)); - m_dstFolder = getter_AddRefs(NS_GetWeakReference(dstFolder)); - m_eventQueue = do_QueryInterface(eventQueue, &rv); - if (urlListener) - m_urlListener = do_QueryInterface(urlListener, &rv); - m_srcKeyArray.CopyArray(srcKeyArray); - m_dupKeyArray.CopyArray(srcKeyArray); - nsXPIDLCString uri; - rv = srcFolder->GetURI(getter_Copies(uri)); - nsCString protocolType(uri); - protocolType.SetLength(protocolType.FindChar(':')); - // ** jt -- only do this for mailbox protocol - if (protocolType.EqualsIgnoreCase("mailbox")) + nsresult rv; + NS_NewISupportsArray(getter_AddRefs(m_srcHdrs)); + m_srcMsgIdString = srcMsgIdString; + m_idsAreUids = idsAreUids; + m_isMove = isMove; + m_srcFolder = getter_AddRefs(NS_GetWeakReference(srcFolder)); + m_dstFolder = getter_AddRefs(NS_GetWeakReference(dstFolder)); + m_eventQueue = do_QueryInterface(eventQueue, &rv); + if (urlListener) + m_urlListener = do_QueryInterface(urlListener, &rv); + m_srcKeyArray.CopyArray(srcKeyArray); + m_dupKeyArray.CopyArray(srcKeyArray); + nsXPIDLCString uri; + rv = srcFolder->GetURI(getter_Copies(uri)); + nsCString protocolType(uri); + protocolType.SetLength(protocolType.FindChar(':')); + // ** jt -- only do this for mailbox protocol + if (protocolType.EqualsIgnoreCase("mailbox")) + { + m_srcIsPop3 = PR_TRUE; + PRUint32 i, count = m_srcKeyArray.GetSize(); + nsCOMPtr srcDB; + rv = srcFolder->GetMsgDatabase(nsnull, getter_AddRefs(srcDB)); + if (NS_FAILED(rv)) return rv; + nsCOMPtr srcHdr; + nsCOMPtr copySrcHdr; + nsMsgKey pseudoKey; + + for (i=0; i srcDB; - rv = srcFolder->GetMsgDatabase(nsnull, getter_AddRefs(srcDB)); - if (NS_FAILED(rv)) return rv; - nsCOMPtr srcHdr; - nsCOMPtr copySrcHdr; - nsMsgKey pseudoKey; - - for (i=0; iGetMsgHdrForKey(m_srcKeyArray.GetAt(i), + getter_AddRefs(srcHdr)); + if (NS_SUCCEEDED(rv)) + { + PRUint32 msgSize; + rv = srcHdr->GetMessageSize(&msgSize); + if (NS_SUCCEEDED(rv)) + m_srcSizeArray.Add(msgSize); + if (isMove) { - rv = srcDB->GetMsgHdrForKey(m_srcKeyArray.GetAt(i), - getter_AddRefs(srcHdr)); - if (NS_SUCCEEDED(rv)) - { - PRUint32 msgSize; - rv = srcHdr->GetMessageSize(&msgSize); - if (NS_SUCCEEDED(rv)) - m_srcSizeArray.Add(msgSize); - if (isMove) - { - srcDB->GetNextPseudoMsgKey(&pseudoKey); - pseudoKey--; - m_dupKeyArray.SetAt(i,pseudoKey); - rv = srcDB->CopyHdrFromExistingHdr(pseudoKey, - srcHdr, PR_FALSE, - getter_AddRefs(copySrcHdr)); - if (NS_SUCCEEDED(rv)) - { - nsCOMPtr supports = do_QueryInterface(copySrcHdr); - m_srcHdrs->AppendElement(supports); - } - } - } + srcDB->GetNextPseudoMsgKey(&pseudoKey); + pseudoKey--; + m_dupKeyArray.SetAt(i,pseudoKey); + rv = srcDB->CopyHdrFromExistingHdr(pseudoKey, + srcHdr, PR_FALSE, + getter_AddRefs(copySrcHdr)); + if (NS_SUCCEEDED(rv)) + { + nsCOMPtr supports = do_QueryInterface(copySrcHdr); + m_srcHdrs->AppendElement(supports); + } } + } } - return rv; + } + return rv; } nsImapMoveCopyMsgTxn::~nsImapMoveCopyMsgTxn() @@ -146,61 +146,61 @@ nsImapMoveCopyMsgTxn::QueryInterface(REFNSIID aIID, void** aInstancePtr) NS_IMETHODIMP nsImapMoveCopyMsgTxn::UndoTransaction(void) { - nsresult rv = NS_OK; - nsCOMPtr imapService(do_GetService(kCImapService, &rv)); - if (NS_FAILED(rv)) return rv; - if (m_isMove || !m_dstFolder) + nsresult rv = NS_OK; + nsCOMPtr imapService(do_GetService(kCImapService, &rv)); + if (NS_FAILED(rv)) return rv; + if (m_isMove || !m_dstFolder) + { + if (m_srcIsPop3) { - if (m_srcIsPop3) - { - rv = UndoMailboxDelete(); - if (NS_FAILED(rv)) return rv; - } - else - { - nsCOMPtr srcFolder = do_QueryReferent(m_srcFolder, &rv); - if (NS_FAILED(rv) || !srcFolder) return rv; - nsCOMPtr srcListener = - do_QueryInterface(srcFolder, &rv); - if (NS_FAILED(rv)) return rv; - // ** make sure we are in the selected state; use lite select - // folder so we won't hit performance hard - rv = imapService->LiteSelectFolder(m_eventQueue, srcFolder, - srcListener, nsnull); - if (NS_FAILED(rv)) return rv; - rv = imapService->SubtractMessageFlags( - m_eventQueue, srcFolder, srcListener, nsnull, - m_srcMsgIdString.get(), kImapMsgDeletedFlag, - m_idsAreUids); - if (NS_FAILED(rv)) return rv; - if (DeleteIsMoveToTrash(srcFolder)) - rv = imapService->GetHeaders(m_eventQueue, srcFolder, - srcListener, nsnull, - m_srcMsgIdString.get(), - PR_TRUE); - } + rv = UndoMailboxDelete(); + if (NS_FAILED(rv)) return rv; } - if (m_dstKeyArray.GetSize() > 0) + else { - nsCOMPtr dstFolder = do_QueryReferent(m_dstFolder, &rv); - if (NS_FAILED(rv) || !dstFolder) return rv; - - nsCOMPtr dstListener; - - dstListener = do_QueryInterface(dstFolder, &rv); - if (NS_FAILED(rv)) return rv; - // ** make sire we are in the selected state; use lite select folder - // so we won't hit preformace hard - rv = imapService->LiteSelectFolder(m_eventQueue, dstFolder, - dstListener, nsnull); - if (NS_FAILED(rv)) return rv; - rv = imapService->AddMessageFlags(m_eventQueue, dstFolder, - dstListener, nsnull, - m_dstMsgIdString.get(), - kImapMsgDeletedFlag, - m_idsAreUids); + nsCOMPtr srcFolder = do_QueryReferent(m_srcFolder, &rv); + if (NS_FAILED(rv) || !srcFolder) return rv; + nsCOMPtr srcListener = + do_QueryInterface(srcFolder, &rv); + if (NS_FAILED(rv)) return rv; + // ** make sure we are in the selected state; use lite select + // folder so we won't hit performance hard + rv = imapService->LiteSelectFolder(m_eventQueue, srcFolder, + srcListener, nsnull); + if (NS_FAILED(rv)) return rv; + rv = imapService->SubtractMessageFlags( + m_eventQueue, srcFolder, srcListener, nsnull, + m_srcMsgIdString.get(), kImapMsgDeletedFlag, + m_idsAreUids); + if (NS_FAILED(rv)) return rv; + if (DeleteIsMoveToTrash(srcFolder)) + rv = imapService->GetHeaders(m_eventQueue, srcFolder, + srcListener, nsnull, + m_srcMsgIdString.get(), + PR_TRUE); } - return rv; + } + if (m_dstKeyArray.GetSize() > 0) + { + nsCOMPtr dstFolder = do_QueryReferent(m_dstFolder, &rv); + if (NS_FAILED(rv) || !dstFolder) return rv; + + nsCOMPtr dstListener; + + dstListener = do_QueryInterface(dstFolder, &rv); + if (NS_FAILED(rv)) return rv; + // ** make sire we are in the selected state; use lite select folder + // so we won't hit preformace hard + rv = imapService->LiteSelectFolder(m_eventQueue, dstFolder, + dstListener, nsnull); + if (NS_FAILED(rv)) return rv; + rv = imapService->AddMessageFlags(m_eventQueue, dstFolder, + dstListener, nsnull, + m_dstMsgIdString.get(), + kImapMsgDeletedFlag, + m_idsAreUids); + } + return rv; } NS_IMETHODIMP @@ -402,3 +402,213 @@ PRBool nsImapMoveCopyMsgTxn::DeleteIsMoveToTrash(nsIMsgFolder *folder) retVal); return retVal; } + + + +nsImapOfflineTxn::nsImapOfflineTxn(nsIMsgFolder* srcFolder, nsMsgKeyArray* srcKeyArray, + nsIMsgFolder* dstFolder, PRBool isMove, nsOfflineImapOperationType opType, + nsIMsgDBHdr *srcHdr, + nsIEventQueue* eventQueue, nsIUrlListener* urlListener) +{ + Init(srcFolder, srcKeyArray, nsnull, dstFolder, PR_TRUE, + isMove, eventQueue, urlListener); + + m_opType = opType; + m_flags = 0; + m_addFlags = PR_FALSE; + m_header = srcHdr; + if (opType == nsIMsgOfflineImapOperation::kDeletedMsg) + { + nsCOMPtr srcDB; + nsCOMPtr folderInfo; + + nsresult rv = srcFolder->GetDBFolderInfoAndDB(getter_AddRefs(folderInfo), getter_AddRefs(srcDB)); + if (NS_SUCCEEDED(rv) && srcDB) + { + nsMsgKey pseudoKey; + nsCOMPtr copySrcHdr; + + srcDB->GetNextPseudoMsgKey(&pseudoKey); + pseudoKey--; + m_dupKeyArray.SetAt(0, pseudoKey); + rv = srcDB->CopyHdrFromExistingHdr(pseudoKey, srcHdr, PR_FALSE, getter_AddRefs(copySrcHdr)); + if (NS_SUCCEEDED(rv)) + { + nsCOMPtr supports = do_QueryInterface(copySrcHdr); + m_srcHdrs->AppendElement(supports); + } + } + } +} + +nsImapOfflineTxn::~nsImapOfflineTxn() +{ +} + +// Open the database and find the key for the offline operation that we want to +// undo, then remove it from the database, we also hold on to this +// data for a redo operation. +NS_IMETHODIMP nsImapOfflineTxn::UndoTransaction(void) +{ + nsresult rv; + + nsCOMPtr srcFolder = do_QueryReferent(m_srcFolder, &rv); + if (NS_FAILED(rv) || !srcFolder) + return rv; + nsCOMPtr op; + nsCOMPtr folderInfo; + nsCOMPtr srcDB; + nsCOMPtr destDB; + + nsMsgKey hdrKey = nsMsgKey_None; + + if (m_header) + m_header->GetMessageKey(&hdrKey); + + rv = srcFolder->GetDBFolderInfoAndDB(getter_AddRefs(folderInfo), getter_AddRefs(srcDB)); + NS_ENSURE_SUCCESS(rv, rv); + switch (m_opType) + { + case nsIMsgOfflineImapOperation::kMsgMoved: + case nsIMsgOfflineImapOperation::kMsgCopy: + case nsIMsgOfflineImapOperation::kAddedHeader: + case nsIMsgOfflineImapOperation::kFlagsChanged: + rv = srcDB->GetOfflineOpForKey(hdrKey, PR_FALSE, getter_AddRefs(op)); + if (NS_SUCCEEDED(rv) && op) + { + srcDB->RemoveOfflineOp(op); + op = nsnull; + } + if (m_header && (m_opType == nsIMsgOfflineImapOperation::kAddedHeader)) + { + nsCOMPtr mailHdr; + nsMsgKey msgKey; + m_header->GetMessageKey(&msgKey); + rv = srcDB->GetMsgHdrForKey(msgKey, getter_AddRefs(mailHdr)); + if (mailHdr) + srcDB->DeleteHeader(mailHdr, nsnull, PR_TRUE, PR_FALSE); + } + break; + case nsIMsgOfflineImapOperation::kDeletedMsg: + { + nsMsgKey msgKey; + m_header->GetMessageKey(&msgKey); + nsCOMPtr undeletedHdr; + m_srcHdrs->QueryElementAt(0, NS_GET_IID(nsIMsgDBHdr), getter_AddRefs(undeletedHdr)); + if (undeletedHdr) + { + nsCOMPtr newHdr; + + srcDB->CopyHdrFromExistingHdr (msgKey, undeletedHdr, PR_TRUE, getter_AddRefs(newHdr)); + } + srcDB->Close(PR_TRUE); + srcFolder->SummaryChanged(); + } + break; + case nsIMsgOfflineImapOperation::kMsgMarkedDeleted: + srcDB->MarkImapDeleted(hdrKey, PR_FALSE, nsnull); + break; + default: + break; + } + srcDB->Close(PR_TRUE); + srcFolder->SummaryChanged(); + return NS_OK; +} + +NS_IMETHODIMP nsImapOfflineTxn::RedoTransaction(void) +{ + nsresult rv; + + nsCOMPtr srcFolder = do_QueryReferent(m_srcFolder, &rv); + if (NS_FAILED(rv) || !srcFolder) + return rv; + nsCOMPtr op; + nsCOMPtr folderInfo; + nsCOMPtr srcDB; + nsCOMPtr destDB; + rv = srcFolder->GetDBFolderInfoAndDB(getter_AddRefs(folderInfo), getter_AddRefs(srcDB)); + NS_ENSURE_SUCCESS(rv, rv); + nsMsgKey hdrKey = nsMsgKey_None; + + if (m_header) + m_header->GetMessageKey(&hdrKey); + + switch (m_opType) + { + case nsIMsgOfflineImapOperation::kMsgMoved: + case nsIMsgOfflineImapOperation::kMsgCopy: + rv = srcDB->GetOfflineOpForKey(hdrKey, PR_FALSE, getter_AddRefs(op)); + if (NS_SUCCEEDED(rv) && op) + { + nsCOMPtr dstFolder = do_QueryReferent(m_dstFolder, &rv); + if (dstFolder) + { + nsXPIDLCString folderURI; + dstFolder->GetURI(getter_Copies(folderURI)); + + + if (m_opType == nsIMsgOfflineImapOperation::kMsgMoved) + { + op->SetDestinationFolderURI(folderURI); // offline move + } + if (m_opType == nsIMsgOfflineImapOperation::kMsgCopy) + { + op->SetOperation(nsIMsgOfflineImapOperation::kMsgMoved); + op->AddMessageCopyOperation(folderURI); // offline copy + } + dstFolder->SummaryChanged(); + } + } + break; + case nsIMsgOfflineImapOperation::kAddedHeader: + { + nsCOMPtr restoreHdr; + nsMsgKey msgKey; + m_header->GetMessageKey(&msgKey); + nsCOMPtr dstFolder = do_QueryReferent(m_dstFolder, &rv); + rv = srcFolder->GetDBFolderInfoAndDB(getter_AddRefs(folderInfo), getter_AddRefs(destDB)); + NS_ENSURE_SUCCESS(rv, rv); + if (m_header) + destDB->CopyHdrFromExistingHdr (msgKey, m_header, PR_TRUE, getter_AddRefs(restoreHdr)); + destDB->Close(PR_TRUE); + dstFolder->SummaryChanged(); + rv = destDB->GetOfflineOpForKey(hdrKey, PR_TRUE, getter_AddRefs(op)); + if (NS_SUCCEEDED(rv) && op) + { + nsXPIDLCString folderURI; + srcFolder->GetURI(getter_Copies(folderURI)); + op->SetSourceFolderURI(folderURI); + } + dstFolder->SummaryChanged(); + destDB->Close(PR_TRUE); + } + break; + case nsIMsgOfflineImapOperation::kDeletedMsg: + srcDB->DeleteMessage(hdrKey, nsnull, PR_TRUE); + break; + case nsIMsgOfflineImapOperation::kMsgMarkedDeleted: + srcDB->MarkImapDeleted(hdrKey, PR_TRUE, nsnull); + break; + case nsIMsgOfflineImapOperation::kFlagsChanged: + rv = srcDB->GetOfflineOpForKey(hdrKey, PR_TRUE, getter_AddRefs(op)); + if (NS_SUCCEEDED(rv) && op) + { + imapMessageFlagsType newMsgFlags; + op->GetNewFlags(&newMsgFlags); + if (m_addFlags) + op->SetFlagOperation(newMsgFlags | m_flags); + else + op->SetFlagOperation(newMsgFlags & ~m_flags); + } + break; + default: + break; + } + srcDB->Close(PR_TRUE); + srcDB = nsnull; + srcFolder->SummaryChanged(); + return NS_OK; +} + + diff --git a/mailnews/imap/src/nsImapUndoTxn.h b/mailnews/imap/src/nsImapUndoTxn.h index fea6c1f6af1..f5b10866904 100644 --- a/mailnews/imap/src/nsImapUndoTxn.h +++ b/mailnews/imap/src/nsImapUndoTxn.h @@ -14,7 +14,7 @@ * * The Initial Developer of the Original Code is Netscape * Communications Corporation. Portions created by Netscape are - * Copyright (C) 1998, 1999 Netscape Communications Corporation. All + * Copyright (C) 1998-2001 Netscape Communications Corporation. All * Rights Reserved. * * Contributor(s): @@ -30,6 +30,7 @@ #include "nsIEventQueue.h" #include "nsMsgTxn.h" #include "nsMsgKeyArray.h" +#include "nsIMsgOfflineImapOperation.h" #include "nsCOMPtr.h" #include "nsWeakReference.h" @@ -41,52 +42,77 @@ class nsImapMoveCopyMsgTxn : public nsMsgTxn { public: - NS_DEFINE_STATIC_IID_ACCESSOR(NS_IMAPMOVECOPYMSGTXN_IID) + NS_DEFINE_STATIC_IID_ACCESSOR(NS_IMAPMOVECOPYMSGTXN_IID) - nsImapMoveCopyMsgTxn(); - nsImapMoveCopyMsgTxn(nsIMsgFolder* srcFolder, nsMsgKeyArray* srcKeyArray, - const char* srcMsgIdString, nsIMsgFolder* dstFolder, - PRBool idsAreUids, PRBool isMove, - nsIEventQueue *eventQueue, - nsIUrlListener *urlListener); - virtual ~nsImapMoveCopyMsgTxn(); + nsImapMoveCopyMsgTxn(); + nsImapMoveCopyMsgTxn(nsIMsgFolder* srcFolder, nsMsgKeyArray* srcKeyArray, + const char* srcMsgIdString, nsIMsgFolder* dstFolder, + PRBool idsAreUids, PRBool isMove, + nsIEventQueue *eventQueue, + nsIUrlListener *urlListener); + virtual ~nsImapMoveCopyMsgTxn(); - NS_DECL_ISUPPORTS_INHERITED + NS_DECL_ISUPPORTS_INHERITED - NS_IMETHOD UndoTransaction(void); - NS_IMETHOD RedoTransaction(void); + NS_IMETHOD UndoTransaction(void); + NS_IMETHOD RedoTransaction(void); - // helper - nsresult SetCopyResponseUid(nsMsgKeyArray* keyArray, - const char *msgIdString); - nsresult GetSrcKeyArray(nsMsgKeyArray& srcKeyArray); - nsresult GetDstKeyArray(nsMsgKeyArray& dstKeyArray); - nsresult AddDstKey(nsMsgKey aKey); - nsresult UndoMailboxDelete(); - nsresult RedoMailboxDelete(); - nsresult Init(nsIMsgFolder* srcFolder, nsMsgKeyArray* srcKeyArray, - const char* srcMsgIdString, nsIMsgFolder* dstFolder, - PRBool idsAreUids, PRBool isMove, - nsIEventQueue *eventQueue, - nsIUrlListener *urlListener); - PRBool DeleteIsMoveToTrash(nsIMsgFolder* folder); + // helper + nsresult SetCopyResponseUid(nsMsgKeyArray* keyArray, + const char *msgIdString); + nsresult GetSrcKeyArray(nsMsgKeyArray& srcKeyArray); + nsresult GetDstKeyArray(nsMsgKeyArray& dstKeyArray); + nsresult AddDstKey(nsMsgKey aKey); + nsresult UndoMailboxDelete(); + nsresult RedoMailboxDelete(); + nsresult Init(nsIMsgFolder* srcFolder, nsMsgKeyArray* srcKeyArray, + const char* srcMsgIdString, nsIMsgFolder* dstFolder, + PRBool idsAreUids, PRBool isMove, + nsIEventQueue *eventQueue, + nsIUrlListener *urlListener); + PRBool DeleteIsMoveToTrash(nsIMsgFolder* folder); -private: +protected: - nsWeakPtr m_srcFolder; - nsCOMPtr m_srcHdrs; - nsMsgKeyArray m_dupKeyArray; - nsMsgKeyArray m_srcKeyArray; - nsCString m_srcMsgIdString; - nsWeakPtr m_dstFolder; - nsMsgKeyArray m_dstKeyArray; - nsCString m_dstMsgIdString; - nsCOMPtr m_eventQueue; - nsCOMPtr m_urlListener; - PRBool m_idsAreUids; - PRBool m_isMove; - PRBool m_srcIsPop3; - nsUInt32Array m_srcSizeArray; + nsWeakPtr m_srcFolder; + nsCOMPtr m_srcHdrs; + nsMsgKeyArray m_dupKeyArray; + nsMsgKeyArray m_srcKeyArray; + nsCString m_srcMsgIdString; + nsWeakPtr m_dstFolder; + nsMsgKeyArray m_dstKeyArray; + nsCString m_dstMsgIdString; + nsCOMPtr m_eventQueue; + nsCOMPtr m_urlListener; + PRBool m_idsAreUids; + PRBool m_isMove; + PRBool m_srcIsPop3; + nsUInt32Array m_srcSizeArray; }; +class nsImapOfflineTxn : public nsImapMoveCopyMsgTxn +{ +public: + nsImapOfflineTxn(nsIMsgFolder* srcFolder, nsMsgKeyArray* srcKeyArray, + nsIMsgFolder* dstFolder, + PRBool isMove, + nsOfflineImapOperationType opType, + nsIMsgDBHdr *srcHdr, + nsIEventQueue *eventQueue, + nsIUrlListener *urlListener); + virtual ~nsImapOfflineTxn(); + + NS_IMETHOD UndoTransaction(void); + NS_IMETHOD RedoTransaction(void); + void SetAddFlags(PRBool addFlags) {m_addFlags = addFlags;} + void SetFlags(PRUint32 flags) {m_flags = flags;} +protected: + nsOfflineImapOperationType m_opType; + nsCOMPtr m_header; + // these two are used to undo flag changes, which we don't currently do. + PRBool m_addFlags; + PRUint32 m_flags; +}; + + #endif