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