kmail

kmfolderdir.cpp
1// kmfolderdir.cpp
2
3#include <config.h>
4#include <tqdir.h>
5
6#include "kmfolderdir.h"
7#include "kmfoldersearch.h"
8#include "kmfoldercachedimap.h"
9#include "kmfolder.h"
10
11#include <assert.h>
12#include <errno.h>
13#include <tdelocale.h>
14#include <tdemessagebox.h>
15#include <kdebug.h>
16#include <tdestandarddirs.h>
17
18
19//=============================================================================
20//=============================================================================
21KMFolderRootDir::KMFolderRootDir(KMFolderMgr* manager, const TQString& path,
22 KMFolderDirType dirType)
23 : KMFolderDir( 0, 0, path, dirType ),
24 mPath( path ),
25 mManager( manager )
26{
27}
28
29//-----------------------------------------------------------------------------
30KMFolderRootDir::~KMFolderRootDir()
31{
32 // WABA: We can't let KMFolderDir do this because by the time its
33 // desctructor gets called, KMFolderRootDir is already destructed
34 // Most notably the path.
35 clear();
36}
37
38//-----------------------------------------------------------------------------
39void KMFolderRootDir::setPath(const TQString& aPath)
40{
41 mPath = aPath;
42}
43
44
45//-----------------------------------------------------------------------------
46TQString KMFolderRootDir::path() const
47{
48 return mPath;
49}
50
51
52//-----------------------------------------------------------------------------
53TQString KMFolderRootDir::prettyURL() const
54{
55 if ( !mBaseURL.isEmpty() )
56 return i18n( mBaseURL.data() );
57 else
58 return TQString();
59}
60
61
62//-----------------------------------------------------------------------------
63void KMFolderRootDir::setBaseURL( const TQCString &baseURL )
64{
65 mBaseURL = baseURL;
66}
67
68
69//-----------------------------------------------------------------------------
70KMFolderMgr* KMFolderRootDir::manager() const
71{
72 return mManager;
73}
74
75
76//=============================================================================
77//=============================================================================
78KMFolderDir::KMFolderDir( KMFolder * owner, KMFolderDir* parent,
79 const TQString& name, KMFolderDirType dirType )
80 : KMFolderNode( parent, name ), KMFolderNodeList(),
81 mOwner( owner ), mDirType( dirType )
82{
83 setAutoDelete( true );
84}
85
86
87//-----------------------------------------------------------------------------
88KMFolderDir::~KMFolderDir()
89{
90 clear();
91}
92
93
94//-----------------------------------------------------------------------------
95KMFolder* KMFolderDir::createFolder(const TQString& aFolderName, bool aSysFldr, KMFolderType aFolderType)
96{
97 KMFolder* fld;
98
99 assert(!aFolderName.isEmpty());
100 // FIXME urgs, is this still needed
101 if (mDirType == KMImapDir)
102 fld = new KMFolder( this, aFolderName, KMFolderTypeImap );
103 else
104 fld = new KMFolder( this, aFolderName, aFolderType );
105
106 assert(fld != 0);
107 fld->setSystemFolder(aSysFldr);
108
109 KMFolderNode* fNode;
110 int index = 0;
111 for (fNode=first(); fNode; fNode=next()) {
112 if (fNode->name().lower() > fld->name().lower()) {
113 insert( index, fld );
114 break;
115 }
116 ++index;
117 }
118
119 if (!fNode)
120 append(fld);
121
123 return fld;
124}
125
126
127//----------------------------------------------------------------------------
128TQString KMFolderDir::path() const
129{
130 static TQString p;
131
132 if (parent())
133 {
134 p = parent()->path();
135 p.append("/");
136 p.append(name());
137 }
138 else p = "";
139
140 return p;
141}
142
143
144//----------------------------------------------------------------------------
145TQString KMFolderDir::label() const
146{
147 if ( mOwner )
148 return mOwner->label();
149 else
150 return TQString();
151}
152
153
154//-----------------------------------------------------------------------------
156{
157 TQString parentUrl;
158 if ( parent() )
159 parentUrl = parent()->prettyURL();
160 if ( !parentUrl.isEmpty() )
161 return parentUrl + '/' + label();
162 else
163 return label();
164}
165
166//-----------------------------------------------------------------------------
167void KMFolderDir::addDirToParent( const TQString &dirName, KMFolder *parentFolder )
168{
169 KMFolderDir* folderDir = new KMFolderDir( parentFolder, this, dirName, mDirType);
170 folderDir->reload();
171 append( folderDir );
172 parentFolder->setChild( folderDir );
173}
174
175// Get the default folder type of the given dir type. This function should only be used when
176// needing to find out what the folder type of a missing folder is.
177KMFolderType dirTypeToFolderType( KMFolderDirType dirType )
178{
179 switch( dirType ) {
180
181 // Use maildir for normal folder dirs, as this function is only called when finding a dir
182 // without a parent folder, which can only happen with maildir-like folders
183 case KMStandardDir: return KMFolderTypeMaildir;
184
185 case KMImapDir: return KMFolderTypeImap;
186 case KMDImapDir: return KMFolderTypeCachedImap;
187 case KMSearchDir: return KMFolderTypeSearch;
188 default: Q_ASSERT( false ); return KMFolderTypeMaildir;
189 }
190}
191
192//-----------------------------------------------------------------------------
194{
195 TQDir dir;
196 KMFolder* folder;
197 TQFileInfo* fileInfo;
198 TQStringList diList;
199 TQPtrList<KMFolder> folderList;
200
201 clear();
202
203 const TQString fldPath = path();
204 dir.setFilter(TQDir::Files | TQDir::Dirs | TQDir::Hidden);
205 dir.setNameFilter("*");
206
207 if (!dir.cd(fldPath, TRUE))
208 {
209 TQString msg = i18n("<qt>Cannot enter folder <b>%1</b>.</qt>").arg(fldPath);
210 KMessageBox::information(0, msg);
211 return FALSE;
212 }
213
214 TQFileInfoList* fiList=(TQFileInfoList*)dir.entryInfoList();
215 if (!fiList)
216 {
217 TQString msg = i18n("<qt>Folder <b>%1</b> is unreadable.</qt>").arg(fldPath);
218 KMessageBox::information(0, msg);
219 return FALSE;
220 }
221
222 for (fileInfo=fiList->first(); fileInfo; fileInfo=fiList->next())
223 {
224 const TQString fname = fileInfo->fileName();
225 if( ( fname[0] == '.' ) && !fname.endsWith( ".directory" ) ) {
226 // ignore all hidden files except our subfolder containers
227 continue;
228 }
229 if( fname == ".directory" ) {
230 // ignore .directory files (not created by us)
231 continue;
232 }
233 // Collect subdirectories.
234 if ( fileInfo->isDir() &&
235 fname.startsWith( "." ) && fname.endsWith( ".directory" ) ) {
236 diList.append(fname);
237 continue;
238 }
239
240 if ( mDirType == KMImapDir
241 && path().startsWith( KMFolderImap::cacheLocation() ) )
242 {
243 // Is the below needed for dimap as well?
244 if ( KMFolderImap::encodeFileName(
245 KMFolderImap::decodeFileName( fname ) ) == fname )
246 {
247 folder = new KMFolder( this, KMFolderImap::decodeFileName( fname ),
248 KMFolderTypeImap );
249 append(folder);
250 folderList.append(folder);
251 }
252 }
253 else if ( mDirType == KMDImapDir
254 && path().startsWith( KMFolderCachedImap::cacheLocation() ) )
255 {
256 if (fileInfo->isDir()) // a directory
257 {
258 // For this to be a cached IMAP folder, it must be in the KMail dimap
259 // subdir and must be have a uidcache file or be a maildir folder
260 TQString maildir(fname + "/new");
261 TQString imapcachefile = TQString::fromLatin1(".%1.uidcache").arg(fname);
262 if ( dir.exists( imapcachefile) || dir.exists( maildir ) )
263 {
264 folder = new KMFolder( this, fname, KMFolderTypeCachedImap );
265 append(folder);
266 folderList.append(folder);
267 }
268 }
269 }
270 else if ( mDirType == KMSearchDir)
271 {
272 folder = new KMFolder( this, fname, KMFolderTypeSearch );
273 append(folder);
274 folderList.append(folder);
275 }
276 else if ( mDirType == KMStandardDir )
277 {
278 // This is neither an imap, dimap nor a search folder. Can be either
279 // mbox or maildir.
280 if (fileInfo->isDir())
281 {
282 // Maildir folder
283 if( dir.exists( fname + "/new" ) )
284 {
285 folder = new KMFolder( this, fname, KMFolderTypeMaildir );
286 append(folder);
287 folderList.append(folder);
288 }
289 }
290 else
291 {
292 // all other files are folders (at the moment ;-)
293 folder = new KMFolder( this, fname, KMFolderTypeMbox );
294 append(folder);
295 folderList.append(folder);
296 }
297 }
298 }
299
300 TQStringList dirsWithoutFolder = diList;
301 for (folder=folderList.first(); folder; folder=folderList.next())
302 {
303 for(TQStringList::Iterator it = diList.begin();
304 it != diList.end();
305 ++it)
306 if (*it == "." + folder->fileName() + ".directory")
307 {
308 dirsWithoutFolder.remove( *it );
309 addDirToParent( *it, folder );
310 break;
311 }
312 }
313
314 // Check if the are any dirs without an associated folder. This can happen if the user messes
315 // with the on-disk folder structure, see kolab issue 2972. In that case, we don't want to loose
316 // the subfolders as well, so we recreate the folder so the folder/dir hierachy is OK again.
317 if ( type() == KMDImapDir ) {
318 for ( TQStringList::Iterator it = dirsWithoutFolder.begin();
319 it != dirsWithoutFolder.end(); ++it ) {
320
321 // .foo.directory => foo
322 TQString folderName = *it;
323 int right = folderName.find( ".directory" );
324 int left = folderName.find( "." );
325 Q_ASSERT( left != -1 && right != -1 );
326 folderName = folderName.mid( left + 1, right - 1 );
327
328 kdDebug(5006) << "Found dir without associated folder: " << ( *it ) << ", recreating the folder " << folderName << "." << endl;
329
330 // Recreate the missing folder
331 KMFolder *folder = new KMFolder( this, folderName, KMFolderTypeCachedImap );
332 append( folder );
333 folderList.append( folder );
334
335 addDirToParent( *it, folder );
336 }
337 }
338 return TRUE;
339}
340
341
342//-----------------------------------------------------------------------------
343KMFolderNode* KMFolderDir::hasNamedFolder(const TQString& aName)
344{
345 KMFolderNode* fNode;
346 for (fNode=first(); fNode; fNode=next()) {
347 if (fNode->name() == aName)
348 return fNode;
349 }
350 return 0;
351}
352
353
354//-----------------------------------------------------------------------------
355KMFolderMgr* KMFolderDir::manager() const
356{
357 return parent()->manager();
358}
359
360
361#include "kmfolderdir.moc"
362
KMail list that manages the contents of one directory that may contain folders and/or other directori...
Definition: kmfolderdir.h:16
virtual KMFolder * createFolder(const TQString &folderName, bool sysFldr=false, KMFolderType folderType=KMFolderTypeMbox)
Create a mail folder in this directory with given name.
Definition: kmfolderdir.cpp:95
virtual TQString path() const
Return full pathname of this directory.
void addDirToParent(const TQString &dirName, KMFolder *parentFolder)
Adds the given subdirectory of this directory to the associated folder.
virtual bool reload()
Read contents of directory.
virtual TQString prettyURL() const
URL of the node for visualization purposes.
virtual KMFolderNode * hasNamedFolder(const TQString &name)
Returns folder with given name or zero if it does not exist.
TQString label() const
Returns the label of the folder for visualization.
virtual KMFolderMgr * manager() const
Returns the folder manager that manages this folder.
Mail folder.
Definition: kmfolder.h:69
void correctUnreadMsgsCount()
A cludge to help make sure the count of unread messges is kept in sync.
Definition: kmfolder.cpp:700
virtual TQString label() const
Returns the label of the folder for visualization.
Definition: kmfolder.cpp:581
TQString fileName() const
Returns the filename of the folder (reimplemented in KMFolderImap)
Definition: kmfolder.cpp:238
void setChild(KMFolderDir *aChild)
Set the folder directory associated with this node.
Definition: kmfolder.cpp:295