diff --git a/folderstorage.cpp b/folderstorage.cpp index b2dd4d40d..cc77dc46f 100644 --- a/folderstorage.cpp +++ b/folderstorage.cpp @@ -638,7 +638,7 @@ int FolderStorage::rename(const QString& newName, KMFolderDir *newParent) //----------------------------------------------------------------------------- -int FolderStorage::remove() +void FolderStorage::remove() { assert(!folder()->name().isEmpty()); @@ -650,10 +650,9 @@ int FolderStorage::remove() unlink(QFile::encodeName(indexLocation())); int rc = removeContents(); - if (rc) return rc; needsCompact = false; //we are dead - no need to compact us - return 0; + emit removed(folder(), (rc ? false : true)); } diff --git a/folderstorage.h b/folderstorage.h index 9604dbd13..90d387853 100644 --- a/folderstorage.h +++ b/folderstorage.h @@ -257,7 +257,7 @@ public: of the folder in memory. Note that the folder is closed during this process, whether there are others using it or not. @see KMFolder::removeContents */ - virtual int remove(); + virtual void remove(); /** Delete entire folder. Forces a close *but* opens the folder again afterwards. Returns errno(3) error code or zero on @@ -418,6 +418,9 @@ signals: // Emitted by KMFolderCachedIMAP to signal syncing void syncRunning( KMFolder*, bool ); + /** Emitted when a folder was removed */ + void removed(KMFolder*, bool); + public slots: /** Incrementally update the index if possible else call writeIndex */ virtual int updateIndex() = 0; diff --git a/imapaccountbase.cpp b/imapaccountbase.cpp index fd055178a..9ba67d9da 100644 --- a/imapaccountbase.cpp +++ b/imapaccountbase.cpp @@ -529,6 +529,14 @@ namespace KMail { mFoldersQueuedForChecking.clear(); } + //----------------------------------------------------------------------------- + bool ImapAccountBase::checkingMail( KMFolder *folder ) + { + if (checkingMail() && mFoldersQueuedForChecking.contains(folder)) + return true; + return false; + } + //----------------------------------------------------------------------------- void ImapAccountBase::handleBodyStructure( QDataStream & stream, KMMessage * msg, const AttachmentStrategy *as ) diff --git a/imapaccountbase.h b/imapaccountbase.h index 85cf09bd3..f926191ef 100644 --- a/imapaccountbase.h +++ b/imapaccountbase.h @@ -184,6 +184,14 @@ class AttachmentStrategy; */ void processNewMailSingleFolder(KMFolder* folder); + /** + * Check whether we're checking for new mail + * and the folder is included + */ + bool checkingMail( KMFolder *folder ); + + bool checkingMail() { return NetworkAccount::checkingMail(); } + /** * Set whether the current listDirectory should create an INBOX */ diff --git a/kmfolder.cpp b/kmfolder.cpp index 6be83c187..82bab4b3d 100644 --- a/kmfolder.cpp +++ b/kmfolder.cpp @@ -79,6 +79,8 @@ KMFolder::KMFolder( KMFolderDir* aParent, const QString& aFolderName, SIGNAL( numUnreadMsgsChanged( KMFolder* ) ) ); connect( mStorage, SIGNAL( syncRunning( KMFolder*, bool ) ), SIGNAL( syncRunning( KMFolder*, bool ) ) ); + connect( mStorage, SIGNAL( removed( KMFolder*, bool ) ), + SIGNAL( removed( KMFolder*, bool ) ) ); //FIXME: Centralize all the readConfig calls somehow - Zack mStorage->readConfig(); @@ -414,9 +416,9 @@ int KMFolder::create( bool imap ) return mStorage->create( imap ); } -int KMFolder::remove() +void KMFolder::remove() { - return mStorage->remove(); + mStorage->remove(); } int KMFolder::expunge() diff --git a/kmfolder.h b/kmfolder.h index 79ed46e2a..90f2e07c3 100644 --- a/kmfolder.h +++ b/kmfolder.h @@ -252,7 +252,7 @@ public: of the folder in memory. Note that the folder is closed during this process, whether there are others using it or not. @see KMFolder::removeContents */ - int remove(); + void remove(); /** Delete entire folder. Forces a close *but* opens the folder again afterwards. Returns errno(3) error code or zero on @@ -504,6 +504,9 @@ signals: // Emitted by KMFolderCachedIMAP to signal syncing void syncRunning( KMFolder*, bool ); + /** Emitted when a folder was removed */ + void removed(KMFolder*, bool); + public slots: /** Incrementally update the index if possible else call writeIndex */ int updateIndex(); diff --git a/kmfoldercachedimap.cpp b/kmfoldercachedimap.cpp index f33241e59..f75811123 100644 --- a/kmfoldercachedimap.cpp +++ b/kmfoldercachedimap.cpp @@ -123,9 +123,11 @@ KMFolderCachedImap::KMFolderCachedImap( KMFolder* folder, const char* aName ) KConfig* config = KMKernel::config(); KConfigGroupSaver saver(config, "Folder-" + idString()); if (mImapPath.isEmpty()) mImapPath = config->readEntry("ImapPath"); - if (aName == "INBOX" && mImapPath == "/INBOX/") + if (QString(aName).upper() == "INBOX" && mImapPath == "/INBOX/") { mLabel = i18n("inbox"); + // for the icon + folder->setSystemFolder(true); } mNoContent = config->readBoolEntry("NoContent", FALSE); mReadOnly = config->readBoolEntry("ReadOnly", FALSE); @@ -156,10 +158,9 @@ KMFolderCachedImap::~KMFolderCachedImap() if (kmkernel->undoStack()) kmkernel->undoStack()->folderDestroyed( folder() ); } -int KMFolderCachedImap::remove() +void KMFolderCachedImap::remove() { mFolderRemoved = true; - int rc = KMFolderMaildir::remove(); if( mRemoveRightAway ) { // This is the account folder of an account that was just removed @@ -175,8 +176,7 @@ int KMFolderCachedImap::remove() // from the cache or if it's new on the server. The file is removed // during the sync } - - return rc; + FolderStorage::remove(); } QString KMFolderCachedImap::uidCacheLocation() const diff --git a/kmfoldercachedimap.h b/kmfoldercachedimap.h index e50b89295..42edc08cd 100644 --- a/kmfoldercachedimap.h +++ b/kmfoldercachedimap.h @@ -87,7 +87,7 @@ public: virtual KMFolderType folderType() const { return KMFolderTypeCachedImap; } /** Remove this folder */ - virtual int remove(); + virtual void remove(); /** Synchronize this folder and it's subfolders with the server */ virtual void serverSync( bool suppressDialog ); diff --git a/kmfolderimap.cpp b/kmfolderimap.cpp index 3989e1168..33cd42c09 100644 --- a/kmfolderimap.cpp +++ b/kmfolderimap.cpp @@ -54,6 +54,7 @@ KMFolderImap::KMFolderImap(KMFolder* folder, const char* aName) mCheckFlags = TRUE; mCheckMail = TRUE; mCheckingValidity = FALSE; + mAlreadyRemoved = false; KConfig* config = KMKernel::config(); KConfigGroupSaver saver(config, "Folder-" + idString()); @@ -78,7 +79,7 @@ KMFolderImap::~KMFolderImap() ongoing operations and reset mailcheck if we were deleted during an ongoing mailcheck of our account. Not very gracefull, but safe, and the only way I can see to reset the account state cleanly. */ - if ( mAccount->checkingMail() ) { + if ( mAccount->checkingMail( folder() ) ) { mAccount->killAllJobs(); } } @@ -173,12 +174,20 @@ void KMFolderImap::writeConfig() } //----------------------------------------------------------------------------- -void KMFolderImap::removeOnServer() +void KMFolderImap::remove() { + if (mAlreadyRemoved) { + // override + FolderStorage::remove(); + return; + } KURL url = mAccount->getUrl(); url.setPath(imapPath()); - if ( mAccount->makeConnection() != ImapAccountBase::Connected ) + if ( mAccount->makeConnection() == ImapAccountBase::Error ) + { + emit removed(folder(), false); return; + } KIO::SimpleJob *job = KIO::file_delete(url, FALSE); KIO::Scheduler::assignJobToSlave(mAccount->slave(), job); ImapAccountBase::jobData jd(url.url()); @@ -197,9 +206,10 @@ void KMFolderImap::slotRemoveFolderResult(KIO::Job *job) { mAccount->slotSlaveError( mAccount->slave(), job->error(), job->errorText() ); + emit removed(folder(), false); } else { mAccount->displayProgress(); - kmkernel->imapFolderMgr()->remove( folder() ); + FolderStorage::remove(); } } @@ -578,7 +588,10 @@ void KMFolderImap::slotListResult( QStringList mSubfolderNames, && mSubfolderNames.findIndex(node->name()) == -1) { kdDebug(5006) << node->name() << " disappeared." << endl; - kmkernel->imapFolderMgr()->remove(static_cast(node)); + // remove the folder without server round trip + KMFolder* fld = static_cast(node); + static_cast(fld->storage())->setAlreadyRemoved(true); + kmkernel->imapFolderMgr()->remove(fld); node = folder()->child()->first(); } else node = folder()->child()->next(); diff --git a/kmfolderimap.h b/kmfolderimap.h index c41faadcc..4906c9661 100644 --- a/kmfolderimap.h +++ b/kmfolderimap.h @@ -116,7 +116,7 @@ public: virtual int rename( const QString& newName, KMFolderDir *aParent = 0 ); /** Remove the IMAP folder on the server and if successful also locally */ - virtual void removeOnServer(); + virtual void remove(); /** Automatically expunge deleted messages when leaving the folder */ bool autoExpunge(); @@ -263,6 +263,12 @@ public: /** Return the trash folder. */ KMFolder* trashFolder() const; + /** + * Mark the folder as already removed from the server + * If the folder is removed the server will not be queried anymore + */ + void setAlreadyRemoved(bool removed) { mAlreadyRemoved = removed; } + signals: void folderComplete(KMFolderImap *folder, bool success); @@ -383,6 +389,7 @@ protected: private: bool mCheckingValidity; QDict mMetaDataMap; + bool mAlreadyRemoved; }; #endif // kmfolderimap_h diff --git a/kmfoldermgr.cpp b/kmfoldermgr.cpp index 573e97833..112032b73 100644 --- a/kmfoldermgr.cpp +++ b/kmfoldermgr.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include "kmmainwin.h" #include "kmfiltermgr.h" @@ -35,6 +36,7 @@ KMFolderMgr::KMFolderMgr(const QString& aBasePath, KMFolderDirType dirType): mQuiet = 0; mChanged = FALSE; setBasePath(aBasePath); + mRemoveOrig = 0; } @@ -307,26 +309,54 @@ KMFolder* KMFolderMgr::findOrCreate(const QString& aFolderName, bool sysFldr) //----------------------------------------------------------------------------- void KMFolderMgr::remove(KMFolder* aFolder) { - assert(aFolder != 0); - + if (!aFolder) return; + // remember the original folder to trigger contentsChanged later + if (!mRemoveOrig) mRemoveOrig = aFolder; + if (aFolder->child()) + { + // call remove for every child + KMFolderNode* node; + QPtrListIterator it(*aFolder->child()); + for ( ; (node = it.current()); ) + { + ++it; + if (node->isDir()) continue; + KMFolder *folder = static_cast(node); + remove(folder); + } + } emit folderRemoved(aFolder); - removeFolderAux(aFolder); + removeFolder(aFolder); +} - contentsChanged(); +void KMFolderMgr::removeFolder(KMFolder* aFolder) +{ + connect(aFolder, SIGNAL(removed(KMFolder*, bool)), + this, SLOT(removeFolderAux(KMFolder*, bool))); + aFolder->remove(); } -void KMFolderMgr::removeFolderAux(KMFolder* aFolder) +void KMFolderMgr::removeFolderAux(KMFolder* aFolder, bool success) { + if (!success) { + mRemoveOrig = 0; + return; + } + KMFolderDir* fdir = aFolder->parent(); KMFolderNode* fN; - for (fN = fdir->first(); fN != 0; fN = fdir->next()) + for (fN = fdir->first(); fN != 0; fN = fdir->next()) { if (fN->isDir() && (fN->name() == "." + aFolder->fileName() + ".directory")) { removeDirAux(static_cast(fN)); break; } - aFolder->remove(); + } aFolder->parent()->remove(aFolder); - // mDir.remove(aFolder); + if (aFolder == mRemoveOrig) { + // call only if we're removing the original parent folder + contentsChanged(); + mRemoveOrig = 0; + } if (kmkernel->filterMgr()) kmkernel->filterMgr()->folderRemoved(aFolder,0); } @@ -334,13 +364,6 @@ void KMFolderMgr::removeDirAux(KMFolderDir* aFolderDir) { QDir dir; QString folderDirLocation = aFolderDir->path(); - KMFolderNode* fN; - for (fN = aFolderDir->first(); fN != 0; fN = aFolderDir->first()) { - if (fN->isDir()) - removeDirAux(static_cast(fN)); - else - removeFolderAux(static_cast(fN)); - } aFolderDir->clear(); aFolderDir->parent()->remove(aFolderDir); dir.rmdir(folderDirLocation); diff --git a/kmfoldermgr.h b/kmfoldermgr.h index 1607fe0c0..a7b059414 100644 --- a/kmfoldermgr.h +++ b/kmfoldermgr.h @@ -115,6 +115,9 @@ public slots: void compactAll(); void expireAll(); + /** Called from KMFolder::remove when the folderstorage was removed */ + void removeFolderAux(KMFolder* obsoleteFolder, bool success); + signals: /** Emitted when the list of folders has changed. This signal is a hook where clients like the KMFolderTree tree-view can connect. The signal @@ -152,7 +155,7 @@ protected: void compactAllAux(KMFolderDir* dir); /** Auxillary function to facilitate removal of a folder */ - void removeFolderAux(KMFolder* aFolder); + void removeFolder(KMFolder* aFolder); /** Auxillary function to facilitate removal of a folder directory */ void removeDirAux(KMFolderDir* aFolderDir); @@ -161,6 +164,7 @@ protected: KMFolderRootDir mDir; int mQuiet; bool mChanged; + KMFolder* mRemoveOrig; }; #endif /*kmfoldermgr_h*/ diff --git a/kmfoldertree.cpp b/kmfoldertree.cpp index becaa6900..5a6c25226 100644 --- a/kmfoldertree.cpp +++ b/kmfoldertree.cpp @@ -166,7 +166,8 @@ void KMFolderTreeItem::init() setType(Root); else if (mFolder->isSystemFolder()) { if (mFolder == kmkernel->inboxFolder() - || mFolder->folderType() == KMFolderTypeImap) + || mFolder->folderType() == KMFolderTypeImap + || mFolder->folderType() == KMFolderTypeCachedImap) setType(Inbox); else if (mFolder == kmkernel->outboxFolder()) setType(Outbox); diff --git a/kmmainwidget.cpp b/kmmainwidget.cpp index ce9370aba..1a7a666dc 100644 --- a/kmmainwidget.cpp +++ b/kmmainwidget.cpp @@ -1006,7 +1006,7 @@ void KMMainWidget::slotRemoveFolder() } } if (mFolder->folderType() == KMFolderTypeImap) - static_cast(mFolder->storage())->removeOnServer(); + kmkernel->imapFolderMgr()->remove(mFolder); else if (mFolder->folderType() == KMFolderTypeSearch) kmkernel->searchFolderMgr()->remove(mFolder); else