kmail Library API Documentation

kmfoldermgr.cpp

00001 // kmfoldermgr.cpp
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 "undostack.h"
00031 #include "kmmsgdict.h"
00032 #include "folderstorage.h"
00033 #include "renamejob.h"
00034 #include "copyfolderjob.h"
00035 
00036 using KMail::RenameJob;
00037 using KMail::CopyFolderJob;
00038 
00039 //-----------------------------------------------------------------------------
00040 KMFolderMgr::KMFolderMgr(const QString& aBasePath, KMFolderDirType dirType):
00041   QObject(), mDir(this, QString::null, dirType)
00042 {
00043   if ( dirType == KMStandardDir )
00044     mDir.setBaseURL( I18N_NOOP("Local") );
00045   mQuiet = 0;
00046   mChanged = FALSE;
00047   setBasePath(aBasePath);
00048   mRemoveOrig = 0;
00049 }
00050 
00051 
00052 //-----------------------------------------------------------------------------
00053 KMFolderMgr::~KMFolderMgr()
00054 {
00055   if  (kmkernel->undoStack())
00056     kmkernel->undoStack()->clear(); // Speed things up a bit.
00057   mBasePath = QString::null;
00058 }
00059 
00060 
00061 //-----------------------------------------------------------------------------
00062 void KMFolderMgr::expireAll() {
00063   KConfig             *config = KMKernel::config();
00064   KConfigGroupSaver   saver(config, "General");
00065   int                 ret = KMessageBox::Continue;
00066 
00067   if (config->readBoolEntry("warn-before-expire", true)) {
00068     ret = KMessageBox::warningContinueCancel(KMainWindow::memberList->first(),
00069              i18n("Are you sure you want to expire old messages?"),
00070              i18n("Expire Old Messages?"), i18n("Expire"));
00071   }
00072 
00073   if (ret == KMessageBox::Continue) {
00074     expireAllFolders( true /*immediate*/ );
00075   }
00076 
00077 }
00078 
00079 #define DO_FOR_ALL(function, folder_code) \
00080   KMFolderNode* node; \
00081   QPtrListIterator<KMFolderNode> it(*dir); \
00082   for ( ; (node = it.current()); ) { \
00083     ++it; \
00084     if (node->isDir()) continue; \
00085     KMFolder *folder = static_cast<KMFolder*>(node); \
00086     folder_code \
00087     KMFolderDir *child = folder->child(); \
00088     if (child) \
00089        function \
00090   }
00091 
00092 int KMFolderMgr::folderCount(KMFolderDir *dir)
00093 {
00094   int count = 0;
00095   if (dir == 0)
00096     dir = &mDir;
00097   DO_FOR_ALL(
00098         {
00099           count += folderCount( child );
00100         },
00101         {
00102           count++;
00103         }
00104   )
00105 
00106   return count;
00107 }
00108 
00109 
00110 
00111 //-----------------------------------------------------------------------------
00112 void KMFolderMgr::compactAllFolders(bool immediate, KMFolderDir* dir)
00113 {
00114   if (dir == 0)
00115     dir = &mDir;
00116   DO_FOR_ALL(
00117         {
00118           compactAllFolders( immediate, child );
00119         },
00120         {
00121           if ( folder->needsCompacting() )
00122               folder->compact( immediate ? KMFolder::CompactNow : KMFolder::CompactLater );
00123         }
00124   )
00125 }
00126 
00127 
00128 //-----------------------------------------------------------------------------
00129 void KMFolderMgr::setBasePath(const QString& aBasePath)
00130 {
00131   assert(!aBasePath.isNull());
00132 
00133   if (aBasePath[0] == '~')
00134   {
00135     mBasePath = QDir::homeDirPath();
00136     mBasePath.append("/");
00137     mBasePath.append(aBasePath.mid(1));
00138   }
00139   else
00140     mBasePath = aBasePath;
00141 
00142   QFileInfo info( mBasePath );
00143 
00144   // FIXME We should ask for an alternative dir, rather than bailing out,
00145   // I guess - till
00146   if ( info.exists() ) {
00147    if ( !info.isDir() ) {
00148       KMessageBox::sorry(0, i18n("'%1' does not appear to be a folder.\n"
00149                                  "Please move the file out of the way.")
00150                             .arg( mBasePath ) );
00151       ::exit(-1);
00152     }
00153     if ( !info.isReadable() || !info.isWritable() ) {
00154       KMessageBox::sorry(0, i18n("The permissions of the folder '%1' are "
00155                                "incorrect;\n"
00156                                "please make sure that you can view and modify "
00157                                "the content of this folder.")
00158                             .arg( mBasePath ) );
00159       ::exit(-1);
00160     }
00161    } else {
00162     // ~/Mail (or whatever the user specified) doesn't exist, create it
00163     if ( ::mkdir( QFile::encodeName( mBasePath ) , S_IRWXU ) == -1 ) {
00164       KMessageBox::sorry(0, i18n("KMail could not create folder '%1';\n"
00165                                  "please make sure that you can view and "
00166                                  "modify the content of the folder '%2'.")
00167                             .arg( mBasePath ).arg( QDir::homeDirPath() ) );
00168       ::exit(-1);
00169     }
00170   }
00171   mDir.setPath(mBasePath);
00172   mDir.reload();
00173   contentsChanged();
00174 }
00175 
00176 
00177 //-----------------------------------------------------------------------------
00178 KMFolder* KMFolderMgr::createFolder(const QString& fName, bool sysFldr,
00179                     KMFolderType aFolderType,
00180                     KMFolderDir *aFolderDir)
00181 {
00182   KMFolder* fld;
00183   KMFolderDir *fldDir = aFolderDir;
00184 
00185   if (!aFolderDir)
00186     fldDir = &mDir;
00187   fld = fldDir->createFolder(fName, sysFldr, aFolderType);
00188   if (fld) {
00189     contentsChanged();
00190     emit folderAdded(fld);
00191     if (kmkernel->filterMgr())
00192       kmkernel->filterMgr()->folderCreated(fld);
00193   }
00194 
00195   return fld;
00196 }
00197 
00198 
00199 //-----------------------------------------------------------------------------
00200 KMFolder* KMFolderMgr::find(const QString& folderName, bool foldersOnly)
00201 {
00202   KMFolderNode* node;
00203 
00204   for (node=mDir.first(); node; node=mDir.next())
00205   {
00206     if (node->isDir() && foldersOnly) continue;
00207     if (node->name()==folderName) return (KMFolder*)node;
00208   }
00209   return 0;
00210 }
00211 
00212 //-----------------------------------------------------------------------------
00213 KMFolder* KMFolderMgr::findById(const uint id)
00214 {
00215   return findIdString( QString::null, id );
00216 }
00217 
00218 //-----------------------------------------------------------------------------
00219 KMFolder* KMFolderMgr::findIdString( const QString& folderId,
00220                                      const uint id,
00221                                      KMFolderDir *dir )
00222 {
00223   if (!dir)
00224     dir = &mDir;
00225 
00226   DO_FOR_ALL(
00227         {
00228           KMFolder *folder = findIdString( folderId, id, child );
00229           if ( folder )
00230              return folder;
00231         },
00232         {
00233           if ( ( !folderId.isEmpty() && folder->idString() == folderId ) ||
00234                ( id != 0 && folder->id() == id ) )
00235              return folder;
00236         }
00237   )
00238 
00239   return 0;
00240 }
00241 
00242 void KMFolderMgr::getFolderURLS( QStringList& flist, const QString& prefix,
00243                                  KMFolderDir *adir )
00244 {
00245   KMFolderDir* dir = adir ? adir : &mDir;
00246 
00247   DO_FOR_ALL(
00248              {
00249                getFolderURLS( flist, prefix + "/" + folder->name(), child );
00250              },
00251              {
00252                flist << prefix + "/" + folder->name();
00253              }
00254              )
00255 }
00256 
00257 KMFolder* KMFolderMgr::getFolderByURL( const QString& vpath,
00258                                        const QString& prefix,
00259                                        KMFolderDir *adir )
00260 {
00261   KMFolderDir* dir = adir ? adir : &mDir;
00262   DO_FOR_ALL(
00263         {
00264           QString a = prefix + "/" + folder->name();
00265           KMFolder * mfolder = getFolderByURL( vpath, a,child );
00266           if ( mfolder )
00267             return mfolder;
00268         },
00269         {
00270           QString comp = prefix + "/" + folder->name();
00271           if ( comp  == vpath )
00272             return folder;
00273         }
00274   )
00275   return 0;
00276 }
00277 
00278 //-----------------------------------------------------------------------------
00279 KMFolder* KMFolderMgr::findOrCreate(const QString& aFolderName, bool sysFldr,
00280                                     const uint id)
00281 {
00282   KMFolder* folder = 0;
00283   if ( id == 0 )
00284     folder = find(aFolderName);
00285   else
00286     folder = findById(id);
00287 
00288   if (!folder)
00289   {
00290     static bool know_type = false;
00291     static KMFolderType type = KMFolderTypeMaildir;
00292     if (know_type == false)
00293     {
00294       know_type = true;
00295       KConfig *config = KMKernel::config();
00296       KConfigGroupSaver saver(config, "General");
00297       if (config->hasKey("default-mailbox-format"))
00298       {
00299         if (config->readNumEntry("default-mailbox-format", 1) == 0)
00300           type = KMFolderTypeMbox;
00301 
00302       }
00303     }
00304 
00305     folder = createFolder(aFolderName, sysFldr, type);
00306     if (!folder) {
00307       KMessageBox::error(0,(i18n("Cannot create file `%1' in %2.\nKMail cannot start without it.").arg(aFolderName).arg(mBasePath)));
00308       exit(-1);
00309     }
00310     if ( id > 0 )
00311       folder->setId( id );
00312   }
00313   return folder;
00314 }
00315 
00316 
00317 //-----------------------------------------------------------------------------
00318 void KMFolderMgr::remove(KMFolder* aFolder)
00319 {
00320   if (!aFolder) return;
00321   // remember the original folder to trigger contentsChanged later
00322   if (!mRemoveOrig) mRemoveOrig = aFolder;
00323   if (aFolder->child())
00324   {
00325     // call remove for every child
00326     KMFolderNode* node;
00327     QPtrListIterator<KMFolderNode> it(*aFolder->child());
00328     for ( ; (node = it.current()); )
00329     {
00330       ++it;
00331       if (node->isDir()) continue;
00332       KMFolder *folder = static_cast<KMFolder*>(node);
00333       remove(folder);
00334     }
00335   }
00336   emit folderRemoved(aFolder);
00337   removeFolder(aFolder);
00338 }
00339 
00340 void KMFolderMgr::removeFolder(KMFolder* aFolder)
00341 {
00342   connect(aFolder, SIGNAL(removed(KMFolder*, bool)),
00343       this, SLOT(removeFolderAux(KMFolder*, bool)));
00344   aFolder->remove();
00345 }
00346 
00347 void KMFolderMgr::removeFolderAux(KMFolder* aFolder, bool success)
00348 {
00349   if (!success) {
00350     mRemoveOrig = 0;
00351     return;
00352   }
00353 
00354   KMFolderDir* fdir = aFolder->parent();
00355   KMFolderNode* fN;
00356   for (fN = fdir->first(); fN != 0; fN = fdir->next()) {
00357     if (fN->isDir() && (fN->name() == "." + aFolder->fileName() + ".directory")) {
00358       removeDirAux(static_cast<KMFolderDir*>(fN));
00359       break;
00360     }
00361   }
00362   aFolder->parent()->remove(aFolder);
00363   // find the parent folder by stripping "." and ".directory" from the name
00364   QString parentName = fdir->name();
00365   parentName = parentName.mid( 1, parentName.length()-11 );
00366   KMFolderNode* parent = fdir->hasNamedFolder( parentName );
00367   if ( !parent && fdir->parent() ) // dimap obviously has a different structure
00368     parent = fdir->parent()->hasNamedFolder( parentName );
00369   // update the children state
00370   if ( parent )
00371     static_cast<KMFolder*>(parent)->storage()->updateChildrenState();
00372   else
00373     kdWarning(5006) << "Can not find parent folder" << endl;
00374 
00375   if (aFolder == mRemoveOrig) {
00376     // call only if we're removing the original parent folder
00377     contentsChanged();
00378     mRemoveOrig = 0;
00379   }
00380 }
00381 
00382 void KMFolderMgr::removeDirAux(KMFolderDir* aFolderDir)
00383 {
00384   QDir dir;
00385   QString folderDirLocation = aFolderDir->path();
00386   aFolderDir->clear();
00387   aFolderDir->parent()->remove(aFolderDir);
00388   dir.rmdir(folderDirLocation);
00389 }
00390 
00391 //-----------------------------------------------------------------------------
00392 KMFolderRootDir& KMFolderMgr::dir(void)
00393 {
00394   return mDir;
00395 }
00396 
00397 
00398 //-----------------------------------------------------------------------------
00399 void KMFolderMgr::contentsChanged(void)
00400 {
00401   if (mQuiet) mChanged = TRUE;
00402   else emit changed();
00403 }
00404 
00405 
00406 //-----------------------------------------------------------------------------
00407 void KMFolderMgr::reload(void)
00408 {
00409 }
00410 
00411 //-----------------------------------------------------------------------------
00412 void KMFolderMgr::createFolderList(QStringList *str,
00413                    QValueList<QGuardedPtr<KMFolder> > *folders)
00414 {
00415   createFolderList( str, folders, 0, "" );
00416 }
00417 
00418 //-----------------------------------------------------------------------------
00419 void KMFolderMgr::createI18nFolderList(QStringList *str,
00420                    QValueList<QGuardedPtr<KMFolder> > *folders)
00421 {
00422   createFolderList( str, folders, 0, QString::null, true );
00423 }
00424 
00425 //-----------------------------------------------------------------------------
00426 void KMFolderMgr::createFolderList(QStringList *str,
00427                    QValueList<QGuardedPtr<KMFolder> > *folders,
00428                    KMFolderDir *adir,
00429                    const QString& prefix,
00430                    bool i18nized)
00431 {
00432   KMFolderDir* dir = adir ? adir : &mDir;
00433 
00434   DO_FOR_ALL(
00435         {
00436           createFolderList(str, folders, child, "  " + prefix, i18nized );
00437         },
00438         {
00439           if (i18nized)
00440             str->append(prefix + folder->label());
00441           else
00442             str->append(prefix + folder->name());
00443           folders->append( folder );
00444         }
00445   )
00446 }
00447 
00448 //-----------------------------------------------------------------------------
00449 void KMFolderMgr::syncAllFolders( KMFolderDir *adir )
00450 {
00451   KMFolderDir* dir = adir ? adir : &mDir;
00452   DO_FOR_ALL(
00453              {
00454                syncAllFolders(child);
00455              },
00456              {
00457                if (folder->isOpened())
00458              folder->sync();
00459              }
00460   )
00461 }
00462 
00463 
00464 //-----------------------------------------------------------------------------
00471 void KMFolderMgr::expireAllFolders(bool immediate, KMFolderDir *adir) {
00472   KMFolderDir   *dir = adir ? adir : &mDir;
00473 
00474   DO_FOR_ALL(
00475              {
00476                expireAllFolders(immediate, child);
00477              },
00478              {
00479                if (folder->isAutoExpire()) {
00480                  folder->expireOldMessages( immediate );
00481                }
00482              }
00483   )
00484 }
00485 
00486 //-----------------------------------------------------------------------------
00487 void KMFolderMgr::invalidateFolder(KMMsgDict *dict, KMFolder *folder)
00488 {
00489     unlink(QFile::encodeName(folder->indexLocation()) + ".sorted");
00490     unlink(QFile::encodeName(folder->indexLocation()) + ".ids");
00491     if (dict) {
00492     folder->fillMsgDict(dict);
00493     dict->writeFolderIds(folder);
00494     }
00495     emit folderInvalidated(folder);
00496 }
00497 
00498 //-----------------------------------------------------------------------------
00499 void KMFolderMgr::readMsgDict(KMMsgDict *dict, KMFolderDir *dir, int pass)
00500 {
00501   bool atTop = false;
00502   if (!dir) {
00503     dir = &mDir;
00504     atTop = true;
00505   }
00506 
00507   DO_FOR_ALL(
00508              {
00509                readMsgDict(dict, child, pass);
00510              },
00511              {
00512            if (pass == 1) {
00513                  dict->readFolderIds(folder);
00514                } else if (pass == 2) {
00515                  if (!dict->hasFolderIds(folder)) {
00516            invalidateFolder(dict, folder);
00517                  }
00518                }
00519              }
00520   )
00521 
00522   if (pass == 1 && atTop)
00523     readMsgDict(dict, dir, pass + 1);
00524 }
00525 
00526 //-----------------------------------------------------------------------------
00527 void KMFolderMgr::writeMsgDict(KMMsgDict *dict, KMFolderDir *dir)
00528 {
00529   if (!dir)
00530     dir = &mDir;
00531 
00532   DO_FOR_ALL(
00533              {
00534                writeMsgDict(dict, child);
00535              },
00536              {
00537                folder->writeMsgDict(dict);
00538              }
00539   )
00540 }
00541 
00542 //-----------------------------------------------------------------------------
00543 void KMFolderMgr::quiet(bool beQuiet)
00544 {
00545   if (beQuiet)
00546     mQuiet++;
00547   else {
00548     mQuiet--;
00549     if (mQuiet <= 0)
00550     {
00551       mQuiet = 0;
00552       if (mChanged) emit changed();
00553       mChanged = FALSE;
00554     }
00555   }
00556 }
00557 
00558 //-----------------------------------------------------------------------------
00559 void KMFolderMgr::tryReleasingFolder(KMFolder* f, KMFolderDir* adir)
00560 {
00561   KMFolderDir* dir = adir ? adir : &mDir;
00562   DO_FOR_ALL(
00563              {
00564                tryReleasingFolder(f, child);
00565              },
00566              {
00567                if (folder->isOpened())
00568              folder->storage()->tryReleasingFolder(f);
00569              }
00570   )
00571 }
00572 
00573 //-----------------------------------------------------------------------------
00574 uint KMFolderMgr::createId()
00575 {
00576   int newId;
00577   do
00578   {
00579     newId = kapp->random();
00580   } while ( findById( newId ) != 0 );
00581 
00582   return newId;
00583 }
00584 
00585 //-----------------------------------------------------------------------------
00586 void KMFolderMgr::moveFolder( KMFolder* folder, KMFolderDir *newParent )
00587 {
00588   renameFolder( folder, folder->name(), newParent );
00589 }
00590 
00591 //-----------------------------------------------------------------------------
00592 void KMFolderMgr::renameFolder( KMFolder* folder, const QString& newName,
00593                                 KMFolderDir *newParent )
00594 {
00595   RenameJob* job = new RenameJob( folder->storage(), newName, newParent );
00596   connect( job, SIGNAL( renameDone( QString, bool ) ),
00597       this, SLOT( slotRenameDone( QString, bool ) ) );
00598   job->start();
00599 }
00600 
00601 //-----------------------------------------------------------------------------
00602 void KMFolderMgr::copyFolder( KMFolder* folder, KMFolderDir *newParent )
00603 {
00604   kdDebug(5006) << "Copy folder: " << folder->prettyURL() << endl;
00605   CopyFolderJob* job = new CopyFolderJob( folder->storage(), newParent );
00606   job->start();
00607 }
00608 
00609 //-----------------------------------------------------------------------------
00610 void KMFolderMgr::slotRenameDone( QString, bool success )
00611 {
00612   kdDebug(5006) << k_funcinfo << success << endl;
00613 }
00614 
00615 #include "kmfoldermgr.moc"
KDE Logo
This file is part of the documentation for kmail Library Version 3.3.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Fri Dec 21 14:24:53 2007 by doxygen 1.4.2 written by Dimitri van Heesch, © 1997-2003