kmail

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 "folderstorage.h"
00031 #include "renamejob.h"
00032 using KMail::RenameJob;
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 Folders") );
00040   mQuiet = 0;
00041   mChanged = FALSE;
00042   setBasePath(aBasePath);
00043   mRemoveOrig = 0;
00044 }
00045 
00046 
00047 //-----------------------------------------------------------------------------
00048 KMFolderMgr::~KMFolderMgr()
00049 {
00050   mBasePath = QString::null;
00051 }
00052 
00053 
00054 //-----------------------------------------------------------------------------
00055 void KMFolderMgr::expireAll() {
00056   KConfig             *config = KMKernel::config();
00057   KConfigGroupSaver   saver(config, "General");
00058   int                 ret = KMessageBox::Continue;
00059 
00060   if (config->readBoolEntry("warn-before-expire", true)) {
00061     ret = KMessageBox::warningContinueCancel(KMainWindow::memberList->first(),
00062              i18n("Are you sure you want to expire old messages?"),
00063              i18n("Expire Old Messages?"), i18n("Expire"));
00064   }
00065 
00066   if (ret == KMessageBox::Continue) {
00067     expireAllFolders( true /*immediate*/ );
00068   }
00069 
00070 }
00071 
00072 #define DO_FOR_ALL(function, folder_code) \
00073   KMFolderNode* node; \
00074   QPtrListIterator<KMFolderNode> it(*dir); \
00075   for ( ; (node = it.current()); ) { \
00076     ++it; \
00077     if (node->isDir()) continue; \
00078     KMFolder *folder = static_cast<KMFolder*>(node); \
00079     folder_code \
00080     KMFolderDir *child = folder->child(); \
00081     if (child) \
00082        function \
00083   }
00084 
00085 int KMFolderMgr::folderCount(KMFolderDir *dir)
00086 {
00087   int count = 0;
00088   if (dir == 0)
00089     dir = &mDir;
00090   DO_FOR_ALL(
00091         {
00092           count += folderCount( child );
00093         },
00094         {
00095           count++;
00096         }
00097   )
00098 
00099   return count;
00100 }
00101 
00102 
00103 
00104 //-----------------------------------------------------------------------------
00105 void KMFolderMgr::compactAllFolders(bool immediate, KMFolderDir* dir)
00106 {
00107   if (dir == 0)
00108     dir = &mDir;
00109   DO_FOR_ALL(
00110         {
00111           compactAllFolders( immediate, child );
00112         },
00113         {
00114           if ( folder->needsCompacting() )
00115               folder->compact( immediate ? KMFolder::CompactNow : KMFolder::CompactLater );
00116         }
00117   )
00118 }
00119 
00120 
00121 //-----------------------------------------------------------------------------
00122 void KMFolderMgr::setBasePath(const QString& aBasePath)
00123 {
00124   assert(!aBasePath.isNull());
00125 
00126   if (aBasePath[0] == '~')
00127   {
00128     mBasePath = QDir::homeDirPath();
00129     mBasePath.append("/");
00130     mBasePath.append(aBasePath.mid(1));
00131   }
00132   else
00133     mBasePath = aBasePath;
00134 
00135   QFileInfo info( mBasePath );
00136 
00137   // FIXME We should ask for an alternative dir, rather than bailing out,
00138   // I guess - till
00139   if ( info.exists() ) {
00140    if ( !info.isDir() ) {
00141       KMessageBox::sorry(0, i18n("'%1' does not appear to be a folder.\n"
00142                                  "Please move the file out of the way.")
00143                             .arg( mBasePath ) );
00144       ::exit(-1);
00145     }
00146     if ( !info.isReadable() || !info.isWritable() ) {
00147       KMessageBox::sorry(0, i18n("The permissions of the folder '%1' are "
00148                                "incorrect;\n"
00149                                "please make sure that you can view and modify "
00150                                "the content of this folder.")
00151                             .arg( mBasePath ) );
00152       ::exit(-1);
00153     }
00154    } else {
00155     // ~/Mail (or whatever the user specified) doesn't exist, create it
00156     if ( ::mkdir( QFile::encodeName( mBasePath ) , S_IRWXU ) == -1 ) {
00157       KMessageBox::sorry(0, i18n("KMail could not create folder '%1';\n"
00158                                  "please make sure that you can view and "
00159                                  "modify the content of the folder '%2'.")
00160                             .arg( mBasePath ).arg( QDir::homeDirPath() ) );
00161       ::exit(-1);
00162     }
00163   }
00164   mDir.setPath(mBasePath);
00165   mDir.reload();
00166   contentsChanged();
00167 }
00168 
00169 
00170 //-----------------------------------------------------------------------------
00171 KMFolder* KMFolderMgr::createFolder(const QString& fName, bool sysFldr,
00172                     KMFolderType aFolderType,
00173                     KMFolderDir *aFolderDir)
00174 {
00175   KMFolder* fld;
00176   KMFolderDir *fldDir = aFolderDir;
00177 
00178   if (!aFolderDir)
00179     fldDir = &mDir;
00180   fld = fldDir->createFolder(fName, sysFldr, aFolderType);
00181   if (fld) {
00182     if ( fld->id() == 0 )
00183       fld->setId( createId() );
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::quiet(bool beQuiet)
00483 {
00484   if (beQuiet)
00485     mQuiet++;
00486   else {
00487     mQuiet--;
00488     if (mQuiet <= 0)
00489     {
00490       mQuiet = 0;
00491       if (mChanged) emit changed();
00492       mChanged = FALSE;
00493     }
00494   }
00495 }
00496 
00497 //-----------------------------------------------------------------------------
00498 void KMFolderMgr::tryReleasingFolder(KMFolder* f, KMFolderDir* adir)
00499 {
00500   KMFolderDir* dir = adir ? adir : &mDir;
00501   DO_FOR_ALL(
00502              {
00503                tryReleasingFolder(f, child);
00504              },
00505              {
00506                if (folder->isOpened())
00507              folder->storage()->tryReleasingFolder(f);
00508              }
00509   )
00510 }
00511 
00512 //-----------------------------------------------------------------------------
00513 uint KMFolderMgr::createId()
00514 {
00515   int newId;
00516   do
00517   {
00518     newId = kapp->random();
00519   } while ( findById( newId ) != 0 );
00520 
00521   return newId;
00522 }
00523 
00524 //-----------------------------------------------------------------------------
00525 void KMFolderMgr::moveFolder( KMFolder* folder, KMFolderDir *newParent )
00526 {
00527   renameFolder( folder, folder->name(), newParent );
00528 }
00529 
00530 //-----------------------------------------------------------------------------
00531 void KMFolderMgr::renameFolder( KMFolder* folder, const QString& newName,
00532                                 KMFolderDir *newParent )
00533 {
00534   RenameJob* job = new RenameJob( folder->storage(), newName, newParent );
00535   connect( job, SIGNAL( renameDone( QString, bool ) ),
00536       this, SLOT( slotRenameDone( QString, bool ) ) );
00537   job->start();
00538 }
00539 
00540 //-----------------------------------------------------------------------------
00541 void KMFolderMgr::slotRenameDone( QString, bool success )
00542 {
00543   kdDebug(5006) << k_funcinfo << success << endl;
00544 }
00545 
00546 #include "kmfoldermgr.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys