kmail

renamejob.cpp

Go to the documentation of this file.
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 Qt library by Trolltech AS, Norway (or with modified versions
00020  *  of Qt that use the same license as Qt), 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  *  Qt.  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 <qmap.h>
00051 
00052 using namespace KMail;
00053 
00054 template <typename T> static QStringList imapPaths( FolderStorage* storage )
00055 {
00056   QStringList 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 QString& 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, SIGNAL(folderCopyComplete(bool)), 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, SIGNAL(result(KIO::Job*)),
00153         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   QString oldconfig = "Folder-" + mStorage->folder()->idString();
00211   KConfig* config = KMKernel::config();
00212   QMap<QString, QString> entries = config->entryMap( oldconfig );
00213   KConfigGroupSaver saver(config, "Folder-" + mNewFolder->idString());
00214   for ( QMap<QString, QString>::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 ( QStringList::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"