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 
TQString fileName() const
Returns the filename of the folder (reimplemented in KMFolderImap)
Definition: kmfolder.cpp:238
KMail list that manages the contents of one directory that may contain folders and/or other directori...
Definition: kmfolderdir.h:15
virtual TQString label() const
Returns the label of the folder for visualization.
Definition: kmfolder.cpp:581
virtual KMFolderNode * hasNamedFolder(const TQString &name)
Returns folder with given name or zero if it does not exist.
void correctUnreadMsgsCount()
A cludge to help make sure the count of unread messges is kept in sync.
Definition: kmfolder.cpp:700
virtual bool reload()
Read contents of directory.
virtual KMFolderMgr * manager() const
Returns the folder manager that manages this folder.
void setChild(KMFolderDir *aChild)
Set the folder directory associated with this node.
Definition: kmfolder.cpp:295
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
void addDirToParent(const TQString &dirName, KMFolder *parentFolder)
Adds the given subdirectory of this directory to the associated folder.
virtual TQString path() const
Return full pathname of this directory.
Mail folder.
Definition: kmfolder.h:68
TQString label() const
Returns the label of the folder for visualization.
virtual TQString prettyURL() const
URL of the node for visualization purposes.