Fix recursive deletion of folders for imap. Works also for dimap (of course ;-))

Oh, well, and display a nice inbox icon for dimap.
CCMAIL: 43913-done@bugs.kde.org

svn path=/trunk/kdepim/; revision=296645
wilder-work
Carsten Burghardt 22 years ago
parent 6968cbda53
commit f968ff305d
  1. 5
      folderstorage.cpp
  2. 5
      folderstorage.h
  3. 8
      imapaccountbase.cpp
  4. 8
      imapaccountbase.h
  5. 6
      kmfolder.cpp
  6. 5
      kmfolder.h
  7. 10
      kmfoldercachedimap.cpp
  8. 2
      kmfoldercachedimap.h
  9. 23
      kmfolderimap.cpp
  10. 9
      kmfolderimap.h
  11. 53
      kmfoldermgr.cpp
  12. 6
      kmfoldermgr.h
  13. 3
      kmfoldertree.cpp
  14. 2
      kmmainwidget.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));
}

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

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

@ -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
*/

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

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

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

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

@ -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<KMFolder*>(node));
// remove the folder without server round trip
KMFolder* fld = static_cast<KMFolder*>(node);
static_cast<KMFolderImap*>(fld->storage())->setAlreadyRemoved(true);
kmkernel->imapFolderMgr()->remove(fld);
node = folder()->child()->first();
}
else node = folder()->child()->next();

@ -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<KMMsgMetaData> mMetaDataMap;
bool mAlreadyRemoved;
};
#endif // kmfolderimap_h

@ -21,6 +21,7 @@
#include <klocale.h>
#include <kmessagebox.h>
#include <kconfig.h>
#include <kdebug.h>
#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<KMFolderNode> it(*aFolder->child());
for ( ; (node = it.current()); )
{
++it;
if (node->isDir()) continue;
KMFolder *folder = static_cast<KMFolder*>(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<KMFolderDir*>(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<KMFolderDir*>(fN));
else
removeFolderAux(static_cast<KMFolder*>(fN));
}
aFolderDir->clear();
aFolderDir->parent()->remove(aFolderDir);
dir.rmdir(folderDirLocation);

@ -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*/

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

@ -1006,7 +1006,7 @@ void KMMainWidget::slotRemoveFolder()
}
}
if (mFolder->folderType() == KMFolderTypeImap)
static_cast<KMFolderImap*>(mFolder->storage())->removeOnServer();
kmkernel->imapFolderMgr()->remove(mFolder);
else if (mFolder->folderType() == KMFolderTypeSearch)
kmkernel->searchFolderMgr()->remove(mFolder);
else

Loading…
Cancel
Save