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 
45 using namespace KMail;
46 
47 CopyFolderJob::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 
56 CopyFolderJob::~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  */
72 void 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 
104 void 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 
271 void 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