]>
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 | { | |
33d0b396 RR |
225 | SetItemSpacing( 20 ); |
226 | wxImageList *imageList = new wxImageList( 18, 18 ); | |
c801d85f KB |
227 | imageList->Add( wxBitmap( folder_xpm ) ); |
228 | imageList->Add( wxBitmap( txt_xpm ) ); | |
229 | imageList->Add( wxBitmap( list_xpm ) ); | |
230 | imageList->Add( wxBitmap( find_xpm ) ); | |
231 | ||
232 | SetImageList( imageList, wxIMAGE_LIST_NORMAL ); | |
233 | ||
234 | m_dirName = dirName; | |
235 | m_showHidden = FALSE; | |
236 | Update(); | |
237 | ||
238 | m_lastFocus = this; | |
239 | ||
240 | SetDropTarget( new wxTextDropTarget() ); | |
241 | }; | |
242 | ||
243 | void wxFileCtrl::ChangeToListMode() | |
244 | { | |
245 | SetSingleStyle( wxLC_LIST ); | |
246 | Update(); | |
247 | }; | |
248 | ||
249 | void wxFileCtrl::ChangeToReportMode() | |
250 | { | |
251 | SetSingleStyle( wxLC_REPORT ); | |
252 | Update(); | |
253 | }; | |
254 | ||
255 | void wxFileCtrl::ChangeToIconMode() | |
256 | { | |
257 | SetSingleStyle( wxLC_ICON ); | |
258 | Update(); | |
259 | }; | |
260 | ||
261 | void wxFileCtrl::ShowHidden( bool show ) | |
262 | { | |
263 | m_showHidden = show; | |
264 | Update(); | |
265 | }; | |
266 | ||
267 | int ListCompare( const long data1, const long data2, const long WXUNUSED(data) ) | |
268 | { | |
269 | wxFileData *fd1 = (wxFileData*)data1 ; | |
270 | wxFileData *fd2 = (wxFileData*)data2 ; | |
271 | if (fd1->IsDir() && !fd2->IsDir()) return -1; | |
272 | if (fd2->IsDir() && !fd1->IsDir()) return 1; | |
273 | return strcmp( fd1->GetName(), fd2->GetName() ); | |
274 | }; | |
275 | ||
276 | void wxFileCtrl::Update( void ) | |
277 | { | |
278 | DeleteAllItems(); | |
279 | for (int i = 0; i < 5; i++) DeleteColumn( 0 ); | |
280 | long my_style = GetWindowStyleFlag(); | |
281 | if (my_style & wxLC_REPORT) | |
282 | { | |
283 | InsertColumn( 0, "Name", wxLIST_FORMAT_LEFT, 110 ); | |
284 | InsertColumn( 1, "Size", wxLIST_FORMAT_LEFT, 60 ); | |
285 | InsertColumn( 2, "Date", wxLIST_FORMAT_LEFT, 55 ); | |
286 | InsertColumn( 3, "Time", wxLIST_FORMAT_LEFT, 50 ); | |
287 | InsertColumn( 4, "Permissions", wxLIST_FORMAT_LEFT, 120 ); | |
288 | }; | |
289 | wxFileData *fd = NULL; | |
290 | wxListItem item; | |
291 | item.m_mask = wxLIST_MASK_TEXT + wxLIST_MASK_DATA; | |
292 | if (my_style & wxLC_ICON) item.m_mask += wxLIST_MASK_IMAGE; | |
293 | item.m_itemId = 0; | |
294 | item.m_col = 0; | |
295 | wxString s; | |
296 | wxString res = m_dirName + "/*"; | |
297 | char *f = wxFindFirstFile( res.GetData(), 0 ); | |
298 | while (f) | |
299 | { | |
300 | res = wxFileNameFromPath( f ); | |
301 | fd = new wxFileData( res, f ); | |
302 | s = fd->GetName(); | |
303 | if (m_showHidden || (s[0] != '.')) | |
304 | { | |
305 | fd->MakeItem( item ); | |
306 | if (my_style & wxLC_REPORT) | |
307 | { | |
308 | InsertItem( item ); | |
309 | for (int i = 1; i < 5; i++) SetItem( item.m_itemId, i, fd->GetEntry( i) ); | |
310 | } | |
311 | else if (my_style & wxLC_LIST) | |
312 | { | |
313 | InsertItem( item ); | |
314 | } | |
315 | else if (my_style & wxLC_ICON) | |
316 | { | |
317 | if (fd->IsDir()) item.m_image = 0; else item.m_image = 1; | |
318 | InsertItem( item ); | |
319 | }; | |
320 | item.m_itemId++; | |
321 | }; | |
322 | f = wxFindNextFile(); | |
323 | }; | |
324 | SortItems( ListCompare, 0 ); | |
c801d85f KB |
325 | }; |
326 | ||
327 | ||
328 | int wxFileCtrl::FillList( wxStringList &list ) | |
329 | { | |
330 | long index = -1; | |
331 | int count = 0; | |
332 | wxString s; | |
333 | for (;;) | |
334 | { | |
335 | index = GetNextItem( index, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED ); | |
336 | if (index == -1) break; | |
337 | wxListItem item; | |
338 | item.m_itemId = index; | |
339 | GetItem( item ); | |
340 | wxFileData *fd = (wxFileData*)item.m_data; | |
341 | list.Add( fd->GetFullName() ); | |
342 | index++; | |
343 | count++; | |
344 | }; | |
345 | if (count == 0) | |
346 | { | |
347 | index = GetNextItem( -1, wxLIST_NEXT_ALL, wxLIST_STATE_FOCUSED ); | |
348 | if (index == -1) return 0; | |
349 | wxListItem item; | |
350 | item.m_itemId = index; | |
351 | GetItem( item ); | |
352 | wxFileData *fd = (wxFileData*)item.m_data; | |
353 | list.Add( fd->GetFullName() ); | |
354 | count = 1; | |
355 | }; | |
356 | return count; | |
357 | }; | |
358 | ||
359 | void wxFileCtrl::DeleteFiles(void) | |
360 | { | |
361 | /* | |
362 | wxStringList list; | |
363 | int count = FillList( list ); | |
364 | if (count > 0) | |
365 | { | |
366 | wxString s = "Delete "; | |
367 | s += wxIntToString( count ); | |
368 | s += " selected file"; | |
369 | if (count > 1) s += "s"; | |
370 | s += " or director"; | |
371 | if (count > 1) s += "ies?"; else s+= "y?"; | |
372 | if (wxYES == wxMessageBox( s, "Delete", wxYES_NO )) | |
373 | wxDeleteStatusDia( NULL, &list ); | |
374 | }; | |
375 | */ | |
376 | }; | |
377 | ||
378 | void wxFileCtrl::CopyFiles( char *WXUNUSED(dest) ) | |
379 | { | |
380 | /* | |
381 | wxStringList list; | |
382 | int count = FillList( list ); | |
383 | wxString s = dest; | |
384 | int ret = 0; // 0 = nix, 1 = copy, 2 = move | |
385 | wxCopyMoveDia( (wxFrame*)GetParent(), count, &ret, &s ); | |
386 | if (ret == 1) | |
387 | wxCopyStatusDia( NULL, s, &list ); | |
388 | */ | |
389 | }; | |
390 | ||
391 | void wxFileCtrl::MoveFiles( char *WXUNUSED(dest) ) | |
392 | { | |
393 | }; | |
394 | ||
395 | void wxFileCtrl::RenameFile(void) | |
396 | { | |
397 | }; | |
398 | ||
399 | void wxFileCtrl::MakeDir(void) | |
400 | { | |
401 | /* | |
402 | wxString s = wxGetTextFromUser( "Enter new directory name:", "Make directory" ); | |
403 | if (s.IsNull()) return; | |
404 | if (s == "") return; | |
405 | if ((s == ".") || (s == "..")) | |
406 | { | |
407 | wxMessageBox( "This was obviously an invalid directory name.", "Go away." ); | |
408 | return; | |
409 | }; | |
410 | wxString dir; | |
411 | GetDir( dir ); | |
412 | dir += "/"; | |
413 | dir += s; | |
414 | if (wxFileExists( dir )) | |
415 | { | |
416 | wxMessageBox( "Filename exists already. Cannot create directoy.", "Make directory" ); | |
417 | return; | |
418 | }; | |
419 | wxMkdir( dir ); | |
420 | Update(); | |
421 | */ | |
422 | }; | |
423 | ||
424 | void wxFileCtrl::GoToParentDir(void) | |
425 | { | |
426 | wxString s = m_dirName; | |
427 | int pos = s.Last( '/' ); | |
428 | if ((pos >= 0) && (s != "/")) | |
429 | { | |
430 | s.Remove( pos, s.Length()-pos ); | |
431 | if (s.Length() == 0) s = "/"; | |
432 | m_dirName = s; | |
433 | Update(); | |
434 | }; | |
435 | }; | |
436 | ||
437 | void wxFileCtrl::GoToHomeDir(void) | |
438 | { | |
439 | wxString s = wxGetUserHome( wxString() ); | |
440 | m_dirName = s; | |
441 | Update(); | |
442 | }; | |
443 | ||
444 | void wxFileCtrl::GoToDir( const wxString &dir ) | |
445 | { | |
446 | m_dirName = dir; | |
447 | Update(); | |
448 | }; | |
449 | ||
450 | void wxFileCtrl::GetDir( wxString &dir ) | |
451 | { | |
452 | dir = m_dirName; | |
453 | }; | |
454 | ||
455 | /* | |
456 | void wxFileCtrl::OnDropFiles( int WXUNUSED(n), char **WXUNUSED(data), int WXUNUSED(x), int WXUNUSED(y) ) | |
457 | { | |
458 | wxString destDir; | |
459 | wxPoint pt( x, y ); | |
460 | int flag = wxLIST_HITTEST_ONITEM; | |
461 | long hit = HitTest( pt, flag ); | |
462 | if (hit > -1) | |
463 | { | |
464 | wxListItem li; | |
465 | li.m_itemId = hit; | |
466 | GetItem( li ); | |
467 | wxFileData *fd = (wxFileData*)li.m_data; | |
468 | if (fd->IsDir()) fd->GetFullName( destDir ); | |
469 | }; | |
470 | if (destDir.IsNull()) destDir = m_dirName; | |
471 | int ret = 0; // 0 = nix, 1 = copy, 2 = move | |
472 | wxCopyMoveDia( (wxFrame*)GetParent(), n, &ret, &destDir ); | |
473 | if (ret == 1) | |
474 | { | |
475 | wxStringList slist; | |
476 | for (int i = 0; i < n; i++) slist.Add( data[i] ); | |
477 | wxCopyStatusDia( NULL, destDir.GetData(), &slist ); | |
478 | Update(); | |
479 | }; | |
480 | }; | |
481 | */ | |
482 | ||
483 | void wxFileCtrl::OnListDeleteItem( wxListEvent &event ) | |
484 | { | |
485 | wxFileData *fd = (wxFileData*)event.m_item.m_data; | |
486 | delete fd; | |
487 | }; | |
488 | ||
489 | void wxFileCtrl::OnListKeyDown( wxListEvent &event ) | |
490 | { | |
491 | wxFileData *fd = (wxFileData*)event.m_item.m_data; | |
492 | if (fd->IsDir()) | |
493 | { | |
494 | m_dirName = fd->GetFullName(); | |
495 | Update(); | |
496 | Refresh(); | |
497 | return; | |
498 | }; | |
499 | if (fd->IsExe()) | |
500 | { | |
501 | wxExecute( fd->GetFullName() ); | |
502 | return; | |
503 | }; | |
504 | }; | |
505 | ||
506 | void wxFileCtrl::OnListEndLabelEdit( wxListEvent &event ) | |
507 | { | |
508 | wxFileData *fd = (wxFileData*)event.m_item.m_data; | |
509 | wxString newName = event.m_item.m_text; | |
510 | if (fd->NewNameIsLegal( newName )) | |
511 | { | |
512 | if (fd->Rename( newName )) | |
513 | { | |
514 | Update(); | |
515 | } | |
516 | else | |
517 | { | |
518 | wxString s = "Could not rename file to "; | |
519 | s += newName; | |
520 | s += "."; | |
521 | wxMessageBox( s, "FileMaker", wxOK ); | |
522 | }; | |
523 | } | |
524 | else | |
525 | { | |
526 | wxString s = "File name "; | |
527 | s += newName; | |
528 | s += " exists already or is invalid.\n"; | |
529 | s += "Could not rename file."; | |
530 | wxMessageBox( s, "FileMaker", wxOK ); | |
531 | }; | |
532 | return; | |
533 | }; | |
534 | ||
535 | void wxFileCtrl::OnSetFocus( wxFocusEvent &event ) | |
536 | { | |
537 | m_lastFocus = this; | |
538 | event.Skip(); | |
539 | }; | |
540 | ||
541 |