]>
Commit | Line | Data |
---|---|---|
c801d85f KB |
1 | /* |
2 | * Author: Robert Roebling | |
3 | * | |
4 | * Copyright: (C) 1997,1998 Robert Roebling | |
5 | * | |
6 | * This library is free software; you can redistribute it and/or | |
7 | * modify it under the terms of the wxWindows Licence, which | |
8 | * you have received with this library (see Licence.htm). | |
9 | * | |
10 | */ | |
11 | ||
12 | ||
13 | #ifdef __GNUG__ | |
14 | #pragma implementation "filectrl.h" | |
15 | #endif | |
16 | ||
17 | #include "filectrl.h" | |
18 | ||
19 | #include "wx/dnd.h" | |
20 | ||
21 | #include "sys/types.h" | |
22 | #include "sys/stat.h" | |
23 | #include "dirent.h" | |
24 | #include "pwd.h" | |
25 | #include "grp.h" | |
26 | #include "time.h" | |
27 | ||
28 | #include "folder.xpm" | |
29 | #include "txt.xpm" | |
30 | #include "list.xpm" | |
31 | #include "find.xpm" | |
32 | ||
33 | //----------------------------------------------------------------------------- | |
34 | // wxFileData | |
35 | //----------------------------------------------------------------------------- | |
36 | ||
37 | IMPLEMENT_DYNAMIC_CLASS(wxFileData,wxObject); | |
38 | ||
39 | wxFileData::wxFileData( const wxString &name, const wxString &fname ) | |
40 | { | |
41 | m_name = name; | |
42 | m_fileName = fname; | |
43 | ||
44 | struct stat buff; | |
45 | stat( m_fileName.GetData(), &buff ); | |
46 | struct stat lbuff; | |
47 | lstat( m_fileName.GetData(), &lbuff ); | |
48 | ||
49 | struct tm *t = localtime( &lbuff.st_mtime ); | |
50 | // struct passwd *user = getpwuid( buff.st_uid ); | |
51 | // struct group *grp = getgrgid( buff.st_gid ); | |
52 | ||
53 | m_isDir = S_ISDIR( buff.st_mode ); | |
54 | m_isLink = S_ISLNK( lbuff.st_mode ); | |
55 | m_isExe = ((buff.st_mode & S_IXUSR ) == S_IXUSR ); | |
56 | ||
57 | m_size = buff.st_size; | |
58 | ||
59 | m_hour = t->tm_hour; | |
60 | m_minute = t->tm_min; | |
61 | m_month = t->tm_mon+1; | |
62 | m_day = t->tm_mday; | |
63 | m_year = t->tm_year; | |
64 | ||
65 | m_permissions.sprintf( "%c%c%c", | |
66 | ((( buff.st_mode & S_IRUSR ) == S_IRUSR ) ? 'r' : '-'), | |
67 | ((( buff.st_mode & S_IWUSR ) == S_IWUSR ) ? 'w' : '-'), | |
68 | ((( buff.st_mode & S_IXUSR ) == S_IXUSR ) ? 'x' : '-') ); | |
69 | }; | |
70 | ||
71 | wxString wxFileData::GetName(void) const | |
72 | { | |
73 | return m_name; | |
74 | }; | |
75 | ||
76 | wxString wxFileData::GetFullName(void) const | |
77 | { | |
78 | return m_fileName; | |
79 | }; | |
80 | ||
81 | wxString wxFileData::GetHint(void) const | |
82 | { | |
83 | wxString s = m_fileName; | |
84 | s += " "; | |
85 | if (m_isDir) s += "<DIR> "; | |
86 | else if (m_isLink) s += "<LINK> "; | |
87 | else | |
88 | { | |
89 | s += LongToString( m_size ); | |
90 | s += " bytes "; | |
91 | }; | |
92 | s += IntToString( m_day ); | |
93 | s += "."; | |
94 | s += IntToString( m_month ); | |
95 | s += "."; | |
96 | s += IntToString( m_year ); | |
97 | s += " "; | |
98 | s += IntToString( m_hour ); | |
99 | s += ":"; | |
100 | s += IntToString( m_minute ); | |
101 | s += " "; | |
102 | s += m_permissions; | |
103 | return s; | |
104 | }; | |
105 | ||
106 | wxString wxFileData::GetEntry( const int num ) | |
107 | { | |
108 | wxString s; | |
109 | switch (num) | |
110 | { | |
111 | case 0: | |
112 | s = m_name; | |
113 | break; | |
114 | case 1: | |
115 | if (m_isDir) s = "<DIR>"; | |
116 | else if (m_isLink) s = "<LINK>"; | |
117 | else s = LongToString( m_size ); | |
118 | break; | |
119 | case 2: | |
120 | if (m_day < 10) s = "0"; else s = ""; | |
121 | s += IntToString( m_day ); | |
122 | s += "."; | |
123 | if (m_month < 10) s += "0"; | |
124 | s += IntToString( m_month ); | |
125 | s += "."; | |
126 | if (m_year < 10) s += "0"; // this should happen real soon... | |
127 | s += IntToString( m_year ); | |
128 | break; | |
129 | case 3: | |
130 | if (m_hour < 10) s = "0"; else s = ""; | |
131 | s += IntToString( m_hour ); | |
132 | s += ":"; | |
133 | if (m_minute < 10) s += "0"; | |
134 | s += IntToString( m_minute ); | |
135 | break; | |
136 | case 4: | |
137 | s = m_permissions; | |
138 | break; | |
139 | default: | |
140 | s = "No entry"; | |
141 | break; | |
142 | }; | |
143 | return s; | |
144 | }; | |
145 | ||
146 | bool wxFileData::IsDir( void ) | |
147 | { | |
148 | return m_isDir; | |
149 | }; | |
150 | ||
151 | bool wxFileData::IsExe( void ) | |
152 | { | |
153 | return m_isExe; | |
154 | }; | |
155 | ||
156 | bool wxFileData::IsLink( void ) | |
157 | { | |
158 | return m_isLink; | |
159 | }; | |
160 | ||
161 | long wxFileData::GetSize( void ) | |
162 | { | |
163 | return m_size; | |
164 | }; | |
165 | ||
166 | bool wxFileData::NewNameIsLegal( const wxString &s ) | |
167 | { | |
168 | wxString fileName = wxPathOnly( m_fileName ); | |
169 | fileName += "/"; | |
170 | fileName += s; | |
171 | return (!wxFileExists( fileName )); | |
172 | }; | |
173 | ||
174 | bool wxFileData::Rename( const wxString &s ) | |
175 | { | |
176 | wxString fileName = wxPathOnly( m_fileName ); | |
177 | fileName += "/"; | |
178 | fileName += s; | |
179 | bool ret = wxRenameFile( m_fileName, fileName ); | |
180 | if (ret) | |
181 | { | |
182 | m_fileName = fileName; | |
183 | m_name = s; | |
184 | }; | |
185 | return ret; | |
186 | }; | |
187 | ||
188 | void wxFileData::MakeItem( wxListItem &item ) | |
189 | { | |
190 | item.m_text = m_name; | |
191 | item.m_colour = wxBLACK; | |
192 | if (IsExe()) item.m_colour = wxRED; | |
193 | if (IsDir()) item.m_colour = wxBLUE; | |
194 | if (IsLink()) | |
195 | { | |
196 | wxColour *dg = wxTheColourDatabase->FindColour( "MEDIUM GREY" ); | |
197 | item.m_colour = dg; | |
198 | }; | |
199 | item.m_data = (long)this; | |
200 | }; | |
201 | ||
202 | //----------------------------------------------------------------------------- | |
203 | // wxFileCtrl | |
204 | //----------------------------------------------------------------------------- | |
205 | ||
206 | IMPLEMENT_DYNAMIC_CLASS(wxFileCtrl,wxListCtrl); | |
207 | ||
208 | BEGIN_EVENT_TABLE(wxFileCtrl,wxListCtrl) | |
209 | EVT_SET_FOCUS (wxFileCtrl::OnSetFocus) | |
210 | END_EVENT_TABLE() | |
211 | ||
212 | wxFileCtrl *wxFileCtrl::m_lastFocus = NULL; | |
213 | ||
214 | wxFileCtrl::wxFileCtrl( void ) | |
215 | { | |
216 | m_dirName = "/"; | |
217 | m_showHidden = FALSE; | |
218 | }; | |
219 | ||
220 | wxFileCtrl::wxFileCtrl( wxWindow *win, const wxWindowID id, const wxString &dirName, | |
221 | const wxPoint &pos, const wxSize &size, | |
222 | const long style, const wxString &name ) : | |
223 | wxListCtrl( win, id, pos, size, style, name ) | |
224 | { | |
225 | wxImageList *imageList = new wxImageList(); | |
226 | imageList->Add( wxBitmap( folder_xpm ) ); | |
227 | imageList->Add( wxBitmap( txt_xpm ) ); | |
228 | imageList->Add( wxBitmap( list_xpm ) ); | |
229 | imageList->Add( wxBitmap( find_xpm ) ); | |
230 | ||
231 | SetImageList( imageList, wxIMAGE_LIST_NORMAL ); | |
232 | ||
233 | m_dirName = dirName; | |
234 | m_showHidden = FALSE; | |
235 | Update(); | |
236 | ||
237 | m_lastFocus = this; | |
238 | ||
239 | SetDropTarget( new wxTextDropTarget() ); | |
240 | }; | |
241 | ||
242 | void wxFileCtrl::ChangeToListMode() | |
243 | { | |
244 | SetSingleStyle( wxLC_LIST ); | |
245 | Update(); | |
246 | }; | |
247 | ||
248 | void wxFileCtrl::ChangeToReportMode() | |
249 | { | |
250 | SetSingleStyle( wxLC_REPORT ); | |
251 | Update(); | |
252 | }; | |
253 | ||
254 | void wxFileCtrl::ChangeToIconMode() | |
255 | { | |
256 | SetSingleStyle( wxLC_ICON ); | |
257 | Update(); | |
258 | }; | |
259 | ||
260 | void wxFileCtrl::ShowHidden( bool show ) | |
261 | { | |
262 | m_showHidden = show; | |
263 | Update(); | |
264 | }; | |
265 | ||
266 | int ListCompare( const long data1, const long data2, const long WXUNUSED(data) ) | |
267 | { | |
268 | wxFileData *fd1 = (wxFileData*)data1 ; | |
269 | wxFileData *fd2 = (wxFileData*)data2 ; | |
270 | if (fd1->IsDir() && !fd2->IsDir()) return -1; | |
271 | if (fd2->IsDir() && !fd1->IsDir()) return 1; | |
272 | return strcmp( fd1->GetName(), fd2->GetName() ); | |
273 | }; | |
274 | ||
275 | void wxFileCtrl::Update( void ) | |
276 | { | |
277 | DeleteAllItems(); | |
278 | for (int i = 0; i < 5; i++) DeleteColumn( 0 ); | |
279 | long my_style = GetWindowStyleFlag(); | |
280 | if (my_style & wxLC_REPORT) | |
281 | { | |
282 | InsertColumn( 0, "Name", wxLIST_FORMAT_LEFT, 110 ); | |
283 | InsertColumn( 1, "Size", wxLIST_FORMAT_LEFT, 60 ); | |
284 | InsertColumn( 2, "Date", wxLIST_FORMAT_LEFT, 55 ); | |
285 | InsertColumn( 3, "Time", wxLIST_FORMAT_LEFT, 50 ); | |
286 | InsertColumn( 4, "Permissions", wxLIST_FORMAT_LEFT, 120 ); | |
287 | }; | |
288 | wxFileData *fd = NULL; | |
289 | wxListItem item; | |
290 | item.m_mask = wxLIST_MASK_TEXT + wxLIST_MASK_DATA; | |
291 | if (my_style & wxLC_ICON) item.m_mask += wxLIST_MASK_IMAGE; | |
292 | item.m_itemId = 0; | |
293 | item.m_col = 0; | |
294 | wxString s; | |
295 | wxString res = m_dirName + "/*"; | |
296 | char *f = wxFindFirstFile( res.GetData(), 0 ); | |
297 | while (f) | |
298 | { | |
299 | res = wxFileNameFromPath( f ); | |
300 | fd = new wxFileData( res, f ); | |
301 | s = fd->GetName(); | |
302 | if (m_showHidden || (s[0] != '.')) | |
303 | { | |
304 | fd->MakeItem( item ); | |
305 | if (my_style & wxLC_REPORT) | |
306 | { | |
307 | InsertItem( item ); | |
308 | for (int i = 1; i < 5; i++) SetItem( item.m_itemId, i, fd->GetEntry( i) ); | |
309 | } | |
310 | else if (my_style & wxLC_LIST) | |
311 | { | |
312 | InsertItem( item ); | |
313 | } | |
314 | else if (my_style & wxLC_ICON) | |
315 | { | |
316 | if (fd->IsDir()) item.m_image = 0; else item.m_image = 1; | |
317 | InsertItem( item ); | |
318 | }; | |
319 | item.m_itemId++; | |
320 | }; | |
321 | f = wxFindNextFile(); | |
322 | }; | |
323 | SortItems( ListCompare, 0 ); | |
c801d85f KB |
324 | }; |
325 | ||
326 | ||
327 | int wxFileCtrl::FillList( wxStringList &list ) | |
328 | { | |
329 | long index = -1; | |
330 | int count = 0; | |
331 | wxString s; | |
332 | for (;;) | |
333 | { | |
334 | index = GetNextItem( index, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED ); | |
335 | if (index == -1) break; | |
336 | wxListItem item; | |
337 | item.m_itemId = index; | |
338 | GetItem( item ); | |
339 | wxFileData *fd = (wxFileData*)item.m_data; | |
340 | list.Add( fd->GetFullName() ); | |
341 | index++; | |
342 | count++; | |
343 | }; | |
344 | if (count == 0) | |
345 | { | |
346 | index = GetNextItem( -1, wxLIST_NEXT_ALL, wxLIST_STATE_FOCUSED ); | |
347 | if (index == -1) return 0; | |
348 | wxListItem item; | |
349 | item.m_itemId = index; | |
350 | GetItem( item ); | |
351 | wxFileData *fd = (wxFileData*)item.m_data; | |
352 | list.Add( fd->GetFullName() ); | |
353 | count = 1; | |
354 | }; | |
355 | return count; | |
356 | }; | |
357 | ||
358 | void wxFileCtrl::DeleteFiles(void) | |
359 | { | |
360 | /* | |
361 | wxStringList list; | |
362 | int count = FillList( list ); | |
363 | if (count > 0) | |
364 | { | |
365 | wxString s = "Delete "; | |
366 | s += wxIntToString( count ); | |
367 | s += " selected file"; | |
368 | if (count > 1) s += "s"; | |
369 | s += " or director"; | |
370 | if (count > 1) s += "ies?"; else s+= "y?"; | |
371 | if (wxYES == wxMessageBox( s, "Delete", wxYES_NO )) | |
372 | wxDeleteStatusDia( NULL, &list ); | |
373 | }; | |
374 | */ | |
375 | }; | |
376 | ||
377 | void wxFileCtrl::CopyFiles( char *WXUNUSED(dest) ) | |
378 | { | |
379 | /* | |
380 | wxStringList list; | |
381 | int count = FillList( list ); | |
382 | wxString s = dest; | |
383 | int ret = 0; // 0 = nix, 1 = copy, 2 = move | |
384 | wxCopyMoveDia( (wxFrame*)GetParent(), count, &ret, &s ); | |
385 | if (ret == 1) | |
386 | wxCopyStatusDia( NULL, s, &list ); | |
387 | */ | |
388 | }; | |
389 | ||
390 | void wxFileCtrl::MoveFiles( char *WXUNUSED(dest) ) | |
391 | { | |
392 | }; | |
393 | ||
394 | void wxFileCtrl::RenameFile(void) | |
395 | { | |
396 | }; | |
397 | ||
398 | void wxFileCtrl::MakeDir(void) | |
399 | { | |
400 | /* | |
401 | wxString s = wxGetTextFromUser( "Enter new directory name:", "Make directory" ); | |
402 | if (s.IsNull()) return; | |
403 | if (s == "") return; | |
404 | if ((s == ".") || (s == "..")) | |
405 | { | |
406 | wxMessageBox( "This was obviously an invalid directory name.", "Go away." ); | |
407 | return; | |
408 | }; | |
409 | wxString dir; | |
410 | GetDir( dir ); | |
411 | dir += "/"; | |
412 | dir += s; | |
413 | if (wxFileExists( dir )) | |
414 | { | |
415 | wxMessageBox( "Filename exists already. Cannot create directoy.", "Make directory" ); | |
416 | return; | |
417 | }; | |
418 | wxMkdir( dir ); | |
419 | Update(); | |
420 | */ | |
421 | }; | |
422 | ||
423 | void wxFileCtrl::GoToParentDir(void) | |
424 | { | |
425 | wxString s = m_dirName; | |
426 | int pos = s.Last( '/' ); | |
427 | if ((pos >= 0) && (s != "/")) | |
428 | { | |
429 | s.Remove( pos, s.Length()-pos ); | |
430 | if (s.Length() == 0) s = "/"; | |
431 | m_dirName = s; | |
432 | Update(); | |
433 | }; | |
434 | }; | |
435 | ||
436 | void wxFileCtrl::GoToHomeDir(void) | |
437 | { | |
438 | wxString s = wxGetUserHome( wxString() ); | |
439 | m_dirName = s; | |
440 | Update(); | |
441 | }; | |
442 | ||
443 | void wxFileCtrl::GoToDir( const wxString &dir ) | |
444 | { | |
445 | m_dirName = dir; | |
446 | Update(); | |
447 | }; | |
448 | ||
449 | void wxFileCtrl::GetDir( wxString &dir ) | |
450 | { | |
451 | dir = m_dirName; | |
452 | }; | |
453 | ||
454 | /* | |
455 | void wxFileCtrl::OnDropFiles( int WXUNUSED(n), char **WXUNUSED(data), int WXUNUSED(x), int WXUNUSED(y) ) | |
456 | { | |
457 | wxString destDir; | |
458 | wxPoint pt( x, y ); | |
459 | int flag = wxLIST_HITTEST_ONITEM; | |
460 | long hit = HitTest( pt, flag ); | |
461 | if (hit > -1) | |
462 | { | |
463 | wxListItem li; | |
464 | li.m_itemId = hit; | |
465 | GetItem( li ); | |
466 | wxFileData *fd = (wxFileData*)li.m_data; | |
467 | if (fd->IsDir()) fd->GetFullName( destDir ); | |
468 | }; | |
469 | if (destDir.IsNull()) destDir = m_dirName; | |
470 | int ret = 0; // 0 = nix, 1 = copy, 2 = move | |
471 | wxCopyMoveDia( (wxFrame*)GetParent(), n, &ret, &destDir ); | |
472 | if (ret == 1) | |
473 | { | |
474 | wxStringList slist; | |
475 | for (int i = 0; i < n; i++) slist.Add( data[i] ); | |
476 | wxCopyStatusDia( NULL, destDir.GetData(), &slist ); | |
477 | Update(); | |
478 | }; | |
479 | }; | |
480 | */ | |
481 | ||
482 | void wxFileCtrl::OnListDeleteItem( wxListEvent &event ) | |
483 | { | |
484 | wxFileData *fd = (wxFileData*)event.m_item.m_data; | |
485 | delete fd; | |
486 | }; | |
487 | ||
488 | void wxFileCtrl::OnListKeyDown( wxListEvent &event ) | |
489 | { | |
490 | wxFileData *fd = (wxFileData*)event.m_item.m_data; | |
491 | if (fd->IsDir()) | |
492 | { | |
493 | m_dirName = fd->GetFullName(); | |
494 | Update(); | |
495 | Refresh(); | |
496 | return; | |
497 | }; | |
498 | if (fd->IsExe()) | |
499 | { | |
500 | wxExecute( fd->GetFullName() ); | |
501 | return; | |
502 | }; | |
503 | }; | |
504 | ||
505 | void wxFileCtrl::OnListEndLabelEdit( wxListEvent &event ) | |
506 | { | |
507 | wxFileData *fd = (wxFileData*)event.m_item.m_data; | |
508 | wxString newName = event.m_item.m_text; | |
509 | if (fd->NewNameIsLegal( newName )) | |
510 | { | |
511 | if (fd->Rename( newName )) | |
512 | { | |
513 | Update(); | |
514 | } | |
515 | else | |
516 | { | |
517 | wxString s = "Could not rename file to "; | |
518 | s += newName; | |
519 | s += "."; | |
520 | wxMessageBox( s, "FileMaker", wxOK ); | |
521 | }; | |
522 | } | |
523 | else | |
524 | { | |
525 | wxString s = "File name "; | |
526 | s += newName; | |
527 | s += " exists already or is invalid.\n"; | |
528 | s += "Could not rename file."; | |
529 | wxMessageBox( s, "FileMaker", wxOK ); | |
530 | }; | |
531 | return; | |
532 | }; | |
533 | ||
534 | void wxFileCtrl::OnSetFocus( wxFocusEvent &event ) | |
535 | { | |
536 | m_lastFocus = this; | |
537 | event.Skip(); | |
538 | }; | |
539 | ||
540 |