kmail Library API Documentation

renamejob.cpp

00001 
00029 #include "renamejob.h"
00030 #include "kmfolderimap.h"
00031 #include "kmfoldercachedimap.h"
00032 #include "folderstorage.h"
00033 #include "kmfolder.h"
00034 #include "kmfolderdir.h"
00035 #include "kmfoldertype.h"
00036 #include "kmfoldermgr.h"
00037 #include "imapaccountbase.h"
00038 #include "kmacctimap.h"
00039 #include "kmacctcachedimap.h"
00040 #include "kmcommands.h"
00041 #include "kmmsgbase.h"
00042 #include "undostack.h"
00043 
00044 #include <kdebug.h>
00045 #include <kurl.h>
00046 #include <kio/scheduler.h>
00047 #include <kio/job.h>
00048 #include <kio/global.h>
00049 #include <klocale.h>
00050 #include <config.h>
00051 
00052 #include <qmap.h>
00053 
00054 using namespace KMail;
00055 
00056 RenameJob::RenameJob( FolderStorage* storage, const QString& newName, 
00057     KMFolderDir* newParent )
00058  : FolderJob( 0, tOther, (storage ? storage->folder() : 0) ),
00059    mStorage( storage ), mNewParent( newParent ),
00060    mNewName( newName ), mNewFolder( 0 )
00061 {
00062   mOldName = storage->name();
00063   if ( storage->folderType() == KMFolderTypeImap ) {
00064     mOldImapPath = static_cast<KMFolderImap*>(storage)->imapPath();
00065   } else if ( storage->folderType() == KMFolderTypeCachedImap ) {
00066     mOldImapPath = static_cast<KMFolderCachedImap*>(storage)->imapPath();
00067   }
00068 }
00069 
00070 RenameJob::~RenameJob()
00071 {
00072 }
00073 
00074 void RenameJob::execute()
00075 {
00076   if ( mNewParent )
00077   {
00078     // move the folder to a different parent
00079     KMFolderType type = mStorage->folderType();
00080     if ( ( type == KMFolderTypeMbox || type == KMFolderTypeMaildir ) &&
00081          mNewParent->type() == KMStandardDir )
00082     {
00083       // local folders can handle this on their own
00084       mStorage->rename( mNewName, mNewParent );
00085       emit renameDone( mNewName, true );
00086       deleteLater();
00087       return;
00088     }
00089     // first create the new folder
00090     KMFolderMgr* folderMgr = kmkernel->folderMgr();
00091     if ( mNewParent->type() == KMImapDir ) {
00092       folderMgr = kmkernel->imapFolderMgr();
00093     } else if ( mNewParent->type() == KMDImapDir ) {
00094       folderMgr = kmkernel->dimapFolderMgr();
00095     }
00096 
00097     // get the default mailbox type
00098     KConfig *config = KMKernel::config();
00099     KConfigGroupSaver saver(config, "General");
00100     int deftype = config->readNumEntry("default-mailbox-format", 1);
00101     if ( deftype < 0 || deftype > 1 ) deftype = 1;
00102 
00103     // the type of the new folder
00104     KMFolderType typenew = 
00105       ( deftype == 0 ) ? KMFolderTypeMbox : KMFolderTypeMaildir;
00106     if ( mNewParent->owner() )
00107       typenew = mNewParent->owner()->folderType();
00108 
00109     mNewFolder = folderMgr->createFolder( mNewName, false, typenew, mNewParent );
00110     if ( !mNewFolder )
00111     {
00112       kdWarning(5006) << k_funcinfo << "could not create folder" << endl;
00113       emit renameDone( mNewName, false );
00114       deleteLater();
00115       return;
00116     }
00117     kdDebug(5006)<< "RenameJob::rename - " << mStorage->folder()->idString()
00118       << " |=> " << mNewFolder->idString() << endl;
00119 
00120     if ( mNewParent->type() == KMImapDir )
00121     {
00122       // online imap
00123       // create it on the server and wait for the folderAdded signal
00124       connect( kmkernel->imapFolderMgr(), SIGNAL( changed() ),
00125           this, SLOT( slotMoveMessages() ) );
00126       KMFolderImap* imapFolder = 
00127         static_cast<KMFolderImap*>(mNewParent->owner()->storage());
00128       imapFolder->createFolder( mNewName );
00129     } else if ( mNewParent->type() == KMDImapDir )
00130     {
00131       KMFolderCachedImap* newStorage = static_cast<KMFolderCachedImap*>(mNewFolder->storage());
00132       KMFolderCachedImap* owner = static_cast<KMFolderCachedImap*>(mNewParent->owner()->storage());
00133       newStorage->initializeFrom( owner );
00134       slotMoveMessages();
00135     } else
00136     {
00137       // local
00138       slotMoveMessages();
00139     }
00140   } else
00141   {
00142     // only rename the folder
00143     if ( mStorage->folderType() != KMFolderTypeImap )
00144     {
00145       // local and dimap folder handle this directly
00146       mStorage->rename( mNewName );
00147       emit renameDone( mNewName, true );
00148       deleteLater();
00149       return;
00150     }
00151     if ( mOldImapPath.isEmpty() )
00152     { 
00153       // sanity
00154       emit renameDone( mNewName, false );
00155       deleteLater();
00156       return;
00157     } else if ( mOldName == mNewName || mOldImapPath == "/INBOX/" ) {
00158       emit renameDone( mNewName, true ); // noop
00159       deleteLater();
00160       return;
00161     }
00162     ImapAccountBase* account = static_cast<KMFolderImap*>(mStorage)->account();
00163     // first rename it on the server
00164     mNewImapPath = mOldImapPath;
00165     mNewImapPath = mNewImapPath.replace( mOldName, mNewName );
00166     KURL src( account->getUrl() );
00167     src.setPath( mOldImapPath );
00168     KURL dst( account->getUrl() );
00169     dst.setPath( mNewImapPath );
00170     KIO::SimpleJob *job = KIO::rename( src, dst, true );
00171     kdDebug(5006)<< "RenameJob::rename - " << src.prettyURL()
00172       << " |=> " << dst.prettyURL() << endl;
00173     ImapAccountBase::jobData jd( src.url() );
00174     account->insertJob( job, jd );
00175     KIO::Scheduler::assignJobToSlave( account->slave(), job );
00176     connect( job, SIGNAL(result(KIO::Job*)),
00177         SLOT(slotRenameResult(KIO::Job*)) );
00178   }
00179 }
00180 
00181 void RenameJob::slotRenameResult( KIO::Job *job )
00182 {
00183   ImapAccountBase* account = static_cast<KMFolderImap*>(mStorage)->account();
00184   ImapAccountBase::JobIterator it = account->findJob(job);
00185   if ( it == account->jobsEnd() )
00186   {
00187     emit renameDone( mNewName, false );
00188     deleteLater();
00189     return;
00190   }
00191   if ( job->error() )
00192   {
00193     account->handleJobError( job, i18n("Error while renaming a folder.") );
00194     emit renameDone( mNewName, false );
00195     deleteLater();
00196     return;
00197   }
00198   account->removeJob(it);
00199   // set the new path
00200   if ( mStorage->folderType() == KMFolderTypeImap )
00201     static_cast<KMFolderImap*>(mStorage)->setImapPath( mNewImapPath );
00202   // unsubscribe old (we don't want ghosts)
00203   account->changeSubscription( false, mOldImapPath );
00204   // subscribe new
00205   account->changeSubscription( true, mNewImapPath );
00206 
00207   // local part (will set the new name)
00208   mStorage->rename( mNewName );
00209 
00210   emit renameDone( mNewName, true );
00211   deleteLater();
00212 }
00213 
00214 void RenameJob::slotMoveMessages()
00215 {
00216   kdDebug(5006) << k_funcinfo << endl;
00217   disconnect( kmkernel->imapFolderMgr(), SIGNAL( changed() ),
00218       this, SLOT( slotMoveMessages() ) );
00219   mStorage->blockSignals( true );
00220   // move all messages to the new folder
00221   QPtrList<KMMsgBase> msgList;
00222   for ( int i = 0; i < mStorage->count(); i++ )
00223   {
00224     KMMsgBase* msgBase = mStorage->getMsgBase( i );
00225     assert( msgBase );
00226     msgList.append( msgBase );
00227   }
00228   if ( msgList.count() == 0 ) 
00229   {
00230     slotMoveCompleted( 0 );
00231   } else
00232   {
00233     KMCommand *command = new KMMoveCommand( mNewFolder, msgList );
00234     connect( command, SIGNAL( completed( KMCommand * ) ),
00235         this, SLOT( slotMoveCompleted( KMCommand * ) ) );
00236     command->start();
00237   }
00238 }
00239 
00240 void RenameJob::slotMoveCompleted( KMCommand* command )
00241 {
00242   kdDebug(5006) << k_funcinfo << (command?command->result():0) << endl;
00243   disconnect( command, SIGNAL( completed( KMCommand * ) ),
00244       this, SLOT( slotMoveCompleted( KMCommand * ) ) );
00245   if ( !command || command->result() == KMCommand::OK ) 
00246   {
00247     kdDebug(5006) << "deleting old folder" << endl;
00248     // move complete or not necessary
00249     // save our settings
00250     QString oldconfig = "Folder-" + mStorage->folder()->idString();
00251     KConfig* config = KMKernel::config();
00252     QMap<QString, QString> entries = config->entryMap( oldconfig );
00253     KConfigGroupSaver saver(config, "Folder-" + mNewFolder->idString());
00254     for ( QMap<QString, QString>::Iterator it = entries.begin(); 
00255           it != entries.end(); ++it ) 
00256     {
00257       if ( it.key() == "Id" || it.key() == "ImapPath" || 
00258            it.key() == "UidValidity" )
00259         continue;
00260       config->writeEntry( it.key(), it.data() );
00261     }
00262     mNewFolder->readConfig( config );
00263       
00264     // delete the old folder
00265     mStorage->blockSignals( false );
00266     if ( mStorage->folderType() == KMFolderTypeImap )
00267     {
00268       kmkernel->imapFolderMgr()->remove( mStorage->folder() );
00269     } else if ( mStorage->folderType() == KMFolderTypeCachedImap ) 
00270     {
00271       // tell the account (see KMFolderCachedImap::listDirectory2)
00272       KMAcctCachedImap* acct = static_cast<KMFolderCachedImap*>(mStorage)->account();
00273       if ( acct )
00274         acct->addDeletedFolder( mOldImapPath );
00275       kmkernel->dimapFolderMgr()->remove( mStorage->folder() );
00276     } else if ( mStorage->folderType() == KMFolderTypeSearch ) 
00277     {
00278       // invalid
00279       kdWarning(5006) << k_funcinfo << "cannot remove a search folder" << endl;
00280     } else {
00281       kmkernel->folderMgr()->remove( mStorage->folder() );
00282     }
00283     
00284     emit renameDone( mNewName, true );
00285   } else 
00286   {
00287     kdDebug(5006) << "rollback - deleting folder" << endl;
00288     // move failed - rollback the last transaction
00289     kmkernel->undoStack()->undo();
00290     // .. and delete the new folder
00291     if ( mNewFolder->folderType() == KMFolderTypeImap )
00292     {
00293       kmkernel->imapFolderMgr()->remove( mNewFolder );
00294     } else if ( mNewFolder->folderType() == KMFolderTypeCachedImap ) 
00295     {
00296       // tell the account (see KMFolderCachedImap::listDirectory2)
00297       KMFolderCachedImap* folder = static_cast<KMFolderCachedImap*>(mNewFolder->storage());
00298       KMAcctCachedImap* acct = folder->account();
00299       if ( acct )
00300         acct->addDeletedFolder( folder->imapPath() );
00301       kmkernel->dimapFolderMgr()->remove( mNewFolder );
00302     } else if ( mNewFolder->folderType() == KMFolderTypeSearch ) 
00303     {
00304       // invalid
00305       kdWarning(5006) << k_funcinfo << "cannot remove a search folder" << endl;
00306     } else {
00307       kmkernel->folderMgr()->remove( mNewFolder );
00308     }
00309     
00310     emit renameDone( mNewName, false );
00311   }
00312   deleteLater();
00313 }
00314 
00315 #include "renamejob.moc"
KDE Logo
This file is part of the documentation for kmail Library Version 3.3.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Wed Jan 31 15:55:09 2007 by doxygen 1.4.2 written by Dimitri van Heesch, © 1997-2003