00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
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 "kmfoldermgr.h"
00036 #include "imapaccountbase.h"
00037 #include "kmacctimap.h"
00038 #include "kmacctcachedimap.h"
00039 #include "kmcommands.h"
00040 #include "kmmsgbase.h"
00041 #include "undostack.h"
00042
00043 #include <kdebug.h>
00044 #include <kurl.h>
00045 #include <kio/scheduler.h>
00046 #include <kio/job.h>
00047 #include <kio/global.h>
00048 #include <klocale.h>
00049 #include <config.h>
00050
00051 #include <qmap.h>
00052
00053 using namespace KMail;
00054
00055 RenameJob::RenameJob( FolderStorage* storage, const QString& newName,
00056 KMFolderDir* newParent )
00057 : FolderJob( 0, tOther, (storage ? storage->folder() : 0) ),
00058 mStorage( storage ), mNewParent( newParent ),
00059 mNewName( newName ), mNewFolder( 0 )
00060 {
00061 mStorageTempOpened = 0;
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
00079 KMFolderType type = mStorage->folderType();
00080 if ( ( type == KMFolderTypeMbox || type == KMFolderTypeMaildir ) &&
00081 mNewParent->type() == KMStandardDir &&
00082 mStorage->folderType() != KMFolderTypeCachedImap )
00083 {
00084
00085 mStorage->rename( mNewName, mNewParent );
00086 emit renameDone( mNewName, true );
00087 deleteLater();
00088 return;
00089 }
00090
00091 KMFolderMgr* folderMgr = kmkernel->folderMgr();
00092 if ( mNewParent->type() == KMImapDir ) {
00093 folderMgr = kmkernel->imapFolderMgr();
00094 } else if ( mNewParent->type() == KMDImapDir ) {
00095 folderMgr = kmkernel->dimapFolderMgr();
00096 }
00097
00098
00099 KConfig *config = KMKernel::config();
00100 KConfigGroupSaver saver(config, "General");
00101 int deftype = config->readNumEntry("default-mailbox-format", 1);
00102 if ( deftype < 0 || deftype > 1 ) deftype = 1;
00103
00104
00105 KMFolderType typenew =
00106 ( deftype == 0 ) ? KMFolderTypeMbox : KMFolderTypeMaildir;
00107 if ( mNewParent->owner() )
00108 typenew = mNewParent->owner()->folderType();
00109
00110 mNewFolder = folderMgr->createFolder( mNewName, false, typenew, mNewParent );
00111 if ( !mNewFolder )
00112 {
00113 kdWarning(5006) << k_funcinfo << "could not create folder" << endl;
00114 emit renameDone( mNewName, false );
00115 deleteLater();
00116 return;
00117 }
00118 kdDebug(5006)<< "RenameJob::rename - " << mStorage->folder()->idString()
00119 << " |=> " << mNewFolder->idString() << endl;
00120
00121 if ( mNewParent->type() == KMImapDir )
00122 {
00123
00124
00125
00126 connect( kmkernel->imapFolderMgr(), SIGNAL( changed() ),
00127 this, SLOT( slotMoveMessages() ) );
00128 KMFolderImap* imapFolder =
00129 static_cast<KMFolderImap*>(mNewParent->owner()->storage());
00130 imapFolder->createFolder( mNewName, QString::null, false );
00131 } else if ( mNewParent->type() == KMDImapDir )
00132 {
00133 KMFolderCachedImap* newStorage = static_cast<KMFolderCachedImap*>(mNewFolder->storage());
00134 KMFolderCachedImap* owner = static_cast<KMFolderCachedImap*>(mNewParent->owner()->storage());
00135 newStorage->initializeFrom( owner );
00136 moveSubFoldersBeforeMessages();
00137 } else if ( mStorage->folderType() == KMFolderTypeCachedImap )
00138 {
00139
00140 moveSubFoldersBeforeMessages();
00141 } else
00142 {
00143
00144 slotMoveMessages();
00145 }
00146 } else
00147 {
00148
00149 if ( mStorage->folderType() != KMFolderTypeImap )
00150 {
00151
00152 mStorage->rename( mNewName );
00153 emit renameDone( mNewName, true );
00154 deleteLater();
00155 return;
00156 }
00157 if ( mOldImapPath.isEmpty() )
00158 {
00159
00160 emit renameDone( mNewName, false );
00161 deleteLater();
00162 return;
00163 } else if ( mOldName == mNewName || mOldImapPath == "/INBOX/" ) {
00164 emit renameDone( mNewName, true );
00165 deleteLater();
00166 return;
00167 }
00168 ImapAccountBase* account = static_cast<KMFolderImap*>(mStorage)->account();
00169
00170 mNewImapPath = mOldImapPath;
00171 mNewImapPath = mNewImapPath.replace( mOldName, mNewName );
00172 KURL src( account->getUrl() );
00173 src.setPath( mOldImapPath );
00174 KURL dst( account->getUrl() );
00175 dst.setPath( mNewImapPath );
00176 KIO::SimpleJob *job = KIO::rename( src, dst, true );
00177 kdDebug(5006)<< "RenameJob::rename - " << src.prettyURL()
00178 << " |=> " << dst.prettyURL() << endl;
00179 ImapAccountBase::jobData jd( src.url() );
00180 account->insertJob( job, jd );
00181 KIO::Scheduler::assignJobToSlave( account->slave(), job );
00182 connect( job, SIGNAL(result(KIO::Job*)),
00183 SLOT(slotRenameResult(KIO::Job*)) );
00184 }
00185 }
00186
00187 void RenameJob::slotRenameResult( KIO::Job *job )
00188 {
00189 ImapAccountBase* account = static_cast<KMFolderImap*>(mStorage)->account();
00190 ImapAccountBase::JobIterator it = account->findJob(job);
00191 if ( it == account->jobsEnd() )
00192 {
00193 emit renameDone( mNewName, false );
00194 deleteLater();
00195 return;
00196 }
00197 if ( job->error() )
00198 {
00199 account->handleJobError( job, i18n("Error while renaming a folder.") );
00200 emit renameDone( mNewName, false );
00201 deleteLater();
00202 return;
00203 }
00204 account->removeJob(it);
00205
00206 if ( mStorage->folderType() == KMFolderTypeImap )
00207 static_cast<KMFolderImap*>(mStorage)->setImapPath( mNewImapPath );
00208
00209 account->changeSubscription( false, mOldImapPath );
00210
00211 account->changeSubscription( true, mNewImapPath );
00212
00213
00214 mStorage->rename( mNewName );
00215
00216 emit renameDone( mNewName, true );
00217 deleteLater();
00218 }
00219
00220 void RenameJob::slotMoveMessages()
00221 {
00222 kdDebug(5006) << k_funcinfo << endl;
00223 disconnect( kmkernel->imapFolderMgr(), SIGNAL( changed() ),
00224 this, SLOT( slotMoveMessages() ) );
00225 mStorage->blockSignals( true );
00226
00227 QPtrList<KMMsgBase> msgList;
00228 if ( !mStorage->isOpened() )
00229 mStorageTempOpened = mStorage->open() ? mStorage : 0;
00230 for ( int i = 0; i < mStorage->count(); i++ )
00231 {
00232 KMMsgBase* msgBase = mStorage->getMsgBase( i );
00233 assert( msgBase );
00234 msgList.append( msgBase );
00235 }
00236 if ( msgList.count() == 0 )
00237 {
00238 slotMoveCompleted( 0 );
00239 } else
00240 {
00241 KMCommand *command = new KMMoveCommand( mNewFolder, msgList );
00242 connect( command, SIGNAL( completed( KMCommand * ) ),
00243 this, SLOT( slotMoveCompleted( KMCommand * ) ) );
00244 command->start();
00245 }
00246 }
00247
00248 void RenameJob::slotMoveCompleted( KMCommand* command )
00249 {
00250 kdDebug(5006) << k_funcinfo << (command?command->result():0) << endl;
00251 if ( mStorageTempOpened ) {
00252 mStorageTempOpened->close();
00253 mStorageTempOpened = 0;
00254 }
00255 if ( command ) {
00256
00257 disconnect( command, SIGNAL( completed( KMCommand * ) ),
00258 this, SLOT( slotMoveCompleted( KMCommand * ) ) );
00259 }
00260 if ( !command || command->result() == KMCommand::OK )
00261 {
00262 kdDebug(5006) << "deleting old folder" << endl;
00263
00264
00265 QString oldconfig = "Folder-" + mStorage->folder()->idString();
00266 KConfig* config = KMKernel::config();
00267 QMap<QString, QString> entries = config->entryMap( oldconfig );
00268 KConfigGroupSaver saver(config, "Folder-" + mNewFolder->idString());
00269 for ( QMap<QString, QString>::Iterator it = entries.begin();
00270 it != entries.end(); ++it )
00271 {
00272 if ( it.key() == "Id" || it.key() == "ImapPath" ||
00273 it.key() == "UidValidity" )
00274 continue;
00275 config->writeEntry( it.key(), it.data() );
00276 }
00277 mNewFolder->readConfig( config );
00278
00279 if ( mNewFolder->child() &&
00280 ( mNewFolder->storage()->hasChildren() == FolderStorage::HasNoChildren ) )
00281 mNewFolder->storage()->updateChildrenState();
00282
00283
00284 mStorage->blockSignals( false );
00285 if ( mStorage->folderType() == KMFolderTypeImap )
00286 {
00287 kmkernel->imapFolderMgr()->remove( mStorage->folder() );
00288 } else if ( mStorage->folderType() == KMFolderTypeCachedImap )
00289 {
00290
00291 KMAcctCachedImap* acct = static_cast<KMFolderCachedImap*>(mStorage)->account();
00292 if ( acct )
00293 acct->addDeletedFolder( mOldImapPath );
00294 kmkernel->dimapFolderMgr()->remove( mStorage->folder() );
00295 } else if ( mStorage->folderType() == KMFolderTypeSearch )
00296 {
00297
00298 kdWarning(5006) << k_funcinfo << "cannot remove a search folder" << endl;
00299 } else {
00300 kmkernel->folderMgr()->remove( mStorage->folder() );
00301 }
00302
00303 emit renameDone( mNewName, true );
00304 } else
00305 {
00306 kdDebug(5006) << "rollback - deleting folder" << endl;
00307
00308 kmkernel->undoStack()->undo();
00309
00310 if ( mNewFolder->folderType() == KMFolderTypeImap )
00311 {
00312 kmkernel->imapFolderMgr()->remove( mNewFolder );
00313 } else if ( mNewFolder->folderType() == KMFolderTypeCachedImap )
00314 {
00315
00316 KMFolderCachedImap* folder = static_cast<KMFolderCachedImap*>(mNewFolder->storage());
00317 KMAcctCachedImap* acct = folder->account();
00318 if ( acct )
00319 acct->addDeletedFolder( folder->imapPath() );
00320 kmkernel->dimapFolderMgr()->remove( mNewFolder );
00321 } else if ( mNewFolder->folderType() == KMFolderTypeSearch )
00322 {
00323
00324 kdWarning(5006) << k_funcinfo << "cannot remove a search folder" << endl;
00325 } else {
00326 kmkernel->folderMgr()->remove( mNewFolder );
00327 }
00328
00329 emit renameDone( mNewName, false );
00330 }
00331 delete this;
00332 }
00333
00334 void RenameJob::slotMoveSubFolders( QString newName, bool success )
00335 {
00336 if ( !success ) {
00337 emit renameDone( newName, false );
00338 } else {
00339 KMFolderDir* child = mStorage->folder()->child();
00340 if ( child && child->first() )
00341 {
00342 KMFolderNode* node = child->first();
00343 {
00344 FolderStorage* childStorage = static_cast<KMFolder*>(node)->storage();
00345 if ( !mNewFolder->child() )
00346 mNewFolder->createChildFolder();
00347 RenameJob* job = new RenameJob( childStorage, childStorage->name(),
00348 mNewFolder->child() );
00349 connect( job, SIGNAL( renameDone( QString, bool ) ),
00350 this, SLOT( slotMoveSubFolders( QString, bool ) ) );
00351 job->start();
00352 }
00353 }
00354 else slotMoveMessages();
00355 }
00356 }
00357
00358 void RenameJob::moveSubFoldersBeforeMessages()
00359 {
00360
00361 KMFolderDir* child = mStorage->folder()->child();
00362 if ( child )
00363 slotMoveSubFolders( "", true );
00364 else slotMoveMessages();
00365 }
00366
00367 #include "renamejob.moc"