00001
00029 #include "copyfolderjob.h"
00030 #include "folderstorage.h"
00031 #include "kmacctcachedimap.h"
00032 #include "kmfoldercachedimap.h"
00033 #include "kmfolder.h"
00034 #include "kmfolderdir.h"
00035 #include "kmfoldertype.h"
00036 #include "kmfoldermgr.h"
00037 #include "kmcommands.h"
00038 #include "kmmsgbase.h"
00039 #include "undostack.h"
00040
00041 #include <kdebug.h>
00042 #include <klocale.h>
00043 #include <config.h>
00044
00045 using namespace KMail;
00046
00047 CopyFolderJob::CopyFolderJob( FolderStorage* const storage, KMFolderDir* const newParent )
00048 : FolderJob( 0, tOther, (storage ? storage->folder() : 0) ),
00049 mStorage( storage ), mNewParent( newParent ),
00050 mNewFolder( 0 ), mChildFolderNodeIterator( *mStorage->folder()->createChildFolder() ),
00051 mNextChildFolder( 0 )
00052 {
00053 mStorage->open( "copyfolder" );
00054 }
00055
00056 CopyFolderJob::~CopyFolderJob()
00057 {
00058 kdDebug(5006) << k_funcinfo << endl;
00059 if ( mNewFolder )
00060 mNewFolder->setMoveInProgress( false );
00061 if ( mStorage )
00062 {
00063 mStorage->folder()->setMoveInProgress( false );
00064 mStorage->close( "copyfolder" );
00065 }
00066 }
00067
00068
00069
00070
00071
00072 void CopyFolderJob::execute()
00073 {
00074 if ( createTargetDir() ) {
00075 copyMessagesToTargetDir();
00076 }
00077 }
00078
00079 void CopyFolderJob::copyMessagesToTargetDir()
00080 {
00081
00082 mStorage->blockSignals( true );
00083
00084 QPtrList<KMMsgBase> msgList;
00085 for ( int i = 0; i < mStorage->count(); i++ )
00086 {
00087 const KMMsgBase* msgBase = mStorage->getMsgBase( i );
00088 assert( msgBase );
00089 msgList.append( msgBase );
00090 }
00091 if ( msgList.count() == 0 ) {
00092 mStorage->blockSignals( false );
00093
00094
00095 slotCopyNextChild();
00096 } else {
00097 KMCommand *command = new KMCopyCommand( mNewFolder, msgList );
00098 connect( command, SIGNAL( completed( KMCommand * ) ),
00099 this, SLOT( slotCopyCompleted( KMCommand * ) ) );
00100 command->start();
00101 }
00102 }
00103
00104 void CopyFolderJob::slotCopyCompleted( KMCommand* command )
00105 {
00106 kdDebug(5006) << k_funcinfo << (command?command->result():0) << endl;
00107 disconnect( command, SIGNAL( completed( KMCommand * ) ),
00108 this, SLOT( slotCopyCompleted( KMCommand * ) ) );
00109
00110 mStorage->blockSignals( false );
00111
00112 if ( command && command->result() != KMCommand::OK ) {
00113 rollback();
00114 return;
00115 }
00116
00117 if ( mStorage->folder()->child() ) {
00118 slotCopyNextChild();
00119 } else {
00120 emit folderCopyComplete( true );
00121 deleteLater();
00122 }
00123 }
00124
00125 void CopyFolderJob::slotCopyNextChild( bool success )
00126 {
00127
00128 if ( mNextChildFolder )
00129 mNextChildFolder->close( "copyfolder" );
00130
00131 if ( !success ) {
00132 kdDebug(5006) << "Failed to copy one subfolder, let's not continue: " << mNewFolder->prettyURL() << endl;
00133 rollback();
00134 emit folderCopyComplete( false );
00135 deleteLater();
00136 }
00137
00138 KMFolderNode* node = mChildFolderNodeIterator.current();
00139 while ( node && node->isDir() ) {
00140 ++mChildFolderNodeIterator;
00141 node = mChildFolderNodeIterator.current();
00142 }
00143 if ( node ) {
00144 mNextChildFolder = static_cast<KMFolder*>(node);
00145 ++mChildFolderNodeIterator;
00146 } else {
00147
00148 emit folderCopyComplete( true );
00149 deleteLater();
00150 return;
00151 }
00152
00153 KMFolderDir * const dir = mNewFolder->createChildFolder();
00154 if ( !dir ) {
00155 kdDebug(5006) << "Failed to create subfolders of: " << mNewFolder->prettyURL() << endl;
00156 emit folderCopyComplete( false );
00157 deleteLater();
00158 return;
00159 }
00160
00161 mNextChildFolder->open( "copyfolder" );
00162 FolderJob* job = new CopyFolderJob( mNextChildFolder->storage(), dir);
00163 connect( job, SIGNAL( folderCopyComplete( bool ) ),
00164 this, SLOT( slotCopyNextChild( bool ) ) );
00165 job->start();
00166 }
00167
00168
00169
00170
00171 bool CopyFolderJob::createTargetDir()
00172 {
00173
00174 KConfig * const config = KMKernel::config();
00175 KConfigGroupSaver saver(config, "General");
00176 int deftype = config->readNumEntry("default-mailbox-format", 1);
00177 if ( deftype < 0 || deftype > 1 ) deftype = 1;
00178
00179
00180 KMFolderType typenew =
00181 ( deftype == 0 ) ? KMFolderTypeMbox : KMFolderTypeMaildir;
00182 if ( mNewParent->owner() )
00183 typenew = mNewParent->owner()->folderType();
00184
00185 bool success = false, waitForFolderCreation = false;
00186
00187 if ( mNewParent->owner() && mNewParent->owner()->folderType() == KMFolderTypeImap ) {
00188 KMFolderImap* selectedStorage = static_cast<KMFolderImap*>( mNewParent->owner()->storage() );
00189 KMAcctImap *anAccount = selectedStorage->account();
00190
00191 if (anAccount->makeConnection() == ImapAccountBase::Connected) {
00192 mNewFolder = kmkernel->imapFolderMgr()->createFolder( mStorage->folder()->name(), false, typenew, mNewParent );
00193 if ( mNewFolder ) {
00194 QString imapPath;
00195 imapPath = anAccount->createImapPath( selectedStorage->imapPath(), mStorage->folder()->name() );
00196 KMFolderImap* newStorage = static_cast<KMFolderImap*>( mNewFolder->storage() );
00197 connect( selectedStorage, SIGNAL(folderCreationResult(const QString&, bool)),
00198 this, SLOT(folderCreationDone(const QString&, bool)) );
00199 selectedStorage->createFolder(mStorage->folder()->name(), QString::null);
00200 newStorage->initializeFrom( selectedStorage, imapPath, QString::null );
00201 static_cast<KMFolderImap*>(mNewParent->owner()->storage())->setAccount( selectedStorage->account() );
00202 waitForFolderCreation = true;
00203 success = true;
00204 }
00205 }
00206 } else if ( mNewParent->owner() && mNewParent->owner()->folderType() == KMFolderTypeCachedImap ) {
00207 mNewFolder = kmkernel->dimapFolderMgr()->createFolder( mStorage->folder()->name(), false, typenew, mNewParent );
00208 if ( mNewFolder ) {
00209 KMFolderCachedImap* selectedStorage = static_cast<KMFolderCachedImap*>( mNewParent->owner()->storage() );
00210 KMFolderCachedImap* newStorage = static_cast<KMFolderCachedImap*>( mNewFolder->storage() );
00211 newStorage->initializeFrom( selectedStorage );
00212 success = true;
00213 }
00214 } else {
00215
00216 mNewFolder = kmkernel->folderMgr()->createFolder(mStorage->folder()->name(), false, typenew, mNewParent );
00217 if ( mNewFolder )
00218 success = true;
00219 }
00220
00221 if ( !success ) {
00222 kdWarning(5006) << k_funcinfo << "could not create folder" << endl;
00223 emit folderCopyComplete( false );
00224 deleteLater();
00225 return false;
00226 }
00227
00228 mNewFolder->setMoveInProgress( true );
00229 mStorage->folder()->setMoveInProgress( true );
00230
00231
00232
00233 mNewFolder->storage()->setContentsType( mStorage->contentsType(), true );
00234 mNewFolder->storage()->writeConfig();
00235 kdDebug(5006)<< "CopyJob::createTargetDir - " << mStorage->folder()->idString()
00236 << " |=> " << mNewFolder->idString() << endl;
00237 return !waitForFolderCreation;
00238 }
00239
00240
00241 void CopyFolderJob::rollback()
00242 {
00243
00244
00245
00246 if ( mNewFolder ) {
00247 if ( mNewFolder->folderType() == KMFolderTypeImap )
00248 {
00249 kmkernel->imapFolderMgr()->remove( mNewFolder );
00250 } else if ( mNewFolder->folderType() == KMFolderTypeCachedImap )
00251 {
00252
00253 KMFolderCachedImap* folder = static_cast<KMFolderCachedImap*>(mNewFolder->storage());
00254 KMAcctCachedImap* acct = folder->account();
00255 if ( acct )
00256 acct->addDeletedFolder( folder->imapPath() );
00257 kmkernel->dimapFolderMgr()->remove( mNewFolder );
00258 } else if ( mNewFolder->folderType() == KMFolderTypeSearch )
00259 {
00260
00261 kdWarning(5006) << k_funcinfo << "cannot remove a search folder" << endl;
00262 } else {
00263 kmkernel->folderMgr()->remove( mNewFolder );
00264 }
00265 }
00266
00267 emit folderCopyComplete( false );
00268 deleteLater();
00269 }
00270
00271 void CopyFolderJob::folderCreationDone(const QString & name, bool success)
00272 {
00273 if ( mStorage->folder()->name() != name )
00274 return;
00275 kdDebug(5006) << k_funcinfo << success << endl;
00276
00277 if ( !success ) {
00278 rollback();
00279 } else {
00280 copyMessagesToTargetDir();
00281 }
00282 }
00283 #include "copyfolderjob.moc"