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