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 <kstandarddirs.h>
17 
18 
19 //=============================================================================
20 //=============================================================================
21 KMFolderRootDir::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 //-----------------------------------------------------------------------------
30 KMFolderRootDir::~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 //-----------------------------------------------------------------------------
39 void KMFolderRootDir::setPath(const TQString& aPath)
40 {
41  mPath = aPath;
42 }
43 
44 
45 //-----------------------------------------------------------------------------
46 TQString KMFolderRootDir::path() const
47 {
48  return mPath;
49 }
50 
51 
52 //-----------------------------------------------------------------------------
53 TQString KMFolderRootDir::prettyURL() const
54 {
55  if ( !mBaseURL.isEmpty() )
56  return i18n( mBaseURL.data() );
57  else
58  return TQString();
59 }
60 
61 
62 //-----------------------------------------------------------------------------
63 void KMFolderRootDir::setBaseURL( const TQCString &baseURL )
64 {
65  mBaseURL = baseURL;
66 }
67 
68 
69 //-----------------------------------------------------------------------------
70 KMFolderMgr* KMFolderRootDir::manager() const
71 {
72  return mManager;
73 }
74 
75 
76 //=============================================================================
77 //=============================================================================
78 KMFolderDir::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 //-----------------------------------------------------------------------------
88 KMFolderDir::~KMFolderDir()
89 {
90  clear();
91 }
92 
93 
94 //-----------------------------------------------------------------------------
95 KMFolder* 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 
122  fld->correctUnreadMsgsCount();
123  return fld;
124 }
125 
126 
127 //----------------------------------------------------------------------------
128 TQString 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 //----------------------------------------------------------------------------
145 TQString KMFolderDir::label() const
146 {
147  if ( mOwner )
148  return mOwner->label();
149  else
150  return TQString();
151 }
152 
153 
154 //-----------------------------------------------------------------------------
155 TQString KMFolderDir::prettyURL() const
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 //-----------------------------------------------------------------------------
167 void 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.
177 KMFolderType 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 //-----------------------------------------------------------------------------
343 KMFolderNode* 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 //-----------------------------------------------------------------------------
355 KMFolderMgr* 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