3 #include "kmfoldermgr.h"
19 #include <kmessagebox.h>
23 #include <kconfiggroup.h>
25 #include "kmmainwin.h"
26 #include "kmfiltermgr.h"
27 #include "folderstorage.h"
29 #include "kmfoldercachedimap.h"
30 #include "kmacctcachedimap.h"
31 #include "renamejob.h"
32 #include "copyfolderjob.h"
34 using KMail::RenameJob
;
35 using KMail::CopyFolderJob
;
37 //-----------------------------------------------------------------------------
38 KMFolderMgr::KMFolderMgr(const QString
& aBasePath
, KMFolderDirType dirType
):
39 QObject(), mDir(this, QString(), dirType
)
41 if ( dirType
== KMStandardDir
)
42 mDir
.setBaseURL( I18N_NOOP("Local Folders") );
45 setBasePath(aBasePath
);
50 //-----------------------------------------------------------------------------
51 KMFolderMgr::~KMFolderMgr()
57 //-----------------------------------------------------------------------------
58 void KMFolderMgr::expireAll() {
59 KSharedConfig::Ptr config
= KMKernel::config();
60 KConfigGroup
group(config
, "General");
61 int ret
= KMessageBox::Continue
;
63 if ( group
.readEntry( "warn-before-expire", true ) ) {
64 ret
= KMessageBox::warningContinueCancel(KMainWindow::memberList().first(),
65 i18n("Are you sure you want to expire old messages?"),
66 i18n("Expire Old Messages?"), KGuiItem(i18n("Expire")));
69 if (ret
== KMessageBox::Continue
) {
70 expireAllFolders( true /*immediate*/ );
75 #define DO_FOR_ALL(function, folder_code) \
76 QList<KMFolderNode*>::const_iterator it; \
77 for ( it = dir->constBegin(); it != dir->constEnd(); ++it ) { \
78 KMFolderNode* node = *it; \
79 if (node->isDir()) continue; \
80 KMFolder *folder = static_cast<KMFolder*>(node); \
82 KMFolderDir *child = folder->child(); \
87 int KMFolderMgr::folderCount(KMFolderDir
*dir
)
94 count
+= folderCount( child
);
106 //-----------------------------------------------------------------------------
107 void KMFolderMgr::compactAllFolders(bool immediate
, KMFolderDir
* dir
)
113 compactAllFolders( immediate
, child
);
116 if ( folder
->needsCompacting() )
117 folder
->compact( immediate
? KMFolder::CompactNow
: KMFolder::CompactLater
);
123 //-----------------------------------------------------------------------------
124 void KMFolderMgr::setBasePath(const QString
& aBasePath
)
126 assert(!aBasePath
.isEmpty());
128 if (aBasePath
.startsWith('~'))
129 mBasePath
= QDir::homePath() + '/' + aBasePath
.mid(1);
131 mBasePath
= aBasePath
;
133 QFileInfo
info( mBasePath
);
135 // FIXME We should ask for an alternative dir, rather than bailing out,
137 // FIXME We also should return boolean value here instead if exiting - jstaniek
138 if ( info
.exists() ) {
139 if ( !info
.isDir() ) {
140 KMessageBox::sorry(0, i18n("'%1' does not appear to be a folder.\n"
141 "Please move the file out of the way.",
145 if ( !info
.isReadable() || !info
.isWritable() ) {
146 KMessageBox::sorry(0, i18n("The permissions of the folder '%1' are "
148 "please make sure that you can view and modify "
149 "the content of this folder.",
154 // ~/Mail (or whatever the user specified) doesn't exist, create it
155 if ( KDE_mkdir( QFile::encodeName( mBasePath
), S_IRWXU
) == -1 ) {
156 KMessageBox::sorry( 0, i18n( "KMail could not create folder '%1';\n"
157 "please make sure that you can view and "
158 "modify the content of the folder '%2'.",
159 mBasePath
, QDir::homePath() ) );
163 mDir
.setPath(mBasePath
);
169 //-----------------------------------------------------------------------------
170 KMFolder
* KMFolderMgr::createFolder(const QString
& fName
, bool sysFldr
,
171 KMFolderType aFolderType
,
172 KMFolderDir
*aFolderDir
)
175 KMFolderDir
*fldDir
= aFolderDir
;
180 // check if this is a dimap folder and the folder we want to create has been deleted
181 // since the last sync
182 if ( fldDir
->owner() && fldDir
->owner()->folderType() == KMFolderTypeCachedImap
) {
183 KMFolderCachedImap
*storage
= static_cast<KMFolderCachedImap
*>( fldDir
->owner()->storage() );
184 KMAcctCachedImap
*account
= storage
->account();
186 QString imapPath
= storage
->imapPath();
187 if ( !imapPath
.endsWith( '/' ) )
190 if ( account
->isDeletedFolder( imapPath
) || account
->isDeletedFolder( imapPath
+ '/' )
191 || account
->isPreviouslyDeletedFolder( imapPath
)
192 || account
->isPreviouslyDeletedFolder( imapPath
+ '/' ) ) {
193 KMessageBox::error( 0, i18n("A folder with the same name has been deleted since the last mail check. "
194 "You need to check mails first before creating another folder with the same name."),
195 i18n("Could Not Create Folder") );
200 fld
= fldDir
->createFolder(fName
, sysFldr
, aFolderType
);
202 if ( fld
->id() == 0 )
203 fld
->setId( createId() );
205 emit
folderAdded(fld
);
206 if (kmkernel
->filterMgr())
207 kmkernel
->filterMgr()->folderCreated(fld
);
214 //-----------------------------------------------------------------------------
215 KMFolder
* KMFolderMgr::find(const QString
& folderName
, bool foldersOnly
) const
217 QList
<KMFolderNode
*>::const_iterator it
;
218 for ( it
= mDir
.begin(); it
!= mDir
.end(); ++it
)
220 KMFolderNode
* node
= *it
;
221 if (node
->isDir() && foldersOnly
) continue;
222 if (node
->name()==folderName
) return (KMFolder
*)node
;
227 //-----------------------------------------------------------------------------
228 KMFolder
* KMFolderMgr::findById(const uint id
) const
230 return findIdString( QString(), id
);
233 //-----------------------------------------------------------------------------
234 KMFolder
* KMFolderMgr::findIdString( const QString
& folderId
,
236 const KMFolderDir
*dir
) const
243 KMFolder
*folder
= findIdString( folderId
, id
, child
);
248 if ( ( !folderId
.isEmpty() && folder
->idString() == folderId
) ||
249 ( id
!= 0 && folder
->id() == id
) )
257 void KMFolderMgr::getFolderURLS( QStringList
& flist
, const QString
& prefix
,
258 const KMFolderDir
*adir
) const
260 const KMFolderDir
* dir
= adir
? adir
: &mDir
;
264 getFolderURLS( flist
, prefix
+ '/' + folder
->name(), child
);
267 flist
<< prefix
+ '/' + folder
->name();
272 KMFolder
* KMFolderMgr::getFolderByURL( const QString
& vpath
,
273 const QString
& prefix
,
274 const KMFolderDir
*adir
) const
276 const KMFolderDir
* dir
= adir
? adir
: &mDir
;
279 QString a
= prefix
+ '/' + folder
->name();
280 KMFolder
* mfolder
= getFolderByURL( vpath
, a
,child
);
285 QString comp
= prefix
+ '/' + folder
->name();
293 //-----------------------------------------------------------------------------
294 KMFolder
* KMFolderMgr::findOrCreate(const QString
& aFolderName
, bool sysFldr
,
297 KMFolder
* folder
= 0;
299 folder
= find(aFolderName
);
301 folder
= findById(id
);
305 static bool know_type
= false;
306 static KMFolderType type
= KMFolderTypeMaildir
;
307 if (know_type
== false)
310 KSharedConfig::Ptr config
= KMKernel::config();
311 KConfigGroup
group(config
, "General");
312 if (group
.hasKey("default-mailbox-format"))
314 if ( group
.readEntry("default-mailbox-format", 1 ) == 0 )
315 type
= KMFolderTypeMbox
;
320 folder
= createFolder(aFolderName
, sysFldr
, type
);
322 KMessageBox::error(0,(i18n("Cannot create file `%1' in %2.\nKMail cannot start without it.", aFolderName
, mBasePath
)));
332 //-----------------------------------------------------------------------------
333 void KMFolderMgr::remove(KMFolder
* aFolder
)
338 // remember the original folder to trigger contentsChanged later
340 mRemoveOrig
= aFolder
;
342 if ( aFolder
->child() )
344 // call remove for every child
345 KMFolderNodeList children
= *aFolder
->child();
346 foreach( KMFolderNode
*child
, children
) {
347 if ( child
->isDir() )
349 KMFolder
*folder
= static_cast<KMFolder
*>( child
);
353 emit
folderRemoved(aFolder
);
354 removeFolder(aFolder
);
357 void KMFolderMgr::removeFolder(KMFolder
* aFolder
)
359 connect(aFolder
, SIGNAL(removed(KMFolder
*, bool)),
360 this, SLOT(removeFolderAux(KMFolder
*, bool)));
364 KMFolder
* KMFolderMgr::parentFolder( KMFolder
* folder
)
366 // find the parent folder by stripping "." and ".directory" from the name
367 KMFolderDir
* fdir
= folder
->parent();
368 QString parentName
= fdir
->name();
369 parentName
= parentName
.mid( 1, parentName
.length()-11 );
370 KMFolderNode
* parent
= fdir
->hasNamedFolder( parentName
);
371 if ( !parent
&& fdir
->parent() ) // dimap obviously has a different structure
372 parent
= fdir
->parent()->hasNamedFolder( parentName
);
374 KMFolder
* parentF
= 0;
376 parentF
= dynamic_cast<KMFolder
*>( parent
);
380 void KMFolderMgr::removeFolderAux(KMFolder
* aFolder
, bool success
)
387 KMFolderDir
* fdir
= aFolder
->parent();
388 QList
<KMFolderNode
*>::const_iterator it
;
389 for ( it
= fdir
->constBegin(); it
!= fdir
->constEnd(); ++it
) {
390 KMFolderNode
* fN
= *it
;
391 if (fN
->isDir() && (fN
->name() == '.' + aFolder
->fileName() + ".directory")) {
392 removeDirAux(static_cast<KMFolderDir
*>(fN
));
397 KMFolder
* parentF
= parentFolder( aFolder
);
400 // aFolder will be deleted by the next call!
401 aFolder
->parent()->removeAll(aFolder
);
403 // update the children state
405 if ( parentF
!= aFolder
) {
406 parentF
->storage()->updateChildrenState();
410 kWarning() << "Can not find parent folder for " << aFolder
->label().toUtf8().data();
412 if (aFolder
== mRemoveOrig
) {
413 // call only if we're removing the original parent folder
419 void KMFolderMgr::removeDirAux(KMFolderDir
* aFolderDir
)
422 QString folderDirLocation
= aFolderDir
->path();
424 aFolderDir
->parent()->removeAll(aFolderDir
);
425 dir
.rmdir(folderDirLocation
);
428 //-----------------------------------------------------------------------------
429 KMFolderRootDir
& KMFolderMgr::dir(void)
435 //-----------------------------------------------------------------------------
436 void KMFolderMgr::contentsChanged(void)
438 if (mQuiet
) mChanged
= true;
443 //-----------------------------------------------------------------------------
444 void KMFolderMgr::reload(void)
448 //-----------------------------------------------------------------------------
449 void KMFolderMgr::createFolderList(QStringList
*str
,
450 QList
<QPointer
<KMFolder
> > *folders
)
452 createFolderList( str
, folders
, 0, "" );
455 //-----------------------------------------------------------------------------
456 void KMFolderMgr::createI18nFolderList(QStringList
*str
,
457 QList
<QPointer
<KMFolder
> > *folders
)
459 createFolderList( str
, folders
, 0, QString(), true );
462 //-----------------------------------------------------------------------------
463 void KMFolderMgr::createFolderList(QStringList
*str
,
464 QList
<QPointer
<KMFolder
> > *folders
,
466 const QString
& prefix
,
469 KMFolderDir
* dir
= adir
? adir
: &mDir
;
473 createFolderList(str
, folders
, child
, " " + prefix
, i18nized
);
477 str
->append(prefix
+ folder
->label());
479 str
->append(prefix
+ folder
->name());
480 folders
->append( folder
);
485 //-----------------------------------------------------------------------------
486 void KMFolderMgr::syncAllFolders( KMFolderDir
*adir
)
488 KMFolderDir
* dir
= adir
? adir
: &mDir
;
491 syncAllFolders(child
);
494 if (folder
->isOpened())
501 //-----------------------------------------------------------------------------
503 * Check each folder in turn to see if it is configured to
504 * AutoExpire. If so, expire old messages.
506 * Should be called with 0 first time around.
508 void KMFolderMgr::expireAllFolders(bool immediate
, KMFolderDir
*adir
) {
509 KMFolderDir
*dir
= adir
? adir
: &mDir
;
513 expireAllFolders(immediate
, child
);
516 if (folder
->isAutoExpire()) {
517 folder
->expireOldMessages( immediate
);
523 //-----------------------------------------------------------------------------
524 void KMFolderMgr::quiet(bool beQuiet
)
533 if (mChanged
) emit
changed();
539 //-----------------------------------------------------------------------------
540 void KMFolderMgr::tryReleasingFolder(KMFolder
* f
, KMFolderDir
* adir
)
542 KMFolderDir
* dir
= adir
? adir
: &mDir
;
545 tryReleasingFolder(f
, child
);
548 if (folder
->isOpened())
549 folder
->storage()->tryReleasingFolder(f
);
554 //-----------------------------------------------------------------------------
555 uint
KMFolderMgr::createId()
560 newId
= KRandom::random();
561 } while ( findById( newId
) != 0 );
566 //-----------------------------------------------------------------------------
567 void KMFolderMgr::moveFolder( KMFolder
* folder
, KMFolderDir
*newParent
)
569 renameFolder( folder
, folder
->name(), newParent
);
572 //-----------------------------------------------------------------------------
573 void KMFolderMgr::renameFolder( KMFolder
* folder
, const QString
& newName
,
574 KMFolderDir
*newParent
)
576 RenameJob
* job
= new RenameJob( folder
->storage(), newName
, newParent
);
577 connect( job
, SIGNAL( renameDone( const QString
&, bool ) ),
578 this, SLOT( slotRenameDone( const QString
&, bool ) ) );
579 connect( job
, SIGNAL( renameDone( const QString
&, bool ) ),
580 this, SIGNAL( folderMoveOrCopyOperationFinished() ) );
585 //-----------------------------------------------------------------------------
586 void KMFolderMgr::copyFolder( KMFolder
* folder
, KMFolderDir
*newParent
)
588 kDebug() << "Copy folder:" << folder
->prettyUrl();
589 CopyFolderJob
* job
= new CopyFolderJob( folder
->storage(), newParent
);
590 connect( job
, SIGNAL( folderCopyComplete( bool ) ),
591 this, SIGNAL( folderMoveOrCopyOperationFinished() ) );
595 //-----------------------------------------------------------------------------
596 void KMFolderMgr::slotRenameDone( const QString
&, bool success
)
601 #include "kmfoldermgr.moc"