kmail

renamejob.cpp
1 /*
2  * Copyright (c) 2004 Carsten Burghardt <burghardt@kde.org>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; version 2 of the License
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16  *
17  * In addition, as a special exception, the copyright holders give
18  * permission to link the code of this program with any edition of
19  * the TQt library by Trolltech AS, Norway (or with modified versions
20  * of TQt that use the same license as TQt), and distribute linked
21  * combinations including the two. You must obey the GNU General
22  * Public License in all respects for all of the code used other than
23  * TQt. If you modify this file, you may extend this exception to
24  * your version of the file, but you are not obligated to do so. If
25  * you do not wish to do so, delete this exception statement from
26  * your version.
27  */
28 
29 #include "renamejob.h"
30 #include "copyfolderjob.h"
31 #include "kmfolderimap.h"
32 #include "kmfoldercachedimap.h"
33 #include "folderstorage.h"
34 #include "kmfolder.h"
35 #include "kmfolderdir.h"
36 #include "kmfoldermgr.h"
37 #include "imapaccountbase.h"
38 #include "kmacctimap.h"
39 #include "kmacctcachedimap.h"
40 #include "kmmsgbase.h"
41 
42 #include <kdebug.h>
43 #include <kurl.h>
44 #include <tdeio/scheduler.h>
45 #include <tdeio/job.h>
46 #include <tdeio/global.h>
47 #include <tdelocale.h>
48 #include <config.h>
49 
50 #include <tqmap.h>
51 
52 using namespace KMail;
53 
54 template <typename T> static TQStringList imapPaths( FolderStorage* storage )
55 {
56  TQStringList rv;
57  rv.append( static_cast<T>( storage )->imapPath() );
58  KMFolderDir* dir = storage->folder()->child();
59  if ( dir ) {
60  KMFolderNode *node = dir->first();
61  while ( node ) {
62  if ( !node->isDir() ) {
63  rv += imapPaths<T>( static_cast<KMFolder*>( node )->storage() );
64  }
65  node = dir->next();
66  }
67  }
68  return rv;
69 }
70 
71 RenameJob::RenameJob( FolderStorage* storage, const TQString& newName,
72  KMFolderDir* newParent )
73  : FolderJob( 0, tOther, (storage ? storage->folder() : 0) ),
74  mStorage( storage ), mNewParent( newParent ),
75  mNewName( newName ), mNewFolder( 0 ), mCopyFolderJob( 0 )
76 {
77  mStorageTempOpened = 0;
78  if ( storage ) {
79  mOldName = storage->name();
80  if ( storage->folderType() == KMFolderTypeImap ) {
81  mOldImapPath = static_cast<KMFolderImap*>(storage)->imapPath();
82 // mOldImapPaths = imapPaths<KMFolderImap*>( storage );
83  } else if ( storage->folderType() == KMFolderTypeCachedImap ) {
84  mOldImapPath = static_cast<KMFolderCachedImap*>(storage)->imapPath();
85  mOldImapPaths = imapPaths<KMFolderCachedImap*>( storage );
86  }
87  }
88 }
89 
90 RenameJob::~RenameJob()
91 {
92 }
93 
94 // FIXME: move on the server for online imap given source and target are on the same server
95 void RenameJob::execute()
96 {
97  if ( mNewParent )
98  {
99  // move the folder to a different parent
100  KMFolderType type = mStorage->folderType();
101  if ( ( type == KMFolderTypeMbox || type == KMFolderTypeMaildir ) &&
102  mNewParent->type() == KMStandardDir &&
103  mStorage->folderType() != KMFolderTypeCachedImap )
104  {
105  // local folders can handle this on their own
106  mStorage->rename( mNewName, mNewParent );
107  emit renameDone( mNewName, true );
108  deleteLater();
109  return;
110  }
111  // copy to the new folder
112  mCopyFolderJob = new CopyFolderJob( mStorage, mNewParent );
113  connect( mCopyFolderJob, TQ_SIGNAL(folderCopyComplete(bool)), TQ_SLOT(folderCopyComplete(bool)) );
114  mCopyFolderJob->execute();
115 
116  } else
117  {
118  // only rename the folder
119  if ( mStorage->folderType() != KMFolderTypeImap )
120  {
121  // local and dimap folder handle this directly
122  mStorage->rename( mNewName );
123  emit renameDone( mNewName, true );
124  deleteLater();
125  return;
126  }
127  if ( mOldImapPath.isEmpty() )
128  {
129  // sanity
130  emit renameDone( mNewName, false );
131  deleteLater();
132  return;
133  } else if ( mOldName == mNewName || mOldImapPath == "/INBOX/" ) {
134  emit renameDone( mNewName, true ); // noop
135  deleteLater();
136  return;
137  }
138  ImapAccountBase* account = static_cast<KMFolderImap*>(mStorage)->account();
139  // first rename it on the server
140  mNewImapPath = mOldImapPath;
141  mNewImapPath = mNewImapPath.replace( mOldName, mNewName );
142  KURL src( account->getUrl() );
143  src.setPath( mOldImapPath );
144  KURL dst( account->getUrl() );
145  dst.setPath( mNewImapPath );
146  TDEIO::SimpleJob *job = TDEIO::rename( src, dst, true );
147  kdDebug(5006)<< "RenameJob::rename - " << src.prettyURL()
148  << " |=> " << dst.prettyURL() << endl;
149  ImapAccountBase::jobData jd( src.url() );
150  account->insertJob( job, jd );
151  TDEIO::Scheduler::assignJobToSlave( account->slave(), job );
152  connect( job, TQ_SIGNAL(result(TDEIO::Job*)),
153  TQ_SLOT(slotRenameResult(TDEIO::Job*)) );
154  }
155 }
156 
157 void RenameJob::slotRenameResult( TDEIO::Job *job )
158 {
159  ImapAccountBase* account = static_cast<KMFolderImap*>(mStorage)->account();
160  ImapAccountBase::JobIterator it = account->findJob(job);
161  if ( it == account->jobsEnd() )
162  {
163  emit renameDone( mNewName, false );
164  deleteLater();
165  return;
166  }
167  if ( job->error() )
168  {
169  account->handleJobError( job, i18n("Error while renaming a folder.") );
170  emit renameDone( mNewName, false );
171  deleteLater();
172  return;
173  }
174  account->removeJob(it);
175  // set the new path
176  if ( mStorage->folderType() == KMFolderTypeImap )
177  static_cast<KMFolderImap*>(mStorage)->setImapPath( mNewImapPath );
178  // unsubscribe old (we don't want ghosts)
179  account->changeSubscription( false, mOldImapPath );
180  // subscribe new
181  account->changeSubscription( true, mNewImapPath );
182 
183  // local part (will set the new name)
184  mStorage->rename( mNewName );
185 
186  emit renameDone( mNewName, true );
187  deleteLater();
188 }
189 
191 {
192  kdDebug(5006) << k_funcinfo << success << endl;
193  if ( !success ) {
194  kdWarning(5006) << k_funcinfo << "could not copy folder" << endl;
195  emit renameDone( mNewName, false );
196  deleteLater();
197  return;
198  }
199  mNewFolder = mCopyFolderJob->targetFolder();
200  mCopyFolderJob = 0;
201 
202  if ( mStorageTempOpened ) {
203  mStorageTempOpened->close( "renamejob" );
204  mStorageTempOpened = 0;
205  }
206 
207  kdDebug(5006) << "deleting old folder" << endl;
208  // move complete or not necessary
209  // save our settings
210  TQString oldconfig = "Folder-" + mStorage->folder()->idString();
211  TDEConfig* config = KMKernel::config();
212  TQMap<TQString, TQString> entries = config->entryMap( oldconfig );
213  TDEConfigGroupSaver saver(config, "Folder-" + mNewFolder->idString());
214  for ( TQMap<TQString, TQString>::Iterator it = entries.begin();
215  it != entries.end(); ++it )
216  {
217  if ( it.key() == "Id" || it.key() == "ImapPath" ||
218  it.key() == "UidValidity" )
219  continue;
220  config->writeEntry( it.key(), it.data() );
221  }
222  mNewFolder->readConfig( config );
223  // make sure the children state is correct
224  if ( mNewFolder->child() &&
225  ( mNewFolder->storage()->hasChildren() == FolderStorage::HasNoChildren ) )
226  mNewFolder->storage()->updateChildrenState();
227 
228  // delete the old folder
229  mStorage->blockSignals( false );
230  if ( mStorage->folderType() == KMFolderTypeImap )
231  {
232  kmkernel->imapFolderMgr()->remove( mStorage->folder() );
233  } else if ( mStorage->folderType() == KMFolderTypeCachedImap )
234  {
235  // tell the account (see KMFolderCachedImap::listDirectory2)
236  KMAcctCachedImap* acct = static_cast<KMFolderCachedImap*>(mStorage)->account();
237  if ( acct ) {
238  for ( TQStringList::ConstIterator it = mOldImapPaths.constBegin(); it != mOldImapPaths.constEnd(); ++it )
239  acct->addDeletedFolder( *it );
240  }
241  kmkernel->dimapFolderMgr()->remove( mStorage->folder() );
242  } else if ( mStorage->folderType() == KMFolderTypeSearch )
243  {
244  // invalid
245  kdWarning(5006) << k_funcinfo << "cannot remove a search folder" << endl;
246  } else {
247  kmkernel->folderMgr()->remove( mStorage->folder() );
248  }
249 
250  emit renameDone( mNewName, true );
251 }
252 
253 #include "renamejob.moc"
virtual KMFolderType folderType() const
Returns the type of this folder.
Definition: folderstorage.h:96
void slotRenameResult(TDEIO::Job *job)
Rename the folder.
Definition: renamejob.cpp:157
KMail list that manages the contents of one directory that may contain folders and/or other directori...
Definition: kmfolderdir.h:15
void renameDone(TQString newName, bool success)
Emitted when the job is done, check the success bool.
KMFolderDir * child() const
Returns the folder directory associated with this node or 0 if no such directory exists.
Definition: kmfolder.h:157
The FolderStorage class is the bass class for the storage related aspects of a collection of mail (a ...
Definition: folderstorage.h:79
TQString idString() const
Returns a string that can be used to identify this folder.
Definition: kmfolder.cpp:705
void folderCopyComplete(bool success)
All messages are copied so remove the original folder.
Definition: renamejob.cpp:190
virtual void updateChildrenState()
Updates the hasChildren() state.
KMFolder * targetFolder() const
Returns the newly created target folder.
Definition: copyfolderjob.h:69
void close(const char *owner, bool force=false)
Close folder.
void readConfig(TDEConfig *config)
This is used by the storage to read the folder specific configuration.
Definition: kmfolder.cpp:161
folderdiaquotatab.h
Definition: aboutdata.cpp:40
RenameJob(FolderStorage *storage, const TQString &newName, KMFolderDir *newParent=0)
Create a new job.
Definition: renamejob.cpp:71
Copy a hierarchy of folders somewhere else in the folder tree.
Definition: copyfolderjob.h:50
virtual int rename(const TQString &newName, KMFolderDir *aParent=0)
Physically rename the folder.
Mail folder.
Definition: kmfolder.h:68
virtual ChildrenState hasChildren() const
Returns if the folder has children, has no children or we don't know.