]> git.saurik.com Git - wxWidgets.git/blame - src/common/dircmn.cpp
Implement incremental search in wxGenericListCtrl.
[wxWidgets.git] / src / common / dircmn.cpp
CommitLineData
35332784
VZ
1///////////////////////////////////////////////////////////////////////////////
2// Name: src/common/dircmn.cpp
3// Purpose: wxDir methods common to all implementations
4// Author: Vadim Zeitlin
5// Modified by:
6// Created: 19.05.01
7// RCS-ID: $Id$
8// Copyright: (c) 2001 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
526954c5 9// Licence: wxWindows licence
35332784
VZ
10///////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
35332784
VZ
20// For compilers that support precompilation, includes "wx.h".
21#include "wx/wxprec.h"
22
23#ifdef __BORLANDC__
24 #pragma hdrstop
25#endif
26
27#ifndef WX_PRECOMP
28 #include "wx/string.h"
29 #include "wx/log.h"
30 #include "wx/intl.h"
bdfeadca 31 #include "wx/filefn.h"
aaa6d89a 32 #include "wx/arrstr.h"
35332784
VZ
33#endif //WX_PRECOMP
34
35#include "wx/dir.h"
23b8a262 36#include "wx/filename.h"
35332784
VZ
37
38// ============================================================================
39// implementation
40// ============================================================================
41
350777b6
VZ
42// ----------------------------------------------------------------------------
43// wxDirTraverser
44// ----------------------------------------------------------------------------
45
46wxDirTraverseResult
47wxDirTraverser::OnOpenError(const wxString& WXUNUSED(dirname))
48{
49 return wxDIR_IGNORE;
50}
51
35332784 52// ----------------------------------------------------------------------------
1357a7dd
VZ
53// wxDir::HasFiles() and HasSubDirs()
54// ----------------------------------------------------------------------------
55
56// dumb generic implementation
57
106dcc2c 58bool wxDir::HasFiles(const wxString& spec) const
1357a7dd
VZ
59{
60 wxString s;
61 return GetFirst(&s, spec, wxDIR_FILES | wxDIR_HIDDEN);
62}
63
64// we have a (much) faster version for Unix
420b39aa 65#if (defined(__CYGWIN__) && defined(__WINDOWS__)) || !defined(__UNIX_LIKE__) || defined(__EMX__) || defined(__WINE__)
1357a7dd 66
106dcc2c 67bool wxDir::HasSubDirs(const wxString& spec) const
1357a7dd
VZ
68{
69 wxString s;
70 return GetFirst(&s, spec, wxDIR_DIRS | wxDIR_HIDDEN);
71}
72
73#endif // !Unix
74
c9f6f0a8
VZ
75// ----------------------------------------------------------------------------
76// wxDir::GetNameWithSep()
77// ----------------------------------------------------------------------------
78
79wxString wxDir::GetNameWithSep() const
80{
81 // Note that for historical reasons (i.e. because GetName() was there
82 // first) we implement this one in terms of GetName() even though it might
83 // actually make more sense to reverse this logic.
84
85 wxString name = GetName();
86 if ( !name.empty() )
87 {
88 // Notice that even though GetName() isn't supposed to return the
89 // separator, it can still be present for the root directory name.
90 if ( name.Last() != wxFILE_SEP_PATH )
91 name += wxFILE_SEP_PATH;
92 }
93
94 return name;
95}
96
1357a7dd 97// ----------------------------------------------------------------------------
35332784
VZ
98// wxDir::Traverse()
99// ----------------------------------------------------------------------------
100
101size_t wxDir::Traverse(wxDirTraverser& sink,
102 const wxString& filespec,
103 int flags) const
104{
105 wxCHECK_MSG( IsOpened(), (size_t)-1,
9a83f860 106 wxT("dir must be opened before traversing it") );
35332784
VZ
107
108 // the total number of files found
109 size_t nFiles = 0;
110
111 // the name of this dir with path delimiter at the end
c9f6f0a8 112 const wxString prefix = GetNameWithSep();
35332784
VZ
113
114 // first, recurse into subdirs
115 if ( flags & wxDIR_DIRS )
116 {
117 wxString dirname;
b494c48b 118 for ( bool cont = GetFirst(&dirname, wxEmptyString, wxDIR_DIRS | (flags & wxDIR_HIDDEN) );
350777b6 119 cont;
51485b76 120 cont = cont && GetNext(&dirname) )
35332784 121 {
350777b6 122 const wxString fulldirname = prefix + dirname;
35332784 123
350777b6 124 switch ( sink.OnDir(fulldirname) )
35332784 125 {
350777b6 126 default:
9a83f860 127 wxFAIL_MSG(wxT("unexpected OnDir() return value") );
350777b6
VZ
128 // fall through
129
130 case wxDIR_STOP:
131 cont = false;
132 break;
133
134 case wxDIR_CONTINUE:
135 {
136 wxDir subdir;
137
138 // don't give the error messages for the directories
139 // which we can't open: there can be all sorts of good
140 // reason for this (e.g. insufficient privileges) and
141 // this shouldn't be treated as an error -- instead
142 // let the user code decide what to do
143 bool ok;
144 do
145 {
146 wxLogNull noLog;
147 ok = subdir.Open(fulldirname);
148 if ( !ok )
149 {
150 // ask the user code what to do
151 bool tryagain;
152 switch ( sink.OnOpenError(fulldirname) )
153 {
154 default:
9a83f860 155 wxFAIL_MSG(wxT("unexpected OnOpenError() return value") );
350777b6
VZ
156 // fall through
157
158 case wxDIR_STOP:
159 cont = false;
160 // fall through
161
162 case wxDIR_IGNORE:
163 tryagain = false;
164 break;
165
166 case wxDIR_CONTINUE:
167 tryagain = true;
168 }
169
170 if ( !tryagain )
171 break;
172 }
173 }
174 while ( !ok );
175
176 if ( ok )
177 {
178 nFiles += subdir.Traverse(sink, filespec, flags);
179 }
180 }
181 break;
182
183 case wxDIR_IGNORE:
184 // nothing to do
185 ;
35332784 186 }
35332784
VZ
187 }
188 }
189
190 // now enum our own files
191 if ( flags & wxDIR_FILES )
192 {
193 flags &= ~wxDIR_DIRS;
194
195 wxString filename;
196 bool cont = GetFirst(&filename, filespec, flags);
197 while ( cont )
198 {
199 wxDirTraverseResult res = sink.OnFile(prefix + filename);
200 if ( res == wxDIR_STOP )
201 break;
202
203 wxASSERT_MSG( res == wxDIR_CONTINUE,
9a83f860 204 wxT("unexpected OnFile() return value") );
35332784
VZ
205
206 nFiles++;
207
208 cont = GetNext(&filename);
209 }
210 }
211
212 return nFiles;
213}
214
215// ----------------------------------------------------------------------------
216// wxDir::GetAllFiles()
217// ----------------------------------------------------------------------------
218
219class wxDirTraverserSimple : public wxDirTraverser
220{
221public:
222 wxDirTraverserSimple(wxArrayString& files) : m_files(files) { }
223
224 virtual wxDirTraverseResult OnFile(const wxString& filename)
225 {
df5168c4 226 m_files.push_back(filename);
35332784
VZ
227 return wxDIR_CONTINUE;
228 }
229
230 virtual wxDirTraverseResult OnDir(const wxString& WXUNUSED(dirname))
231 {
232 return wxDIR_CONTINUE;
233 }
234
235private:
236 wxArrayString& m_files;
fc7a2a60 237
c0c133e1 238 wxDECLARE_NO_COPY_CLASS(wxDirTraverserSimple);
35332784
VZ
239};
240
241/* static */
242size_t wxDir::GetAllFiles(const wxString& dirname,
243 wxArrayString *files,
244 const wxString& filespec,
245 int flags)
246{
9a83f860 247 wxCHECK_MSG( files, (size_t)-1, wxT("NULL pointer in wxDir::GetAllFiles") );
35332784
VZ
248
249 size_t nFiles = 0;
250
251 wxDir dir(dirname);
252 if ( dir.IsOpened() )
253 {
254 wxDirTraverserSimple traverser(*files);
255
256 nFiles += dir.Traverse(traverser, filespec, flags);
257 }
258
259 return nFiles;
260}
d1af8e2d
VZ
261
262// ----------------------------------------------------------------------------
263// wxDir::FindFirst()
264// ----------------------------------------------------------------------------
265
266class wxDirTraverserFindFirst : public wxDirTraverser
267{
268public:
269 wxDirTraverserFindFirst() { }
270
271 virtual wxDirTraverseResult OnFile(const wxString& filename)
272 {
273 m_file = filename;
274 return wxDIR_STOP;
275 }
276
277 virtual wxDirTraverseResult OnDir(const wxString& WXUNUSED(dirname))
278 {
279 return wxDIR_CONTINUE;
280 }
281
282 const wxString& GetFile() const
283 {
284 return m_file;
285 }
286
287private:
288 wxString m_file;
289
c0c133e1 290 wxDECLARE_NO_COPY_CLASS(wxDirTraverserFindFirst);
d1af8e2d
VZ
291};
292
293/* static */
294wxString wxDir::FindFirst(const wxString& dirname,
295 const wxString& filespec,
296 int flags)
297{
298 wxDir dir(dirname);
299 if ( dir.IsOpened() )
300 {
301 wxDirTraverserFindFirst traverser;
302
303 dir.Traverse(traverser, filespec, flags | wxDIR_FILES);
304 return traverser.GetFile();
305 }
306
307 return wxEmptyString;
308}
23b8a262
JS
309
310
311// ----------------------------------------------------------------------------
312// wxDir::GetTotalSize()
313// ----------------------------------------------------------------------------
314
bd08f2f7
VZ
315#if wxUSE_LONGLONG
316
23b8a262
JS
317class wxDirTraverserSumSize : public wxDirTraverser
318{
319public:
a8df8389 320 wxDirTraverserSumSize() { }
23b8a262
JS
321
322 virtual wxDirTraverseResult OnFile(const wxString& filename)
323 {
23b8a262
JS
324 // wxFileName::GetSize won't use this class again as
325 // we're passing it a file and not a directory;
326 // thus we are sure to avoid an endless loop
191d6608
VZ
327 wxULongLong sz = wxFileName::GetSize(filename);
328
23b8a262
JS
329 if (sz == wxInvalidSize)
330 {
331 // if the GetSize() failed (this can happen because e.g. a
332 // file is locked by another process), we can proceed but
333 // we need to at least warn the user that the resulting
334 // final size could be not reliable (if e.g. the locked
335 // file is very big).
336 m_skippedFiles.Add(filename);
337 return wxDIR_CONTINUE;
338 }
339
340 m_sz += sz;
341 return wxDIR_CONTINUE;
342 }
343
344 virtual wxDirTraverseResult OnDir(const wxString& WXUNUSED(dirname))
345 {
346 return wxDIR_CONTINUE;
347 }
348
349 wxULongLong GetTotalSize() const
350 { return m_sz; }
191d6608 351 const wxArrayString& GetSkippedFiles() const
23b8a262
JS
352 { return m_skippedFiles; }
353
354protected:
355 wxULongLong m_sz;
356 wxArrayString m_skippedFiles;
357};
358
359wxULongLong wxDir::GetTotalSize(const wxString &dirname, wxArrayString *filesSkipped)
360{
361 if (!wxDirExists(dirname))
362 return wxInvalidSize;
363
364 // to get the size of this directory and its contents we need
365 // to recursively walk it...
366 wxDir dir(dirname);
367 if ( !dir.IsOpened() )
368 return wxInvalidSize;
369
370 wxDirTraverserSumSize traverser;
852febd8 371 if (dir.Traverse(traverser) == (size_t)-1 )
23b8a262
JS
372 return wxInvalidSize;
373
374 if (filesSkipped)
191d6608 375 *filesSkipped = traverser.GetSkippedFiles();
23b8a262
JS
376
377 return traverser.GetTotalSize();
378}
379
f422aafe
VZ
380#endif // wxUSE_LONGLONG
381
d38315df
FM
382// ----------------------------------------------------------------------------
383// wxDir helpers
384// ----------------------------------------------------------------------------
385
386/* static */
387bool wxDir::Exists(const wxString& dir)
388{
389 return wxFileName::DirExists(dir);
390}
391
392/* static */
393bool wxDir::Make(const wxString &dir, int perm, int flags)
394{
395 return wxFileName::Mkdir(dir, perm, flags);
396}
397
398/* static */
399bool wxDir::Remove(const wxString &dir, int flags)
400{
401 return wxFileName::Rmdir(dir, flags);
402}
ce00f59b 403