kmail

copyfolderjob.cpp
1
29#include "copyfolderjob.h"
30#include "folderstorage.h"
31#include "kmacctcachedimap.h"
32#include "kmfoldercachedimap.h"
33#include "kmfolder.h"
34#include "kmfolderdir.h"
35#include "kmfoldertype.h"
36#include "kmfoldermgr.h"
37#include "kmcommands.h"
38#include "kmmsgbase.h"
39#include "undostack.h"
40
41#include <kdebug.h>
42#include <tdelocale.h>
43#include <config.h>
44
45using namespace KMail;
46
47CopyFolderJob::CopyFolderJob( FolderStorage* const storage, KMFolderDir* const newParent )
48 : FolderJob( 0, tOther, (storage ? storage->folder() : 0) ),
49 mStorage( storage ), mNewParent( newParent ),
50 mNewFolder( 0 ), mChildFolderNodeIterator( *mStorage->folder()->createChildFolder() ),
51 mNextChildFolder( 0 )
52{
53 mStorage->open( "copyfolder" );
54}
55
56CopyFolderJob::~CopyFolderJob()
57{
58 kdDebug(5006) << k_funcinfo << endl;
59 if ( mNewFolder )
60 mNewFolder->setMoveInProgress( false );
61 if ( mStorage )
62 {
63 mStorage->folder()->setMoveInProgress( false );
64 mStorage->close( "copyfolder" );
65 }
66}
67
68/*
69 * The basic strategy is to first create the target folder, then copy all the mail
70 * from the source to the target folder, then recurse for each of the folder's children
71 */
72void CopyFolderJob::execute()
73{
74 if ( createTargetDir() ) {
76 }
77}
78
80{
81 // Hmmmm. Tasty hack. Can I have fries with that?
82 mStorage->blockSignals( true );
83 // move all messages to the new folder
84 TQPtrList<KMMsgBase> msgList;
85 for ( int i = 0; i < mStorage->count(); i++ )
86 {
87 const KMMsgBase* msgBase = mStorage->getMsgBase( i );
88 assert( msgBase );
89 msgList.append( msgBase );
90 }
91 if ( msgList.count() == 0 ) {
92 mStorage->blockSignals( false );
93 // ### be careful, after slotCopyNextChild() the source folder
94 // (including mStorage) might already be deleted!
95 slotCopyNextChild(); // no contents, check subfolders
96 } else {
97 KMCommand *command = new KMCopyCommand( mNewFolder, msgList );
98 connect( command, TQ_SIGNAL( completed( KMCommand * ) ),
99 this, TQ_SLOT( slotCopyCompleted( KMCommand * ) ) );
100 command->start();
101 }
102}
103
104void CopyFolderJob::slotCopyCompleted( KMCommand* command )
105{
106 kdDebug(5006) << k_funcinfo << (command?command->result():0) << endl;
107 disconnect( command, TQ_SIGNAL( completed( KMCommand * ) ),
108 this, TQ_SLOT( slotCopyCompleted( KMCommand * ) ) );
109
110 mStorage->blockSignals( false );
111
112 if ( command && command->result() != KMCommand::OK ) {
113 rollback();
114 return;
115 }
116 // if we have children, recurse
117 if ( mStorage->folder()->child() ) {
119 } else {
120 emit folderCopyComplete( true );
121 deleteLater();
122 }
123}
124
126{
127 //kdDebug(5006) << k_funcinfo << endl;
128 if ( mNextChildFolder )
129 mNextChildFolder->close( "copyfolder" ); // refcount
130 // previous sibling failed
131 if ( !success ) {
132 kdDebug(5006) << "Failed to copy one subfolder, let's not continue: " << mNewFolder->prettyURL() << endl;
133 rollback();
134 emit folderCopyComplete( false );
135 deleteLater();
136 }
137
138 KMFolderNode* node = mChildFolderNodeIterator.current();
139 while ( node && node->isDir() ) {
140 ++mChildFolderNodeIterator;
141 node = mChildFolderNodeIterator.current();
142 }
143 if ( node ) {
144 mNextChildFolder = static_cast<KMFolder*>(node);
145 ++mChildFolderNodeIterator;
146 } else {
147 // no more children, we are done
148 emit folderCopyComplete( true );
149 deleteLater();
150 return;
151 }
152
153 KMFolderDir * const dir = mNewFolder->createChildFolder();
154 if ( !dir ) {
155 kdDebug(5006) << "Failed to create subfolders of: " << mNewFolder->prettyURL() << endl;
156 emit folderCopyComplete( false );
157 deleteLater();
158 return;
159 }
160 // let it do its thing and report back when we are ready to do the next sibling
161 mNextChildFolder->open( "copyfolder" ); // refcount
162 FolderJob* job = new CopyFolderJob( mNextChildFolder->storage(), dir);
163 connect( job, TQ_SIGNAL( folderCopyComplete( bool ) ),
164 this, TQ_SLOT( slotCopyNextChild( bool ) ) );
165 job->start();
166}
167
168
169// FIXME factor into CreateFolderJob and make async, so it works with online imap
170// (create folder code taken from newfolderdialog.cpp)
172{
173 // get the default mailbox type
174 TDEConfig * const config = KMKernel::config();
175 TDEConfigGroupSaver saver(config, "General");
176 int deftype = config->readNumEntry("default-mailbox-format", 1);
177 if ( deftype < 0 || deftype > 1 ) deftype = 1;
178
179 // the type of the new folder
180 KMFolderType typenew =
181 ( deftype == 0 ) ? KMFolderTypeMbox : KMFolderTypeMaildir;
182 if ( mNewParent->owner() )
183 typenew = mNewParent->owner()->folderType();
184
185 bool success = false, waitForFolderCreation = false;
186
187 if ( mNewParent->owner() && mNewParent->owner()->folderType() == KMFolderTypeImap ) {
188 KMFolderImap* selectedStorage = static_cast<KMFolderImap*>( mNewParent->owner()->storage() );
189 KMAcctImap *anAccount = selectedStorage->account();
190 // check if a connection is available BEFORE creating the folder
191 if (anAccount->makeConnection() == ImapAccountBase::Connected) {
192 mNewFolder = kmkernel->imapFolderMgr()->createFolder( mStorage->folder()->name(), false, typenew, mNewParent );
193 if ( mNewFolder ) {
194 TQString imapPath;
195 imapPath = anAccount->createImapPath( selectedStorage->imapPath(), mStorage->folder()->name() );
196 KMFolderImap* newStorage = static_cast<KMFolderImap*>( mNewFolder->storage() );
197 connect( selectedStorage, TQ_SIGNAL(folderCreationResult(const TQString&, bool)),
198 this, TQ_SLOT(folderCreationDone(const TQString&, bool)) );
199 selectedStorage->createFolder(mStorage->folder()->name(), TQString()); // create it on the server
200 newStorage->initializeFrom( selectedStorage, imapPath, TQString() );
201 static_cast<KMFolderImap*>(mNewParent->owner()->storage())->setAccount( selectedStorage->account() );
202 waitForFolderCreation = true;
203 success = true;
204 }
205 }
206 } else if ( mNewParent->owner() && mNewParent->owner()->folderType() == KMFolderTypeCachedImap ) {
207 mNewFolder = kmkernel->dimapFolderMgr()->createFolder( mStorage->folder()->name(), false, typenew, mNewParent );
208 if ( mNewFolder ) {
209 KMFolderCachedImap* selectedStorage = static_cast<KMFolderCachedImap*>( mNewParent->owner()->storage() );
210 KMFolderCachedImap* newStorage = static_cast<KMFolderCachedImap*>( mNewFolder->storage() );
211 newStorage->initializeFrom( selectedStorage );
212 success = true;
213 }
214 } else {
215 // local folder
216 mNewFolder = kmkernel->folderMgr()->createFolder(mStorage->folder()->name(), false, typenew, mNewParent );
217 if ( mNewFolder )
218 success = true;
219 }
220
221 if ( !success ) {
222 kdWarning(5006) << k_funcinfo << "could not create folder" << endl;
223 emit folderCopyComplete( false );
224 deleteLater();
225 return false;
226 }
227
228 mNewFolder->setMoveInProgress( true );
229 mStorage->folder()->setMoveInProgress( true );
230
231 // inherit the folder type
232 // FIXME we should probably copy over most if not all settings
233 mNewFolder->storage()->setContentsType( mStorage->contentsType(), true /*quiet*/ );
234 mNewFolder->storage()->writeConfig();
235 kdDebug(5006)<< "CopyJob::createTargetDir - " << mStorage->folder()->idString()
236 << " |=> " << mNewFolder->idString() << endl;
237 return !waitForFolderCreation;
238}
239
240
242{
243 // copy failed - rollback the last transaction
244// kmkernel->undoStack()->undo();
245 // .. and delete the new folder
246 if ( mNewFolder ) {
247 if ( mNewFolder->folderType() == KMFolderTypeImap )
248 {
249 kmkernel->imapFolderMgr()->remove( mNewFolder );
250 } else if ( mNewFolder->folderType() == KMFolderTypeCachedImap )
251 {
252 // tell the account (see KMFolderCachedImap::listDirectory2)
253 KMFolderCachedImap* folder = static_cast<KMFolderCachedImap*>(mNewFolder->storage());
254 KMAcctCachedImap* acct = folder->account();
255 if ( acct )
256 acct->addDeletedFolder( folder->imapPath() );
257 kmkernel->dimapFolderMgr()->remove( mNewFolder );
258 } else if ( mNewFolder->folderType() == KMFolderTypeSearch )
259 {
260 // invalid
261 kdWarning(5006) << k_funcinfo << "cannot remove a search folder" << endl;
262 } else {
263 kmkernel->folderMgr()->remove( mNewFolder );
264 }
265 }
266
267 emit folderCopyComplete( false );
268 deleteLater();
269}
270
271void CopyFolderJob::folderCreationDone(const TQString & name, bool success)
272{
273 if ( mStorage->folder()->name() != name )
274 return; // not our business
275 kdDebug(5006) << k_funcinfo << success << endl;
276
277 if ( !success ) {
278 rollback();
279 } else {
281 }
282}
283#include "copyfolderjob.moc"
The FolderStorage class is the bass class for the storage related aspects of a collection of mail (a ...
Definition: folderstorage.h:80
KMail list that manages the contents of one directory that may contain folders and/or other directori...
Definition: kmfolderdir.h:16
KMFolder * owner() const
Returns the folder whose children we are holding.
Definition: kmfolderdir.h:59
Mail folder.
Definition: kmfolder.h:69
void close(const char *owner, bool force=false)
Close folder.
Definition: kmfolder.cpp:489
KMFolderType folderType() const
Returns the type of this folder.
Definition: kmfolder.cpp:233
int open(const char *owner)
Open folder for access.
Definition: kmfolder.cpp:479
void copyMessagesToTargetDir()
Copy all messages from the original folder to mNewFolder.
void folderCreationDone(const TQString &name, bool success)
Called when the online IMAP folder creation finished.
void rollback()
Called when one of the operations of the foldre itself or one of it's child folders failed and the al...
bool createTargetDir()
Create the target directory under the new parent.
void folderCopyComplete(bool success)
Emitted when the job is done, check the success bool.
void slotCopyCompleted(KMCommand *command)
Called when the CopyCommand has either succesfully completed copying the contents of our folder to th...
void slotCopyNextChild(bool success=true)
Called when the previous sibling's copy operation completed.
CopyFolderJob(FolderStorage *const storage, KMFolderDir *const newParent=0)
Create a new job.
folderdiaquotatab.h
Definition: aboutdata.cpp:40