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