renamejob.cpp
00001 /* 00002 * Copyright (c) 2004 Carsten Burghardt <burghardt@kde.org> 00003 * 00004 * This program is free software; you can redistribute it and/or modify 00005 * it under the terms of the GNU General Public License as published by 00006 * the Free Software Foundation; version 2 of the License 00007 * 00008 * This program is distributed in the hope that it will be useful, 00009 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00010 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00011 * GNU General Public License for more details. 00012 * 00013 * You should have received a copy of the GNU General Public License 00014 * along with this program; if not, write to the Free Software 00015 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00016 * 00017 * In addition, as a special exception, the copyright holders give 00018 * permission to link the code of this program with any edition of 00019 * the TQt library by Trolltech AS, Norway (or with modified versions 00020 * of TQt that use the same license as TQt), and distribute linked 00021 * combinations including the two. You must obey the GNU General 00022 * Public License in all respects for all of the code used other than 00023 * TQt. If you modify this file, you may extend this exception to 00024 * your version of the file, but you are not obligated to do so. If 00025 * you do not wish to do so, delete this exception statement from 00026 * your version. 00027 */ 00028 00029 #include "renamejob.h" 00030 #include "copyfolderjob.h" 00031 #include "kmfolderimap.h" 00032 #include "kmfoldercachedimap.h" 00033 #include "folderstorage.h" 00034 #include "kmfolder.h" 00035 #include "kmfolderdir.h" 00036 #include "kmfoldermgr.h" 00037 #include "imapaccountbase.h" 00038 #include "kmacctimap.h" 00039 #include "kmacctcachedimap.h" 00040 #include "kmmsgbase.h" 00041 00042 #include <kdebug.h> 00043 #include <kurl.h> 00044 #include <kio/scheduler.h> 00045 #include <kio/job.h> 00046 #include <kio/global.h> 00047 #include <klocale.h> 00048 #include <config.h> 00049 00050 #include <tqmap.h> 00051 00052 using namespace KMail; 00053 00054 template <typename T> static TQStringList imapPaths( FolderStorage* storage ) 00055 { 00056 TQStringList rv; 00057 rv.append( static_cast<T>( storage )->imapPath() ); 00058 KMFolderDir* dir = storage->folder()->child(); 00059 if ( dir ) { 00060 KMFolderNode *node = dir->first(); 00061 while ( node ) { 00062 if ( !node->isDir() ) { 00063 rv += imapPaths<T>( static_cast<KMFolder*>( node )->storage() ); 00064 } 00065 node = dir->next(); 00066 } 00067 } 00068 return rv; 00069 } 00070 00071 RenameJob::RenameJob( FolderStorage* storage, const TQString& newName, 00072 KMFolderDir* newParent ) 00073 : FolderJob( 0, tOther, (storage ? storage->folder() : 0) ), 00074 mStorage( storage ), mNewParent( newParent ), 00075 mNewName( newName ), mNewFolder( 0 ), mCopyFolderJob( 0 ) 00076 { 00077 mStorageTempOpened = 0; 00078 if ( storage ) { 00079 mOldName = storage->name(); 00080 if ( storage->folderType() == KMFolderTypeImap ) { 00081 mOldImapPath = static_cast<KMFolderImap*>(storage)->imapPath(); 00082 // mOldImapPaths = imapPaths<KMFolderImap*>( storage ); 00083 } else if ( storage->folderType() == KMFolderTypeCachedImap ) { 00084 mOldImapPath = static_cast<KMFolderCachedImap*>(storage)->imapPath(); 00085 mOldImapPaths = imapPaths<KMFolderCachedImap*>( storage ); 00086 } 00087 } 00088 } 00089 00090 RenameJob::~RenameJob() 00091 { 00092 } 00093 00094 // FIXME: move on the server for online imap given source and target are on the same server 00095 void RenameJob::execute() 00096 { 00097 if ( mNewParent ) 00098 { 00099 // move the folder to a different parent 00100 KMFolderType type = mStorage->folderType(); 00101 if ( ( type == KMFolderTypeMbox || type == KMFolderTypeMaildir ) && 00102 mNewParent->type() == KMStandardDir && 00103 mStorage->folderType() != KMFolderTypeCachedImap ) 00104 { 00105 // local folders can handle this on their own 00106 mStorage->rename( mNewName, mNewParent ); 00107 emit renameDone( mNewName, true ); 00108 deleteLater(); 00109 return; 00110 } 00111 // copy to the new folder 00112 mCopyFolderJob = new CopyFolderJob( mStorage, mNewParent ); 00113 connect( mCopyFolderJob, TQT_SIGNAL(folderCopyComplete(bool)), TQT_SLOT(folderCopyComplete(bool)) ); 00114 mCopyFolderJob->execute(); 00115 00116 } else 00117 { 00118 // only rename the folder 00119 if ( mStorage->folderType() != KMFolderTypeImap ) 00120 { 00121 // local and dimap folder handle this directly 00122 mStorage->rename( mNewName ); 00123 emit renameDone( mNewName, true ); 00124 deleteLater(); 00125 return; 00126 } 00127 if ( mOldImapPath.isEmpty() ) 00128 { 00129 // sanity 00130 emit renameDone( mNewName, false ); 00131 deleteLater(); 00132 return; 00133 } else if ( mOldName == mNewName || mOldImapPath == "/INBOX/" ) { 00134 emit renameDone( mNewName, true ); // noop 00135 deleteLater(); 00136 return; 00137 } 00138 ImapAccountBase* account = static_cast<KMFolderImap*>(mStorage)->account(); 00139 // first rename it on the server 00140 mNewImapPath = mOldImapPath; 00141 mNewImapPath = mNewImapPath.replace( mOldName, mNewName ); 00142 KURL src( account->getUrl() ); 00143 src.setPath( mOldImapPath ); 00144 KURL dst( account->getUrl() ); 00145 dst.setPath( mNewImapPath ); 00146 KIO::SimpleJob *job = KIO::rename( src, dst, true ); 00147 kdDebug(5006)<< "RenameJob::rename - " << src.prettyURL() 00148 << " |=> " << dst.prettyURL() << endl; 00149 ImapAccountBase::jobData jd( src.url() ); 00150 account->insertJob( job, jd ); 00151 KIO::Scheduler::assignJobToSlave( account->slave(), job ); 00152 connect( job, TQT_SIGNAL(result(KIO::Job*)), 00153 TQT_SLOT(slotRenameResult(KIO::Job*)) ); 00154 } 00155 } 00156 00157 void RenameJob::slotRenameResult( KIO::Job *job ) 00158 { 00159 ImapAccountBase* account = static_cast<KMFolderImap*>(mStorage)->account(); 00160 ImapAccountBase::JobIterator it = account->findJob(job); 00161 if ( it == account->jobsEnd() ) 00162 { 00163 emit renameDone( mNewName, false ); 00164 deleteLater(); 00165 return; 00166 } 00167 if ( job->error() ) 00168 { 00169 account->handleJobError( job, i18n("Error while renaming a folder.") ); 00170 emit renameDone( mNewName, false ); 00171 deleteLater(); 00172 return; 00173 } 00174 account->removeJob(it); 00175 // set the new path 00176 if ( mStorage->folderType() == KMFolderTypeImap ) 00177 static_cast<KMFolderImap*>(mStorage)->setImapPath( mNewImapPath ); 00178 // unsubscribe old (we don't want ghosts) 00179 account->changeSubscription( false, mOldImapPath ); 00180 // subscribe new 00181 account->changeSubscription( true, mNewImapPath ); 00182 00183 // local part (will set the new name) 00184 mStorage->rename( mNewName ); 00185 00186 emit renameDone( mNewName, true ); 00187 deleteLater(); 00188 } 00189 00190 void RenameJob::folderCopyComplete(bool success) 00191 { 00192 kdDebug(5006) << k_funcinfo << success << endl; 00193 if ( !success ) { 00194 kdWarning(5006) << k_funcinfo << "could not copy folder" << endl; 00195 emit renameDone( mNewName, false ); 00196 deleteLater(); 00197 return; 00198 } 00199 mNewFolder = mCopyFolderJob->targetFolder(); 00200 mCopyFolderJob = 0; 00201 00202 if ( mStorageTempOpened ) { 00203 mStorageTempOpened->close( "renamejob" ); 00204 mStorageTempOpened = 0; 00205 } 00206 00207 kdDebug(5006) << "deleting old folder" << endl; 00208 // move complete or not necessary 00209 // save our settings 00210 TQString oldconfig = "Folder-" + mStorage->folder()->idString(); 00211 KConfig* config = KMKernel::config(); 00212 TQMap<TQString, TQString> entries = config->entryMap( oldconfig ); 00213 KConfigGroupSaver saver(config, "Folder-" + mNewFolder->idString()); 00214 for ( TQMap<TQString, TQString>::Iterator it = entries.begin(); 00215 it != entries.end(); ++it ) 00216 { 00217 if ( it.key() == "Id" || it.key() == "ImapPath" || 00218 it.key() == "UidValidity" ) 00219 continue; 00220 config->writeEntry( it.key(), it.data() ); 00221 } 00222 mNewFolder->readConfig( config ); 00223 // make sure the children state is correct 00224 if ( mNewFolder->child() && 00225 ( mNewFolder->storage()->hasChildren() == FolderStorage::HasNoChildren ) ) 00226 mNewFolder->storage()->updateChildrenState(); 00227 00228 // delete the old folder 00229 mStorage->blockSignals( false ); 00230 if ( mStorage->folderType() == KMFolderTypeImap ) 00231 { 00232 kmkernel->imapFolderMgr()->remove( mStorage->folder() ); 00233 } else if ( mStorage->folderType() == KMFolderTypeCachedImap ) 00234 { 00235 // tell the account (see KMFolderCachedImap::listDirectory2) 00236 KMAcctCachedImap* acct = static_cast<KMFolderCachedImap*>(mStorage)->account(); 00237 if ( acct ) { 00238 for ( TQStringList::ConstIterator it = mOldImapPaths.constBegin(); it != mOldImapPaths.constEnd(); ++it ) 00239 acct->addDeletedFolder( *it ); 00240 } 00241 kmkernel->dimapFolderMgr()->remove( mStorage->folder() ); 00242 } else if ( mStorage->folderType() == KMFolderTypeSearch ) 00243 { 00244 // invalid 00245 kdWarning(5006) << k_funcinfo << "cannot remove a search folder" << endl; 00246 } else { 00247 kmkernel->folderMgr()->remove( mStorage->folder() ); 00248 } 00249 00250 emit renameDone( mNewName, true ); 00251 } 00252 00253 #include "renamejob.moc"