kmail

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 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 RenameJob::RenameJob( FolderStorage* storage, const QString& newName,
00055     KMFolderDir* newParent )
00056  : FolderJob( 0, tOther, (storage ? storage->folder() : 0) ),
00057    mStorage( storage ), mNewParent( newParent ),
00058    mNewName( newName ), mNewFolder( 0 ), mCopyFolderJob( 0 )
00059 {
00060   mStorageTempOpened = 0;
00061   if ( storage ) {
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 
00071 RenameJob::~RenameJob()
00072 {
00073 }
00074 
00075 // FIXME: move on the server for online imap given source and target are on the same server
00076 void RenameJob::execute()
00077 {
00078   if ( mNewParent )
00079   {
00080     // move the folder to a different parent
00081     KMFolderType type = mStorage->folderType();
00082     if ( ( type == KMFolderTypeMbox || type == KMFolderTypeMaildir ) &&
00083          mNewParent->type() == KMStandardDir &&
00084          mStorage->folderType() != KMFolderTypeCachedImap )
00085     {
00086       // local folders can handle this on their own
00087       mStorage->rename( mNewName, mNewParent );
00088       emit renameDone( mNewName, true );
00089       deleteLater();
00090       return;
00091     }
00092     // copy to the new folder
00093     mCopyFolderJob = new CopyFolderJob( mStorage, mNewParent );
00094     connect( mCopyFolderJob, SIGNAL(folderCopyComplete(bool)), SLOT(folderCopyComplete(bool)) );
00095     mCopyFolderJob->execute();
00096 
00097   } else
00098   {
00099     // only rename the folder
00100     if ( mStorage->folderType() != KMFolderTypeImap )
00101     {
00102       // local and dimap folder handle this directly
00103       mStorage->rename( mNewName );
00104       emit renameDone( mNewName, true );
00105       deleteLater();
00106       return;
00107     }
00108     if ( mOldImapPath.isEmpty() )
00109     {
00110       // sanity
00111       emit renameDone( mNewName, false );
00112       deleteLater();
00113       return;
00114     } else if ( mOldName == mNewName || mOldImapPath == "/INBOX/" ) {
00115       emit renameDone( mNewName, true ); // noop
00116       deleteLater();
00117       return;
00118     }
00119     ImapAccountBase* account = static_cast<KMFolderImap*>(mStorage)->account();
00120     // first rename it on the server
00121     mNewImapPath = mOldImapPath;
00122     mNewImapPath = mNewImapPath.replace( mOldName, mNewName );
00123     KURL src( account->getUrl() );
00124     src.setPath( mOldImapPath );
00125     KURL dst( account->getUrl() );
00126     dst.setPath( mNewImapPath );
00127     KIO::SimpleJob *job = KIO::rename( src, dst, true );
00128     kdDebug(5006)<< "RenameJob::rename - " << src.prettyURL()
00129       << " |=> " << dst.prettyURL() << endl;
00130     ImapAccountBase::jobData jd( src.url() );
00131     account->insertJob( job, jd );
00132     KIO::Scheduler::assignJobToSlave( account->slave(), job );
00133     connect( job, SIGNAL(result(KIO::Job*)),
00134         SLOT(slotRenameResult(KIO::Job*)) );
00135   }
00136 }
00137 
00138 void RenameJob::slotRenameResult( KIO::Job *job )
00139 {
00140   ImapAccountBase* account = static_cast<KMFolderImap*>(mStorage)->account();
00141   ImapAccountBase::JobIterator it = account->findJob(job);
00142   if ( it == account->jobsEnd() )
00143   {
00144     emit renameDone( mNewName, false );
00145     deleteLater();
00146     return;
00147   }
00148   if ( job->error() )
00149   {
00150     account->handleJobError( job, i18n("Error while renaming a folder.") );
00151     emit renameDone( mNewName, false );
00152     deleteLater();
00153     return;
00154   }
00155   account->removeJob(it);
00156   // set the new path
00157   if ( mStorage->folderType() == KMFolderTypeImap )
00158     static_cast<KMFolderImap*>(mStorage)->setImapPath( mNewImapPath );
00159   // unsubscribe old (we don't want ghosts)
00160   account->changeSubscription( false, mOldImapPath );
00161   // subscribe new
00162   account->changeSubscription( true, mNewImapPath );
00163 
00164   // local part (will set the new name)
00165   mStorage->rename( mNewName );
00166 
00167   emit renameDone( mNewName, true );
00168   deleteLater();
00169 }
00170 
00171 void RenameJob::folderCopyComplete(bool success)
00172 {
00173   kdDebug(5006) << k_funcinfo << success << endl;
00174   if ( !success ) {
00175     kdWarning(5006) << k_funcinfo << "could not copy folder" << endl;
00176     emit renameDone( mNewName, false );
00177     deleteLater();
00178     return;
00179   }
00180   mNewFolder = mCopyFolderJob->targetFolder();
00181   mCopyFolderJob = 0;
00182 
00183   if ( mStorageTempOpened ) {
00184     mStorageTempOpened->close("renamejob");
00185     mStorageTempOpened = 0;
00186   }
00187 
00188   kdDebug(5006) << "deleting old folder" << endl;
00189   // move complete or not necessary
00190   // save our settings
00191   QString oldconfig = "Folder-" + mStorage->folder()->idString();
00192   KConfig* config = KMKernel::config();
00193   QMap<QString, QString> entries = config->entryMap( oldconfig );
00194   KConfigGroupSaver saver(config, "Folder-" + mNewFolder->idString());
00195   for ( QMap<QString, QString>::Iterator it = entries.begin();
00196         it != entries.end(); ++it )
00197   {
00198     if ( it.key() == "Id" || it.key() == "ImapPath" ||
00199           it.key() == "UidValidity" )
00200       continue;
00201     config->writeEntry( it.key(), it.data() );
00202   }
00203   mNewFolder->readConfig( config );
00204   // make sure the children state is correct
00205   if ( mNewFolder->child() &&
00206         ( mNewFolder->storage()->hasChildren() == FolderStorage::HasNoChildren ) )
00207     mNewFolder->storage()->updateChildrenState();
00208 
00209   // delete the old folder
00210   mStorage->blockSignals( false );
00211   if ( mStorage->folderType() == KMFolderTypeImap )
00212   {
00213     kmkernel->imapFolderMgr()->remove( mStorage->folder() );
00214   } else if ( mStorage->folderType() == KMFolderTypeCachedImap )
00215   {
00216     // tell the account (see KMFolderCachedImap::listDirectory2)
00217     KMAcctCachedImap* acct = static_cast<KMFolderCachedImap*>(mStorage)->account();
00218     if ( acct )
00219       acct->addDeletedFolder( mOldImapPath );
00220     kmkernel->dimapFolderMgr()->remove( mStorage->folder() );
00221   } else if ( mStorage->folderType() == KMFolderTypeSearch )
00222   {
00223     // invalid
00224     kdWarning(5006) << k_funcinfo << "cannot remove a search folder" << endl;
00225   } else {
00226     kmkernel->folderMgr()->remove( mStorage->folder() );
00227   }
00228 
00229   emit renameDone( mNewName, true );
00230 }
00231 
00232 #include "renamejob.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys