diff --git a/cachedimapjob.cpp b/cachedimapjob.cpp index eb537349f..1c85dea90 100644 --- a/cachedimapjob.cpp +++ b/cachedimapjob.cpp @@ -545,6 +545,8 @@ void CachedImapJob::slotDeleteNextFolder( KIO::Job *job ) return; } + mAccount->removeDeletedFolder( (*it).path ); + if( job->error() ) { mAccount->handleJobError( job, i18n( "Error while deleting folder %1 on the server: " ).arg( (*it).path ) + '\n' ); delete this; diff --git a/kmacctcachedimap.cpp b/kmacctcachedimap.cpp index 375aa8b1f..d02df0b65 100644 --- a/kmacctcachedimap.cpp +++ b/kmacctcachedimap.cpp @@ -267,7 +267,10 @@ void KMAcctCachedImap::postProcessNewMail( KMFolderCachedImap* folder, bool ) // instead of the user being stuck with "can't delete" every time. // And we do it for _all_ deleted folders, even those that were deleted on the server in the first place (slotListResult). // Otherwise this might have side effects much later (e.g. when regaining permissions to a folder we could see before) + +#if 0 // this opens a race: delete a folder during a sync (after the sync checked that folder), and it'll be forgotten... mDeletedFolders.clear(); +#endif mPreviouslyDeletedFolders.clear(); } @@ -367,9 +370,46 @@ void KMAcctCachedImap::invalidateIMAPFolders( KMFolderCachedImap* folder ) } //----------------------------------------------------------------------------- -void KMAcctCachedImap::addDeletedFolder( const QString& subFolderPath ) +void KMAcctCachedImap::addDeletedFolder( KMFolder* folder ) { - mDeletedFolders.append( subFolderPath ); + if ( folder->folderType() != KMFolderTypeCachedImap ) + return; + KMFolderCachedImap* storage = static_cast(folder->storage()); + addDeletedFolder( storage->imapPath() ); + kdDebug(5006) << k_funcinfo << storage->imapPath() << endl; + + // Add all child folders too + if( folder && folder->child() ) { + KMFolderNode *node = folder->child()->first(); + while( node ) { + if( !node->isDir() ) { + addDeletedFolder( static_cast( node ) ); // recurse + } + node = folder->child()->next(); + } + } +} + +void KMAcctCachedImap::addDeletedFolder( const QString& imapPath ) +{ + mDeletedFolders << imapPath; +} + +QStringList KMAcctCachedImap::deletedFolderPaths( const QString& subFolderPath ) const +{ + QStringList lst; + for ( QStringList::const_iterator it = mDeletedFolders.begin(); it != mDeletedFolders.end(); ++it ) { + if ( (*it).startsWith( subFolderPath ) ) + // We must reverse the order, so that sub sub sub folders are deleted first + lst.prepend( *it ); + } + for ( QStringList::const_iterator it = mPreviouslyDeletedFolders.begin(); it != mPreviouslyDeletedFolders.end(); ++it ) { + if ( (*it).startsWith( subFolderPath ) ) + lst.prepend( *it ); + } + kdDebug(5006) << "KMAcctCachedImap::deletedFolderPaths for " << subFolderPath << " returning: " << lst << endl; + Q_ASSERT( !lst.isEmpty() ); + return lst; } bool KMAcctCachedImap::isDeletedFolder( const QString& subFolderPath ) const diff --git a/kmacctcachedimap.h b/kmacctcachedimap.h index dd119017f..26ca515d2 100644 --- a/kmacctcachedimap.h +++ b/kmacctcachedimap.h @@ -38,6 +38,7 @@ class KMFolderCachedImap; class KMFolderTreeItem; +class KMFolder; namespace KMail { class FolderJob; class ImapJob; @@ -108,9 +109,15 @@ public: virtual void invalidateIMAPFolders( KMFolderCachedImap* ); /** - * Remember that a folder got explicitely deleted + * Remember that a folder got explicitely deleted - including all child folders */ - void addDeletedFolder( const QString& subFolderPath ); + void addDeletedFolder( KMFolder* folder ); + + /** + * Remember that a folder got explicitely deleted - NOT including all child folders + * This is used when renaming a folder. + */ + void addDeletedFolder( const QString& imapPath ); /** * Ask if a folder was explicitely deleted in this session @@ -122,6 +129,11 @@ public: */ bool isPreviouslyDeletedFolder( const QString& subFolderPath ) const; + /** + * return the imap path to the deleted folder, as well as the paths for any child folders + */ + QStringList deletedFolderPaths( const QString& subFolderPath ) const; + /** * Remove folder from the "deleted folders" list */ diff --git a/kmfoldercachedimap.cpp b/kmfoldercachedimap.cpp index 44ec3a45d..2032257c3 100644 --- a/kmfoldercachedimap.cpp +++ b/kmfoldercachedimap.cpp @@ -393,7 +393,7 @@ int KMFolderCachedImap::rename( const QString& aName, // Make the change appear to the user with setLabel, but we'll do the change // on the server during the next sync. The name() is the name at the time of - // the last sync. Only rename if the new one is different. If it's the same, + // the last sync. Only rename if the new one is different. If it's the same, // don't rename, but also make sure the rename is reset, in the case of // A -> B -> A renames. if ( name() != aName ) @@ -1584,7 +1584,7 @@ void KMFolderCachedImap::listDirectory2() { if ( locallyDeleted ) { kdDebug(5006) << subfolderPath << " was deleted locally => delete on server." << endl; - foldersForDeletionOnServer << subfolderPath; + foldersForDeletionOnServer += mAccount->deletedFolderPaths( subfolderPath ); // grab all subsubfolders too } else { kdDebug(5006) << subfolderPath << " is a new folder on the server => create local cache" << endl; KMFolder* newFolder = folder()->child()->createFolder(mSubfolderNames[i], false, KMFolderTypeCachedImap); diff --git a/kmmainwidget.cpp b/kmmainwidget.cpp index 2c8ff9cfd..6ab620534 100644 --- a/kmmainwidget.cpp +++ b/kmmainwidget.cpp @@ -1078,7 +1078,7 @@ void KMMainWidget::slotRemoveFolder() KMFolderCachedImap* storage = static_cast( mFolder->storage() ); KMAcctCachedImap* acct = storage->account(); if ( acct ) - acct->addDeletedFolder( storage->imapPath() ); + acct->addDeletedFolder( mFolder ); kmkernel->dimapFolderMgr()->remove(mFolder); }