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