00001
00002
00003 #ifdef HAVE_CONFIG_H
00004 #include <config.h>
00005 #endif
00006
00007 #include <sys/types.h>
00008
00009 #ifdef HAVE_SYS_STAT_H
00010 #include <sys/stat.h>
00011 #endif
00012
00013 #include <assert.h>
00014 #include <fcntl.h>
00015 #include <stdlib.h>
00016 #include <unistd.h>
00017 #include <time.h>
00018
00019 #include <qdir.h>
00020
00021 #include <klocale.h>
00022 #include <kmessagebox.h>
00023 #include <kconfig.h>
00024 #include <kdebug.h>
00025 #include <kapplication.h>
00026
00027 #include "kmmainwin.h"
00028 #include "kmfiltermgr.h"
00029 #include "kmfoldermgr.h"
00030 #include "folderstorage.h"
00031 #include "renamejob.h"
00032 #include "copyfolderjob.h"
00033
00034 using KMail::RenameJob;
00035 using KMail::CopyFolderJob;
00036
00037
00038 KMFolderMgr::KMFolderMgr(const QString& aBasePath, KMFolderDirType dirType):
00039 QObject(), mDir(this, QString::null, dirType)
00040 {
00041 if ( dirType == KMStandardDir )
00042 mDir.setBaseURL( I18N_NOOP("Local Folders") );
00043 mQuiet = 0;
00044 mChanged = FALSE;
00045 setBasePath(aBasePath);
00046 mRemoveOrig = 0;
00047 }
00048
00049
00050
00051 KMFolderMgr::~KMFolderMgr()
00052 {
00053 mBasePath = QString::null;
00054 }
00055
00056
00057
00058 void KMFolderMgr::expireAll() {
00059 KConfig *config = KMKernel::config();
00060 KConfigGroupSaver saver(config, "General");
00061 int ret = KMessageBox::Continue;
00062
00063 if (config->readBoolEntry("warn-before-expire", true)) {
00064 ret = KMessageBox::warningContinueCancel(KMainWindow::memberList->first(),
00065 i18n("Are you sure you want to expire old messages?"),
00066 i18n("Expire Old Messages?"), i18n("Expire"));
00067 }
00068
00069 if (ret == KMessageBox::Continue) {
00070 expireAllFolders( true );
00071 }
00072
00073 }
00074
00075 #define DO_FOR_ALL(function, folder_code) \
00076 KMFolderNode* node; \
00077 QPtrListIterator<KMFolderNode> it(*dir); \
00078 for ( ; (node = it.current()); ) { \
00079 ++it; \
00080 if (node->isDir()) continue; \
00081 KMFolder *folder = static_cast<KMFolder*>(node); \
00082 folder_code \
00083 KMFolderDir *child = folder->child(); \
00084 if (child) \
00085 function \
00086 }
00087
00088 int KMFolderMgr::folderCount(KMFolderDir *dir)
00089 {
00090 int count = 0;
00091 if (dir == 0)
00092 dir = &mDir;
00093 DO_FOR_ALL(
00094 {
00095 count += folderCount( child );
00096 },
00097 {
00098 count++;
00099 }
00100 )
00101
00102 return count;
00103 }
00104
00105
00106
00107
00108 void KMFolderMgr::compactAllFolders(bool immediate, KMFolderDir* dir)
00109 {
00110 if (dir == 0)
00111 dir = &mDir;
00112 DO_FOR_ALL(
00113 {
00114 compactAllFolders( immediate, child );
00115 },
00116 {
00117 if ( folder->needsCompacting() )
00118 folder->compact( immediate ? KMFolder::CompactNow : KMFolder::CompactLater );
00119 }
00120 )
00121 }
00122
00123
00124
00125 void KMFolderMgr::setBasePath(const QString& aBasePath)
00126 {
00127 assert(!aBasePath.isNull());
00128
00129 if (aBasePath[0] == '~')
00130 {
00131 mBasePath = QDir::homeDirPath();
00132 mBasePath.append("/");
00133 mBasePath.append(aBasePath.mid(1));
00134 }
00135 else
00136 mBasePath = aBasePath;
00137
00138 QFileInfo info( mBasePath );
00139
00140
00141
00142 if ( info.exists() ) {
00143 if ( !info.isDir() ) {
00144 KMessageBox::sorry(0, i18n("'%1' does not appear to be a folder.\n"
00145 "Please move the file out of the way.")
00146 .arg( mBasePath ) );
00147 ::exit(-1);
00148 }
00149 if ( !info.isReadable() || !info.isWritable() ) {
00150 KMessageBox::sorry(0, i18n("The permissions of the folder '%1' are "
00151 "incorrect;\n"
00152 "please make sure that you can view and modify "
00153 "the content of this folder.")
00154 .arg( mBasePath ) );
00155 ::exit(-1);
00156 }
00157 } else {
00158
00159 if ( ::mkdir( QFile::encodeName( mBasePath ) , S_IRWXU ) == -1 ) {
00160 KMessageBox::sorry(0, i18n("KMail could not create folder '%1';\n"
00161 "please make sure that you can view and "
00162 "modify the content of the folder '%2'.")
00163 .arg( mBasePath ).arg( QDir::homeDirPath() ) );
00164 ::exit(-1);
00165 }
00166 }
00167 mDir.setPath(mBasePath);
00168 mDir.reload();
00169 contentsChanged();
00170 }
00171
00172
00173
00174 KMFolder* KMFolderMgr::createFolder(const QString& fName, bool sysFldr,
00175 KMFolderType aFolderType,
00176 KMFolderDir *aFolderDir)
00177 {
00178 KMFolder* fld;
00179 KMFolderDir *fldDir = aFolderDir;
00180
00181 if (!aFolderDir)
00182 fldDir = &mDir;
00183 fld = fldDir->createFolder(fName, sysFldr, aFolderType);
00184 if (fld) {
00185 if ( fld->id() == 0 )
00186 fld->setId( createId() );
00187 contentsChanged();
00188 emit folderAdded(fld);
00189 if (kmkernel->filterMgr())
00190 kmkernel->filterMgr()->folderCreated(fld);
00191 }
00192
00193 return fld;
00194 }
00195
00196
00197
00198 KMFolder* KMFolderMgr::find(const QString& folderName, bool foldersOnly)
00199 {
00200 KMFolderNode* node;
00201
00202 for (node=mDir.first(); node; node=mDir.next())
00203 {
00204 if (node->isDir() && foldersOnly) continue;
00205 if (node->name()==folderName) return (KMFolder*)node;
00206 }
00207 return 0;
00208 }
00209
00210
00211 KMFolder* KMFolderMgr::findById(const uint id)
00212 {
00213 return findIdString( QString::null, id );
00214 }
00215
00216
00217 KMFolder* KMFolderMgr::findIdString( const QString& folderId,
00218 const uint id,
00219 KMFolderDir *dir )
00220 {
00221 if (!dir)
00222 dir = &mDir;
00223
00224 DO_FOR_ALL(
00225 {
00226 KMFolder *folder = findIdString( folderId, id, child );
00227 if ( folder )
00228 return folder;
00229 },
00230 {
00231 if ( ( !folderId.isEmpty() && folder->idString() == folderId ) ||
00232 ( id != 0 && folder->id() == id ) )
00233 return folder;
00234 }
00235 )
00236
00237 return 0;
00238 }
00239
00240 void KMFolderMgr::getFolderURLS( QStringList& flist, const QString& prefix,
00241 KMFolderDir *adir )
00242 {
00243 KMFolderDir* dir = adir ? adir : &mDir;
00244
00245 DO_FOR_ALL(
00246 {
00247 getFolderURLS( flist, prefix + "/" + folder->name(), child );
00248 },
00249 {
00250 flist << prefix + "/" + folder->name();
00251 }
00252 )
00253 }
00254
00255 KMFolder* KMFolderMgr::getFolderByURL( const QString& vpath,
00256 const QString& prefix,
00257 KMFolderDir *adir )
00258 {
00259 KMFolderDir* dir = adir ? adir : &mDir;
00260 DO_FOR_ALL(
00261 {
00262 QString a = prefix + "/" + folder->name();
00263 KMFolder * mfolder = getFolderByURL( vpath, a,child );
00264 if ( mfolder )
00265 return mfolder;
00266 },
00267 {
00268 QString comp = prefix + "/" + folder->name();
00269 if ( comp == vpath )
00270 return folder;
00271 }
00272 )
00273 return 0;
00274 }
00275
00276
00277 KMFolder* KMFolderMgr::findOrCreate(const QString& aFolderName, bool sysFldr,
00278 const uint id)
00279 {
00280 KMFolder* folder = 0;
00281 if ( id == 0 )
00282 folder = find(aFolderName);
00283 else
00284 folder = findById(id);
00285
00286 if (!folder)
00287 {
00288 static bool know_type = false;
00289 static KMFolderType type = KMFolderTypeMaildir;
00290 if (know_type == false)
00291 {
00292 know_type = true;
00293 KConfig *config = KMKernel::config();
00294 KConfigGroupSaver saver(config, "General");
00295 if (config->hasKey("default-mailbox-format"))
00296 {
00297 if (config->readNumEntry("default-mailbox-format", 1) == 0)
00298 type = KMFolderTypeMbox;
00299
00300 }
00301 }
00302
00303 folder = createFolder(aFolderName, sysFldr, type);
00304 if (!folder) {
00305 KMessageBox::error(0,(i18n("Cannot create file `%1' in %2.\nKMail cannot start without it.").arg(aFolderName).arg(mBasePath)));
00306 exit(-1);
00307 }
00308 if ( id > 0 )
00309 folder->setId( id );
00310 }
00311 return folder;
00312 }
00313
00314
00315
00316 void KMFolderMgr::remove(KMFolder* aFolder)
00317 {
00318 if (!aFolder) return;
00319
00320 if (!mRemoveOrig) mRemoveOrig = aFolder;
00321 if (aFolder->child())
00322 {
00323
00324 KMFolderNode* node;
00325 QPtrListIterator<KMFolderNode> it(*aFolder->child());
00326 for ( ; (node = it.current()); )
00327 {
00328 ++it;
00329 if (node->isDir()) continue;
00330 KMFolder *folder = static_cast<KMFolder*>(node);
00331 remove(folder);
00332 }
00333 }
00334 emit folderRemoved(aFolder);
00335 removeFolder(aFolder);
00336 }
00337
00338 void KMFolderMgr::removeFolder(KMFolder* aFolder)
00339 {
00340 connect(aFolder, SIGNAL(removed(KMFolder*, bool)),
00341 this, SLOT(removeFolderAux(KMFolder*, bool)));
00342 aFolder->remove();
00343 }
00344
00345 void KMFolderMgr::removeFolderAux(KMFolder* aFolder, bool success)
00346 {
00347 if (!success) {
00348 mRemoveOrig = 0;
00349 return;
00350 }
00351
00352 KMFolderDir* fdir = aFolder->parent();
00353 KMFolderNode* fN;
00354 for (fN = fdir->first(); fN != 0; fN = fdir->next()) {
00355 if (fN->isDir() && (fN->name() == "." + aFolder->fileName() + ".directory")) {
00356 removeDirAux(static_cast<KMFolderDir*>(fN));
00357 break;
00358 }
00359 }
00360
00361 QString parentName = fdir->name();
00362 parentName = parentName.mid( 1, parentName.length()-11 );
00363 KMFolderNode* parent = fdir->hasNamedFolder( parentName );
00364 if ( !parent && fdir->parent() )
00365 parent = fdir->parent()->hasNamedFolder( parentName );
00366
00367 aFolder->parent()->remove(aFolder);
00368
00369 if ( parent )
00370 static_cast<KMFolder*>(parent)->storage()->updateChildrenState();
00371 else
00372 kdWarning(5006) << "Can not find parent folder" << endl;
00373
00374 if (aFolder == mRemoveOrig) {
00375
00376 contentsChanged();
00377 mRemoveOrig = 0;
00378 }
00379 }
00380
00381 void KMFolderMgr::removeDirAux(KMFolderDir* aFolderDir)
00382 {
00383 QDir dir;
00384 QString folderDirLocation = aFolderDir->path();
00385 aFolderDir->clear();
00386 aFolderDir->parent()->remove(aFolderDir);
00387 dir.rmdir(folderDirLocation);
00388 }
00389
00390
00391 KMFolderRootDir& KMFolderMgr::dir(void)
00392 {
00393 return mDir;
00394 }
00395
00396
00397
00398 void KMFolderMgr::contentsChanged(void)
00399 {
00400 if (mQuiet) mChanged = TRUE;
00401 else emit changed();
00402 }
00403
00404
00405
00406 void KMFolderMgr::reload(void)
00407 {
00408 }
00409
00410
00411 void KMFolderMgr::createFolderList(QStringList *str,
00412 QValueList<QGuardedPtr<KMFolder> > *folders)
00413 {
00414 createFolderList( str, folders, 0, "" );
00415 }
00416
00417
00418 void KMFolderMgr::createI18nFolderList(QStringList *str,
00419 QValueList<QGuardedPtr<KMFolder> > *folders)
00420 {
00421 createFolderList( str, folders, 0, QString::null, true );
00422 }
00423
00424
00425 void KMFolderMgr::createFolderList(QStringList *str,
00426 QValueList<QGuardedPtr<KMFolder> > *folders,
00427 KMFolderDir *adir,
00428 const QString& prefix,
00429 bool i18nized)
00430 {
00431 KMFolderDir* dir = adir ? adir : &mDir;
00432
00433 DO_FOR_ALL(
00434 {
00435 createFolderList(str, folders, child, " " + prefix, i18nized );
00436 },
00437 {
00438 if (i18nized)
00439 str->append(prefix + folder->label());
00440 else
00441 str->append(prefix + folder->name());
00442 folders->append( folder );
00443 }
00444 )
00445 }
00446
00447
00448 void KMFolderMgr::syncAllFolders( KMFolderDir *adir )
00449 {
00450 KMFolderDir* dir = adir ? adir : &mDir;
00451 DO_FOR_ALL(
00452 {
00453 syncAllFolders(child);
00454 },
00455 {
00456 if (folder->isOpened())
00457 folder->sync();
00458 }
00459 )
00460 }
00461
00462
00463
00470 void KMFolderMgr::expireAllFolders(bool immediate, KMFolderDir *adir) {
00471 KMFolderDir *dir = adir ? adir : &mDir;
00472
00473 DO_FOR_ALL(
00474 {
00475 expireAllFolders(immediate, child);
00476 },
00477 {
00478 if (folder->isAutoExpire()) {
00479 folder->expireOldMessages( immediate );
00480 }
00481 }
00482 )
00483 }
00484
00485
00486 void KMFolderMgr::quiet(bool beQuiet)
00487 {
00488 if (beQuiet)
00489 mQuiet++;
00490 else {
00491 mQuiet--;
00492 if (mQuiet <= 0)
00493 {
00494 mQuiet = 0;
00495 if (mChanged) emit changed();
00496 mChanged = FALSE;
00497 }
00498 }
00499 }
00500
00501
00502 void KMFolderMgr::tryReleasingFolder(KMFolder* f, KMFolderDir* adir)
00503 {
00504 KMFolderDir* dir = adir ? adir : &mDir;
00505 DO_FOR_ALL(
00506 {
00507 tryReleasingFolder(f, child);
00508 },
00509 {
00510 if (folder->isOpened())
00511 folder->storage()->tryReleasingFolder(f);
00512 }
00513 )
00514 }
00515
00516
00517 uint KMFolderMgr::createId()
00518 {
00519 int newId;
00520 do
00521 {
00522 newId = kapp->random();
00523 } while ( findById( newId ) != 0 );
00524
00525 return newId;
00526 }
00527
00528
00529 void KMFolderMgr::moveFolder( KMFolder* folder, KMFolderDir *newParent )
00530 {
00531 renameFolder( folder, folder->name(), newParent );
00532 }
00533
00534
00535 void KMFolderMgr::renameFolder( KMFolder* folder, const QString& newName,
00536 KMFolderDir *newParent )
00537 {
00538 RenameJob* job = new RenameJob( folder->storage(), newName, newParent );
00539 connect( job, SIGNAL( renameDone( QString, bool ) ),
00540 this, SLOT( slotRenameDone( QString, bool ) ) );
00541 connect( job, SIGNAL( renameDone( QString, bool ) ),
00542 this, SIGNAL( folderMoveOrCopyOperationFinished() ) );
00543 job->start();
00544 }
00545
00546
00547 void KMFolderMgr::copyFolder( KMFolder* folder, KMFolderDir *newParent )
00548 {
00549 kdDebug(5006) << "Copy folder: " << folder->prettyURL() << endl;
00550 CopyFolderJob* job = new CopyFolderJob( folder->storage(), newParent );
00551 connect( job, SIGNAL( folderCopyComplete( bool ) ),
00552 this, SIGNAL( folderMoveOrCopyOperationFinished() ) );
00553 job->start();
00554 }
00555
00556
00557 void KMFolderMgr::slotRenameDone( QString, bool success )
00558 {
00559 kdDebug(5006) << k_funcinfo << success << endl;
00560 }
00561
00562 #include "kmfoldermgr.moc"