implement offline undo of imap delete r=naving, sr=sspitzer a=asa 93128

This commit is contained in:
bienvenu%netscape.com 2001-08-23 14:35:50 +00:00
Родитель 1e367845e7
Коммит dc15073f81
4 изменённых файлов: 456 добавлений и 221 удалений

Просмотреть файл

@ -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)

Просмотреть файл

@ -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 <nsIMsgDatabase> sourceMailDB;
nsresult stopit = 0;
nsCOMPtr <nsIMsgDatabase> sourceMailDB;
nsCOMPtr <nsIDBFolderInfo> srcDbFolderInfo;
srcFolder->GetDBFolderInfoAndDB(getter_AddRefs(srcDbFolderInfo), getter_AddRefs(sourceMailDB));
PRBool deleteToTrash = PR_FALSE;
PRBool deleteToTrash = PR_FALSE;
PRUint32 srcCount;
messages->Count(&srcCount);
nsCOMPtr<nsIImapIncomingServer> 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 <nsITransactionManager> 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<nsIUrlListener> 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<nsIUrlListener> 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<nsIUrlListener> 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);

Просмотреть файл

@ -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<nsIMsgDatabase> srcDB;
rv = srcFolder->GetMsgDatabase(nsnull, getter_AddRefs(srcDB));
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIMsgDBHdr> srcHdr;
nsCOMPtr<nsIMsgDBHdr> copySrcHdr;
nsMsgKey pseudoKey;
for (i=0; i<count; i++)
{
m_srcIsPop3 = PR_TRUE;
PRUint32 i, count = m_srcKeyArray.GetSize();
nsCOMPtr<nsIMsgDatabase> srcDB;
rv = srcFolder->GetMsgDatabase(nsnull, getter_AddRefs(srcDB));
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIMsgDBHdr> srcHdr;
nsCOMPtr<nsIMsgDBHdr> copySrcHdr;
nsMsgKey pseudoKey;
for (i=0; i<count; i++)
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)
{
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<nsISupports> 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<nsISupports> 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<nsIImapService> imapService(do_GetService(kCImapService, &rv));
if (NS_FAILED(rv)) return rv;
if (m_isMove || !m_dstFolder)
nsresult rv = NS_OK;
nsCOMPtr<nsIImapService> 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<nsIMsgFolder> srcFolder = do_QueryReferent(m_srcFolder, &rv);
if (NS_FAILED(rv) || !srcFolder) return rv;
nsCOMPtr<nsIUrlListener> 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<nsIMsgFolder> dstFolder = do_QueryReferent(m_dstFolder, &rv);
if (NS_FAILED(rv) || !dstFolder) return rv;
nsCOMPtr<nsIUrlListener> 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<nsIMsgFolder> srcFolder = do_QueryReferent(m_srcFolder, &rv);
if (NS_FAILED(rv) || !srcFolder) return rv;
nsCOMPtr<nsIUrlListener> 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<nsIMsgFolder> dstFolder = do_QueryReferent(m_dstFolder, &rv);
if (NS_FAILED(rv) || !dstFolder) return rv;
nsCOMPtr<nsIUrlListener> 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 <nsIMsgDatabase> srcDB;
nsCOMPtr <nsIDBFolderInfo> folderInfo;
nsresult rv = srcFolder->GetDBFolderInfoAndDB(getter_AddRefs(folderInfo), getter_AddRefs(srcDB));
if (NS_SUCCEEDED(rv) && srcDB)
{
nsMsgKey pseudoKey;
nsCOMPtr <nsIMsgDBHdr> 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<nsISupports> 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<nsIMsgFolder> srcFolder = do_QueryReferent(m_srcFolder, &rv);
if (NS_FAILED(rv) || !srcFolder)
return rv;
nsCOMPtr <nsIMsgOfflineImapOperation> op;
nsCOMPtr <nsIDBFolderInfo> folderInfo;
nsCOMPtr <nsIMsgDatabase> srcDB;
nsCOMPtr <nsIMsgDatabase> 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 <nsIMsgDBHdr> 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<nsIMsgDBHdr> undeletedHdr;
m_srcHdrs->QueryElementAt(0, NS_GET_IID(nsIMsgDBHdr), getter_AddRefs(undeletedHdr));
if (undeletedHdr)
{
nsCOMPtr <nsIMsgDBHdr> 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<nsIMsgFolder> srcFolder = do_QueryReferent(m_srcFolder, &rv);
if (NS_FAILED(rv) || !srcFolder)
return rv;
nsCOMPtr <nsIMsgOfflineImapOperation> op;
nsCOMPtr <nsIDBFolderInfo> folderInfo;
nsCOMPtr <nsIMsgDatabase> srcDB;
nsCOMPtr <nsIMsgDatabase> 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<nsIMsgFolder> 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 <nsIMsgDBHdr> restoreHdr;
nsMsgKey msgKey;
m_header->GetMessageKey(&msgKey);
nsCOMPtr<nsIMsgFolder> 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;
}

Просмотреть файл

@ -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<nsISupportsArray> m_srcHdrs;
nsMsgKeyArray m_dupKeyArray;
nsMsgKeyArray m_srcKeyArray;
nsCString m_srcMsgIdString;
nsWeakPtr m_dstFolder;
nsMsgKeyArray m_dstKeyArray;
nsCString m_dstMsgIdString;
nsCOMPtr<nsIEventQueue> m_eventQueue;
nsCOMPtr<nsIUrlListener> m_urlListener;
PRBool m_idsAreUids;
PRBool m_isMove;
PRBool m_srcIsPop3;
nsUInt32Array m_srcSizeArray;
nsWeakPtr m_srcFolder;
nsCOMPtr<nsISupportsArray> m_srcHdrs;
nsMsgKeyArray m_dupKeyArray;
nsMsgKeyArray m_srcKeyArray;
nsCString m_srcMsgIdString;
nsWeakPtr m_dstFolder;
nsMsgKeyArray m_dstKeyArray;
nsCString m_dstMsgIdString;
nsCOMPtr<nsIEventQueue> m_eventQueue;
nsCOMPtr<nsIUrlListener> 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 <nsIMsgDBHdr> m_header;
// these two are used to undo flag changes, which we don't currently do.
PRBool m_addFlags;
PRUint32 m_flags;
};
#endif