kmfolderdir.cpp
00001 // kmfolderdir.cpp 00002 00003 #include <config.h> 00004 #include <tqdir.h> 00005 00006 #include "kmfolderdir.h" 00007 #include "kmfoldersearch.h" 00008 #include "kmfoldercachedimap.h" 00009 #include "kmfolder.h" 00010 00011 #include <assert.h> 00012 #include <errno.h> 00013 #include <tdelocale.h> 00014 #include <tdemessagebox.h> 00015 #include <kdebug.h> 00016 #include <kstandarddirs.h> 00017 00018 00019 //============================================================================= 00020 //============================================================================= 00021 KMFolderRootDir::KMFolderRootDir(KMFolderMgr* manager, const TQString& path, 00022 KMFolderDirType dirType) 00023 : KMFolderDir( 0, 0, path, dirType ), 00024 mPath( path ), 00025 mManager( manager ) 00026 { 00027 } 00028 00029 //----------------------------------------------------------------------------- 00030 KMFolderRootDir::~KMFolderRootDir() 00031 { 00032 // WABA: We can't let KMFolderDir do this because by the time its 00033 // desctructor gets called, KMFolderRootDir is already destructed 00034 // Most notably the path. 00035 clear(); 00036 } 00037 00038 //----------------------------------------------------------------------------- 00039 void KMFolderRootDir::setPath(const TQString& aPath) 00040 { 00041 mPath = aPath; 00042 } 00043 00044 00045 //----------------------------------------------------------------------------- 00046 TQString KMFolderRootDir::path() const 00047 { 00048 return mPath; 00049 } 00050 00051 00052 //----------------------------------------------------------------------------- 00053 TQString KMFolderRootDir::prettyURL() const 00054 { 00055 if ( !mBaseURL.isEmpty() ) 00056 return i18n( mBaseURL.data() ); 00057 else 00058 return TQString(); 00059 } 00060 00061 00062 //----------------------------------------------------------------------------- 00063 void KMFolderRootDir::setBaseURL( const TQCString &baseURL ) 00064 { 00065 mBaseURL = baseURL; 00066 } 00067 00068 00069 //----------------------------------------------------------------------------- 00070 KMFolderMgr* KMFolderRootDir::manager() const 00071 { 00072 return mManager; 00073 } 00074 00075 00076 //============================================================================= 00077 //============================================================================= 00078 KMFolderDir::KMFolderDir( KMFolder * owner, KMFolderDir* parent, 00079 const TQString& name, KMFolderDirType dirType ) 00080 : KMFolderNode( parent, name ), KMFolderNodeList(), 00081 mOwner( owner ), mDirType( dirType ) 00082 { 00083 setAutoDelete( true ); 00084 } 00085 00086 00087 //----------------------------------------------------------------------------- 00088 KMFolderDir::~KMFolderDir() 00089 { 00090 clear(); 00091 } 00092 00093 00094 //----------------------------------------------------------------------------- 00095 KMFolder* KMFolderDir::createFolder(const TQString& aFolderName, bool aSysFldr, KMFolderType aFolderType) 00096 { 00097 KMFolder* fld; 00098 00099 assert(!aFolderName.isEmpty()); 00100 // FIXME urgs, is this still needed 00101 if (mDirType == KMImapDir) 00102 fld = new KMFolder( this, aFolderName, KMFolderTypeImap ); 00103 else 00104 fld = new KMFolder( this, aFolderName, aFolderType ); 00105 00106 assert(fld != 0); 00107 fld->setSystemFolder(aSysFldr); 00108 00109 KMFolderNode* fNode; 00110 int index = 0; 00111 for (fNode=first(); fNode; fNode=next()) { 00112 if (fNode->name().lower() > fld->name().lower()) { 00113 insert( index, fld ); 00114 break; 00115 } 00116 ++index; 00117 } 00118 00119 if (!fNode) 00120 append(fld); 00121 00122 fld->correctUnreadMsgsCount(); 00123 return fld; 00124 } 00125 00126 00127 //---------------------------------------------------------------------------- 00128 TQString KMFolderDir::path() const 00129 { 00130 static TQString p; 00131 00132 if (parent()) 00133 { 00134 p = parent()->path(); 00135 p.append("/"); 00136 p.append(name()); 00137 } 00138 else p = ""; 00139 00140 return p; 00141 } 00142 00143 00144 //---------------------------------------------------------------------------- 00145 TQString KMFolderDir::label() const 00146 { 00147 if ( mOwner ) 00148 return mOwner->label(); 00149 else 00150 return TQString(); 00151 } 00152 00153 00154 //----------------------------------------------------------------------------- 00155 TQString KMFolderDir::prettyURL() const 00156 { 00157 TQString parentUrl; 00158 if ( parent() ) 00159 parentUrl = parent()->prettyURL(); 00160 if ( !parentUrl.isEmpty() ) 00161 return parentUrl + '/' + label(); 00162 else 00163 return label(); 00164 } 00165 00166 //----------------------------------------------------------------------------- 00167 void KMFolderDir::addDirToParent( const TQString &dirName, KMFolder *parentFolder ) 00168 { 00169 KMFolderDir* folderDir = new KMFolderDir( parentFolder, this, dirName, mDirType); 00170 folderDir->reload(); 00171 append( folderDir ); 00172 parentFolder->setChild( folderDir ); 00173 } 00174 00175 // Get the default folder type of the given dir type. This function should only be used when 00176 // needing to find out what the folder type of a missing folder is. 00177 KMFolderType dirTypeToFolderType( KMFolderDirType dirType ) 00178 { 00179 switch( dirType ) { 00180 00181 // Use maildir for normal folder dirs, as this function is only called when finding a dir 00182 // without a parent folder, which can only happen with maildir-like folders 00183 case KMStandardDir: return KMFolderTypeMaildir; 00184 00185 case KMImapDir: return KMFolderTypeImap; 00186 case KMDImapDir: return KMFolderTypeCachedImap; 00187 case KMSearchDir: return KMFolderTypeSearch; 00188 default: Q_ASSERT( false ); return KMFolderTypeMaildir; 00189 } 00190 } 00191 00192 //----------------------------------------------------------------------------- 00193 bool KMFolderDir::reload(void) 00194 { 00195 TQDir dir; 00196 KMFolder* folder; 00197 TQFileInfo* fileInfo; 00198 TQStringList diList; 00199 TQPtrList<KMFolder> folderList; 00200 00201 clear(); 00202 00203 const TQString fldPath = path(); 00204 dir.setFilter(TQDir::Files | TQDir::Dirs | TQDir::Hidden); 00205 dir.setNameFilter("*"); 00206 00207 if (!dir.cd(fldPath, TRUE)) 00208 { 00209 TQString msg = i18n("<qt>Cannot enter folder <b>%1</b>.</qt>").arg(fldPath); 00210 KMessageBox::information(0, msg); 00211 return FALSE; 00212 } 00213 00214 TQFileInfoList* fiList=(TQFileInfoList*)dir.entryInfoList(); 00215 if (!fiList) 00216 { 00217 TQString msg = i18n("<qt>Folder <b>%1</b> is unreadable.</qt>").arg(fldPath); 00218 KMessageBox::information(0, msg); 00219 return FALSE; 00220 } 00221 00222 for (fileInfo=fiList->first(); fileInfo; fileInfo=fiList->next()) 00223 { 00224 const TQString fname = fileInfo->fileName(); 00225 if( ( fname[0] == '.' ) && !fname.endsWith( ".directory" ) ) { 00226 // ignore all hidden files except our subfolder containers 00227 continue; 00228 } 00229 if( fname == ".directory" ) { 00230 // ignore .directory files (not created by us) 00231 continue; 00232 } 00233 // Collect subdirectories. 00234 if ( fileInfo->isDir() && 00235 fname.startsWith( "." ) && fname.endsWith( ".directory" ) ) { 00236 diList.append(fname); 00237 continue; 00238 } 00239 00240 if ( mDirType == KMImapDir 00241 && path().startsWith( KMFolderImap::cacheLocation() ) ) 00242 { 00243 // Is the below needed for dimap as well? 00244 if ( KMFolderImap::encodeFileName( 00245 KMFolderImap::decodeFileName( fname ) ) == fname ) 00246 { 00247 folder = new KMFolder( this, KMFolderImap::decodeFileName( fname ), 00248 KMFolderTypeImap ); 00249 append(folder); 00250 folderList.append(folder); 00251 } 00252 } 00253 else if ( mDirType == KMDImapDir 00254 && path().startsWith( KMFolderCachedImap::cacheLocation() ) ) 00255 { 00256 if (fileInfo->isDir()) // a directory 00257 { 00258 // For this to be a cached IMAP folder, it must be in the KMail dimap 00259 // subdir and must be have a uidcache file or be a maildir folder 00260 TQString maildir(fname + "/new"); 00261 TQString imapcachefile = TQString::fromLatin1(".%1.uidcache").arg(fname); 00262 if ( dir.exists( imapcachefile) || dir.exists( maildir ) ) 00263 { 00264 folder = new KMFolder( this, fname, KMFolderTypeCachedImap ); 00265 append(folder); 00266 folderList.append(folder); 00267 } 00268 } 00269 } 00270 else if ( mDirType == KMSearchDir) 00271 { 00272 folder = new KMFolder( this, fname, KMFolderTypeSearch ); 00273 append(folder); 00274 folderList.append(folder); 00275 } 00276 else if ( mDirType == KMStandardDir ) 00277 { 00278 // This is neither an imap, dimap nor a search folder. Can be either 00279 // mbox or maildir. 00280 if (fileInfo->isDir()) 00281 { 00282 // Maildir folder 00283 if( dir.exists( fname + "/new" ) ) 00284 { 00285 folder = new KMFolder( this, fname, KMFolderTypeMaildir ); 00286 append(folder); 00287 folderList.append(folder); 00288 } 00289 } 00290 else 00291 { 00292 // all other files are folders (at the moment ;-) 00293 folder = new KMFolder( this, fname, KMFolderTypeMbox ); 00294 append(folder); 00295 folderList.append(folder); 00296 } 00297 } 00298 } 00299 00300 TQStringList dirsWithoutFolder = diList; 00301 for (folder=folderList.first(); folder; folder=folderList.next()) 00302 { 00303 for(TQStringList::Iterator it = diList.begin(); 00304 it != diList.end(); 00305 ++it) 00306 if (*it == "." + folder->fileName() + ".directory") 00307 { 00308 dirsWithoutFolder.remove( *it ); 00309 addDirToParent( *it, folder ); 00310 break; 00311 } 00312 } 00313 00314 // Check if the are any dirs without an associated folder. This can happen if the user messes 00315 // with the on-disk folder structure, see kolab issue 2972. In that case, we don't want to loose 00316 // the subfolders as well, so we recreate the folder so the folder/dir hierachy is OK again. 00317 if ( type() == KMDImapDir ) { 00318 for ( TQStringList::Iterator it = dirsWithoutFolder.begin(); 00319 it != dirsWithoutFolder.end(); ++it ) { 00320 00321 // .foo.directory => foo 00322 TQString folderName = *it; 00323 int right = folderName.find( ".directory" ); 00324 int left = folderName.find( "." ); 00325 Q_ASSERT( left != -1 && right != -1 ); 00326 folderName = folderName.mid( left + 1, right - 1 ); 00327 00328 kdDebug(5006) << "Found dir without associated folder: " << ( *it ) << ", recreating the folder " << folderName << "." << endl; 00329 00330 // Recreate the missing folder 00331 KMFolder *folder = new KMFolder( this, folderName, KMFolderTypeCachedImap ); 00332 append( folder ); 00333 folderList.append( folder ); 00334 00335 addDirToParent( *it, folder ); 00336 } 00337 } 00338 return TRUE; 00339 } 00340 00341 00342 //----------------------------------------------------------------------------- 00343 KMFolderNode* KMFolderDir::hasNamedFolder(const TQString& aName) 00344 { 00345 KMFolderNode* fNode; 00346 for (fNode=first(); fNode; fNode=next()) { 00347 if (fNode->name() == aName) 00348 return fNode; 00349 } 00350 return 0; 00351 } 00352 00353 00354 //----------------------------------------------------------------------------- 00355 KMFolderMgr* KMFolderDir::manager() const 00356 { 00357 return parent()->manager(); 00358 } 00359 00360 00361 #include "kmfolderdir.moc" 00362