// kmfolderdir.cpp #include #include #include "kmfolderdir.h" #include "kmfoldersearch.h" #include "kmfoldercachedimap.h" #include "kmfolder.h" #include #include #include #include #include #include //============================================================================= //============================================================================= KMFolderRootDir::KMFolderRootDir(KMFolderMgr* manager, const TQString& path, KMFolderDirType dirType) : KMFolderDir( 0, 0, path, dirType ), mPath( path ), mManager( manager ) { } //----------------------------------------------------------------------------- KMFolderRootDir::~KMFolderRootDir() { // WABA: We can't let KMFolderDir do this because by the time its // desctructor gets called, KMFolderRootDir is already destructed // Most notably the path. clear(); } //----------------------------------------------------------------------------- void KMFolderRootDir::setPath(const TQString& aPath) { mPath = aPath; } //----------------------------------------------------------------------------- TQString KMFolderRootDir::path() const { return mPath; } //----------------------------------------------------------------------------- TQString KMFolderRootDir::prettyURL() const { if ( !mBaseURL.isEmpty() ) return i18n( mBaseURL.data() ); else return TQString(); } //----------------------------------------------------------------------------- void KMFolderRootDir::setBaseURL( const TQCString &baseURL ) { mBaseURL = baseURL; } //----------------------------------------------------------------------------- KMFolderMgr* KMFolderRootDir::manager() const { return mManager; } //============================================================================= //============================================================================= KMFolderDir::KMFolderDir( KMFolder * owner, KMFolderDir* parent, const TQString& name, KMFolderDirType dirType ) : KMFolderNode( parent, name ), KMFolderNodeList(), mOwner( owner ), mDirType( dirType ) { setAutoDelete( true ); } //----------------------------------------------------------------------------- KMFolderDir::~KMFolderDir() { clear(); } //----------------------------------------------------------------------------- KMFolder* KMFolderDir::createFolder(const TQString& aFolderName, bool aSysFldr, KMFolderType aFolderType) { KMFolder* fld; assert(!aFolderName.isEmpty()); // FIXME urgs, is this still needed if (mDirType == KMImapDir) fld = new KMFolder( this, aFolderName, KMFolderTypeImap ); else fld = new KMFolder( this, aFolderName, aFolderType ); assert(fld != 0); fld->setSystemFolder(aSysFldr); KMFolderNode* fNode; int index = 0; for (fNode=first(); fNode; fNode=next()) { if (fNode->name().lower() > fld->name().lower()) { insert( index, fld ); break; } ++index; } if (!fNode) append(fld); fld->correctUnreadMsgsCount(); return fld; } //---------------------------------------------------------------------------- TQString KMFolderDir::path() const { static TQString p; if (parent()) { p = parent()->path(); p.append("/"); p.append(name()); } else p = ""; return p; } //---------------------------------------------------------------------------- TQString KMFolderDir::label() const { if ( mOwner ) return mOwner->label(); else return TQString(); } //----------------------------------------------------------------------------- TQString KMFolderDir::prettyURL() const { TQString parentUrl; if ( parent() ) parentUrl = parent()->prettyURL(); if ( !parentUrl.isEmpty() ) return parentUrl + '/' + label(); else return label(); } //----------------------------------------------------------------------------- void KMFolderDir::addDirToParent( const TQString &dirName, KMFolder *parentFolder ) { KMFolderDir* folderDir = new KMFolderDir( parentFolder, this, dirName, mDirType); folderDir->reload(); append( folderDir ); parentFolder->setChild( folderDir ); } // Get the default folder type of the given dir type. This function should only be used when // needing to find out what the folder type of a missing folder is. KMFolderType dirTypeToFolderType( KMFolderDirType dirType ) { switch( dirType ) { // Use maildir for normal folder dirs, as this function is only called when finding a dir // without a parent folder, which can only happen with maildir-like folders case KMStandardDir: return KMFolderTypeMaildir; case KMImapDir: return KMFolderTypeImap; case KMDImapDir: return KMFolderTypeCachedImap; case KMSearchDir: return KMFolderTypeSearch; default: Q_ASSERT( false ); return KMFolderTypeMaildir; } } //----------------------------------------------------------------------------- bool KMFolderDir::reload(void) { TQDir dir; KMFolder* folder; TQFileInfo* fileInfo; TQStringList diList; TQPtrList folderList; clear(); const TQString fldPath = path(); dir.setFilter(TQDir::Files | TQDir::Dirs | TQDir::Hidden); dir.setNameFilter("*"); if (!dir.cd(fldPath, TRUE)) { TQString msg = i18n("Cannot enter folder %1.").arg(fldPath); KMessageBox::information(0, msg); return FALSE; } TQFileInfoList* fiList=(TQFileInfoList*)dir.entryInfoList(); if (!fiList) { TQString msg = i18n("Folder %1 is unreadable.").arg(fldPath); KMessageBox::information(0, msg); return FALSE; } for (fileInfo=fiList->first(); fileInfo; fileInfo=fiList->next()) { const TQString fname = fileInfo->fileName(); if( ( fname[0] == '.' ) && !fname.endsWith( ".directory" ) ) { // ignore all hidden files except our subfolder containers continue; } if( fname == ".directory" ) { // ignore .directory files (not created by us) continue; } // Collect subdirectories. if ( fileInfo->isDir() && fname.startsWith( "." ) && fname.endsWith( ".directory" ) ) { diList.append(fname); continue; } if ( mDirType == KMImapDir && path().startsWith( KMFolderImap::cacheLocation() ) ) { // Is the below needed for dimap as well? if ( KMFolderImap::encodeFileName( KMFolderImap::decodeFileName( fname ) ) == fname ) { folder = new KMFolder( this, KMFolderImap::decodeFileName( fname ), KMFolderTypeImap ); append(folder); folderList.append(folder); } } else if ( mDirType == KMDImapDir && path().startsWith( KMFolderCachedImap::cacheLocation() ) ) { if (fileInfo->isDir()) // a directory { // For this to be a cached IMAP folder, it must be in the KMail dimap // subdir and must be have a uidcache file or be a maildir folder TQString maildir(fname + "/new"); TQString imapcachefile = TQString::fromLatin1(".%1.uidcache").arg(fname); if ( dir.exists( imapcachefile) || dir.exists( maildir ) ) { folder = new KMFolder( this, fname, KMFolderTypeCachedImap ); append(folder); folderList.append(folder); } } } else if ( mDirType == KMSearchDir) { folder = new KMFolder( this, fname, KMFolderTypeSearch ); append(folder); folderList.append(folder); } else if ( mDirType == KMStandardDir ) { // This is neither an imap, dimap nor a search folder. Can be either // mbox or maildir. if (fileInfo->isDir()) { // Maildir folder if( dir.exists( fname + "/new" ) ) { folder = new KMFolder( this, fname, KMFolderTypeMaildir ); append(folder); folderList.append(folder); } } else { // all other files are folders (at the moment ;-) folder = new KMFolder( this, fname, KMFolderTypeMbox ); append(folder); folderList.append(folder); } } } TQStringList dirsWithoutFolder = diList; for (folder=folderList.first(); folder; folder=folderList.next()) { for(TQStringList::Iterator it = diList.begin(); it != diList.end(); ++it) if (*it == "." + folder->fileName() + ".directory") { dirsWithoutFolder.remove( *it ); addDirToParent( *it, folder ); break; } } // Check if the are any dirs without an associated folder. This can happen if the user messes // with the on-disk folder structure, see kolab issue 2972. In that case, we don't want to loose // the subfolders as well, so we recreate the folder so the folder/dir hierachy is OK again. if ( type() == KMDImapDir ) { for ( TQStringList::Iterator it = dirsWithoutFolder.begin(); it != dirsWithoutFolder.end(); ++it ) { // .foo.directory => foo TQString folderName = *it; int right = folderName.find( ".directory" ); int left = folderName.find( "." ); Q_ASSERT( left != -1 && right != -1 ); folderName = folderName.mid( left + 1, right - 1 ); kdDebug(5006) << "Found dir without associated folder: " << ( *it ) << ", recreating the folder " << folderName << "." << endl; // Recreate the missing folder KMFolder *folder = new KMFolder( this, folderName, KMFolderTypeCachedImap ); append( folder ); folderList.append( folder ); addDirToParent( *it, folder ); } } return TRUE; } //----------------------------------------------------------------------------- KMFolderNode* KMFolderDir::hasNamedFolder(const TQString& aName) { KMFolderNode* fNode; for (fNode=first(); fNode; fNode=next()) { if (fNode->name() == aName) return fNode; } return 0; } //----------------------------------------------------------------------------- KMFolderMgr* KMFolderDir::manager() const { return parent()->manager(); } #include "kmfolderdir.moc"