X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/75ec8bd4236d11e131be099bc19d4df7588501f1..c0fbf24ba6abc81db66ead334d69af670a8ec5a7:/src/generic/filedlgg.cpp diff --git a/src/generic/filedlgg.cpp b/src/generic/filedlgg.cpp index 214a64ddab..6af187654a 100644 --- a/src/generic/filedlgg.cpp +++ b/src/generic/filedlgg.cpp @@ -45,6 +45,7 @@ #include "wx/module.h" #include "wx/config.h" #include "wx/imaglist.h" +#include "wx/dir.h" #if wxUSE_TOOLTIPS #include "wx/tooltip.h" @@ -68,6 +69,9 @@ # include #include +// XPM hack: make the arrays const +#define static static const + #ifndef __DOS__ #include "wx/generic/home.xpm" #endif @@ -79,26 +83,14 @@ #include "wx/generic/deffile.xpm" #include "wx/generic/exefile.xpm" +#undef static + //----------------------------------------------------------------------------- // wxFileData //----------------------------------------------------------------------------- class wxFileData : public wxObject { -private: - wxString m_name; - wxString m_fileName; - long m_size; - int m_hour; - int m_minute; - int m_year; - int m_month; - int m_day; - wxString m_permissions; - bool m_isDir; - bool m_isLink; - bool m_isExe; - public: wxFileData() { } wxFileData( const wxString &name, const wxString &fname ); @@ -114,6 +106,19 @@ public: void SetNewName( const wxString &name, const wxString &fname ); private: + wxString m_name; + wxString m_fileName; + long m_size; + int m_hour; + int m_minute; + int m_year; + int m_month; + int m_day; + wxString m_permissions; + bool m_isDir; + bool m_isLink; + bool m_isExe; + DECLARE_DYNAMIC_CLASS(wxFileData); }; @@ -123,11 +128,6 @@ private: class wxFileCtrl : public wxListCtrl { -private: - wxString m_dirName; - bool m_showHidden; - wxString m_wild; - public: wxFileCtrl(); wxFileCtrl( wxWindow *win, @@ -144,7 +144,7 @@ public: void ChangeToIconMode(); void ShowHidden( bool show = TRUE ); long Add( wxFileData *fd, wxListItem &item ); - void Update(); + void UpdateFiles(); virtual void StatusbarText( wxChar *WXUNUSED(text) ) {}; void MakeDir(); void GoToParentDir(); @@ -155,8 +155,21 @@ public: void OnListDeleteItem( wxListEvent &event ); void OnListDeleteAllItems( wxListEvent &event ); void OnListEndLabelEdit( wxListEvent &event ); + + // Associate commonly used UI controls with wxFileCtrl so that they can be + // disabled when they cannot be used (e.g. can't go to parent directory + // if wxFileCtrl already is in the root dir): + void SetGoToParentControl(wxWindow *ctrl) { m_goToParentControl = ctrl; } + void SetNewDirControl(wxWindow *ctrl) { m_newDirControl = ctrl; } private: + wxString m_dirName; + bool m_showHidden; + wxString m_wild; + + wxWindow *m_goToParentControl; + wxWindow *m_newDirControl; + DECLARE_DYNAMIC_CLASS(wxFileCtrl); DECLARE_EVENT_TABLE() }; @@ -374,6 +387,18 @@ int ListCompare( long data1, long data2, long WXUNUSED(data) ) return wxStrcmp( fd1->GetName(), fd2->GetName() ); } +#ifdef __UNIX__ +#define IsTopMostDir(dir) (dir == wxT("/")) +#endif + +#if defined(__DOS__) || defined(__WINDOWS__) +#define IsTopMostDir(dir) (dir.IsEmpty()) +#endif + +#if defined(__DOS__) || defined(__WINDOWS__) +extern bool wxIsDriveAvailable(const wxString& dirName); +#endif + //----------------------------------------------------------------------------- // wxFileData //----------------------------------------------------------------------------- @@ -384,9 +409,21 @@ wxFileData::wxFileData( const wxString &name, const wxString &fname ) { m_name = name; m_fileName = fname; + +#if defined(__DOS__) || defined(__WINDOWS__) + // VS: In case the file is root directory of a volume (e.g. "C:"), + // we don't want it stat()ed, since the drive may not be in: + if (name.length() == 2 && name[1u] == wxT(':')) + { + m_isDir = TRUE; + m_isExe = m_isLink = FALSE; + m_size = 0; + return; + } +#endif struct stat buff; - stat( m_fileName.fn_str(), &buff ); + wxStat( m_fileName.fn_str(), &buff ); #if defined(__UNIX__) && (!defined( __EMX__ ) && !defined(__VMS)) struct stat lbuff; @@ -539,7 +576,7 @@ void wxFileData::MakeItem( wxListItem &item ) else if (IsExe()) item.m_image = FI_EXECUTABLE; else if (m_name.Find(wxT('.')) != wxNOT_FOUND) - item.m_image = g_IconsTable -> GetIconID(m_name.AfterLast(wxT('.'))); + item.m_image = g_IconsTable->GetIconID(m_name.AfterLast(wxT('.'))); else item.m_image = FI_UNKNOWN; @@ -569,50 +606,54 @@ wxFileCtrl::wxFileCtrl() #if defined(__UNIX__) m_dirName = wxT("/"); #elif defined(__DOS__) - m_dirName = wxT("C:\\"); + m_dirName = wxT(""); #endif m_showHidden = FALSE; } -wxFileCtrl::wxFileCtrl( wxWindow *win, wxWindowID id, - const wxString &dirName, const wxString &wild, - const wxPoint &pos, const wxSize &size, - long style, const wxValidator &validator, const wxString &name ) : - wxListCtrl( win, id, pos, size, style, validator, name ) +wxFileCtrl::wxFileCtrl(wxWindow *win, wxWindowID id, + const wxString &dirName, const wxString &wild, + const wxPoint &pos, const wxSize &size, + long style, const wxValidator &validator, + const wxString &name) + : wxListCtrl(win, id, pos, size, style, validator, name) { - if (! g_IconsTable) g_IconsTable = new wxFileIconsTable; - wxImageList *imageList = g_IconsTable -> GetImageList(); + if (! g_IconsTable) + g_IconsTable = new wxFileIconsTable; + wxImageList *imageList = g_IconsTable->GetImageList(); SetImageList( imageList, wxIMAGE_LIST_SMALL ); + m_goToParentControl = m_newDirControl = NULL; + m_dirName = dirName; m_wild = wild; m_showHidden = FALSE; - Update(); + UpdateFiles(); } void wxFileCtrl::ChangeToListMode() { SetSingleStyle( wxLC_LIST ); - Update(); + UpdateFiles(); } void wxFileCtrl::ChangeToReportMode() { SetSingleStyle( wxLC_REPORT ); - Update(); + UpdateFiles(); } void wxFileCtrl::ChangeToIconMode() { SetSingleStyle( wxLC_ICON ); - Update(); + UpdateFiles(); } void wxFileCtrl::ShowHidden( bool show ) { m_showHidden = show; - Update(); + UpdateFiles(); } long wxFileCtrl::Add( wxFileData *fd, wxListItem &item ) @@ -639,8 +680,10 @@ long wxFileCtrl::Add( wxFileData *fd, wxListItem &item ) return ret; } -void wxFileCtrl::Update() +void wxFileCtrl::UpdateFiles() { + wxBusyCursor bcur; // this may take a while... + long my_style = GetWindowStyleFlag(); int name_col_width = 0; if (my_style & wxLC_REPORT) @@ -666,74 +709,108 @@ void wxFileCtrl::Update() item.m_itemId = 0; item.m_col = 0; - if (m_dirName != wxT("/")) - { - wxString p( wxPathOnly(m_dirName) ); - if (p.IsEmpty()) p = wxT("/"); - fd = new wxFileData( wxT(".."), p ); - Add( fd, item ); - item.m_itemId++; +#if defined(__DOS__) || defined(__WINDOWS__) + if ( IsTopMostDir(m_dirName) ) + { + // Pseudo-directory with all available drives listed... + for (int drive = 1; drive <= 26; drive++) + { + wxString path; + path.Printf(wxT("%c:\\"), (char)(drive + 'A' - 1)); + if ( wxIsDriveAvailable(path) ) + { + path.RemoveLast(); + fd = new wxFileData(path, path); + Add(fd, item); + item.m_itemId++; + } + } } - -#if defined(__UNIX__) - wxString res = m_dirName + wxT("/*"); -#elif defined(__DOS__) - wxString res = m_dirName + wxT("\\*.*"); + else #endif - wxString f( wxFindFirstFile( res.GetData(), wxDIR ) ); - while (!f.IsEmpty()) { - res = wxFileNameFromPath( f ); - fd = new wxFileData( res, f ); - wxString s = fd->GetName(); - if (m_showHidden || (s[0u] != wxT('.'))) + // Real directory... + if ( !IsTopMostDir(m_dirName) ) { - Add( fd, item ); + wxString p(wxPathOnly(m_dirName)); +#ifdef __UNIX__ + if (p.IsEmpty()) p = wxT("/"); +#endif + fd = new wxFileData( wxT(".."), p ); + Add(fd, item); item.m_itemId++; } - f = wxFindNextFile(); - } - // Tokenize the wildcard string, so we can handle more than 1 - // search pattern in a wildcard. - wxStringTokenizer tokenWild( m_wild, ";" ); - while ( tokenWild.HasMoreTokens() ) - { - res = m_dirName + wxFILE_SEP_PATH + tokenWild.GetNextToken(); - f = wxFindFirstFile( res.GetData(), wxFILE ); - while (!f.IsEmpty()) + wxString dirname(m_dirName); +#if defined(__DOS__) || defined(__WINDOWS__) + if (dirname.length() == 2 && dirname[1u] == wxT(':')) + dirname << wxT('\\'); +#endif + wxDir dir(dirname); + + if ( dir.IsOpened() ) { - res = wxFileNameFromPath( f ); - fd = new wxFileData( res, f ); - wxString s = fd->GetName(); - if (m_showHidden || (s[0u] != wxT('.'))) + wxString dirPrefix(dirname + wxFILE_SEP_PATH); + int hiddenFlag = m_showHidden ? wxDIR_HIDDEN : 0; + + bool cont; + wxString f; + + // Get the directories first (not matched against wildcards): + cont = dir.GetFirst(&f, wxEmptyString, wxDIR_DIRS | hiddenFlag); + while (cont) { - Add( fd, item ); + fd = new wxFileData(f, dirPrefix + f); + Add(fd, item); item.m_itemId++; + cont = dir.GetNext(&f); + } + + // Tokenize the wildcard string, so we can handle more than 1 + // search pattern in a wildcard. + wxStringTokenizer tokenWild(m_wild, wxT(";")); + while ( tokenWild.HasMoreTokens() ) + { + cont = dir.GetFirst(&f, tokenWild.GetNextToken(), + wxDIR_FILES | hiddenFlag); + while (cont) + { + fd = new wxFileData(f, dirPrefix + f); + Add(fd, item); + item.m_itemId++; + cont = dir.GetNext(&f); + } } - f = wxFindNextFile(); } } - SortItems( ListCompare, 0 ); + SortItems(ListCompare, 0); - if (my_style & wxLC_REPORT) + if ( my_style & wxLC_REPORT ) { - SetColumnWidth( 1, wxLIST_AUTOSIZE ); - SetColumnWidth( 2, wxLIST_AUTOSIZE ); - SetColumnWidth( 3, wxLIST_AUTOSIZE ); + SetColumnWidth(1, wxLIST_AUTOSIZE); + SetColumnWidth(2, wxLIST_AUTOSIZE); + SetColumnWidth(3, wxLIST_AUTOSIZE); } + + // Finally, enable/disable context-dependent controls: + if ( m_goToParentControl ) + m_goToParentControl->Enable(!IsTopMostDir(m_dirName)); +#if defined(__DOS__) || defined(__WINDOWS__) + if ( m_newDirControl ) + m_newDirControl->Enable(!IsTopMostDir(m_dirName)); +#endif } void wxFileCtrl::SetWild( const wxString &wild ) { m_wild = wild; - Update(); + UpdateFiles(); } void wxFileCtrl::MakeDir() { - wxString new_name( wxT("NewName") ); + wxString new_name( _("NewName") ); wxString path( m_dirName ); path += wxFILE_SEP_PATH; path += new_name; @@ -779,15 +856,18 @@ void wxFileCtrl::MakeDir() void wxFileCtrl::GoToParentDir() { - if (m_dirName != wxT("/")) + if (!IsTopMostDir(m_dirName)) { size_t len = m_dirName.Len(); if (m_dirName[len-1] == wxFILE_SEP_PATH) m_dirName.Remove( len-1, 1 ); wxString fname( wxFileNameFromPath(m_dirName) ); m_dirName = wxPathOnly( m_dirName ); - if (m_dirName.IsEmpty()) m_dirName = wxT("/"); - Update(); +#ifdef __UNIX__ + if (m_dirName.IsEmpty()) + m_dirName = wxT("/"); +#endif + UpdateFiles(); long id = FindItem( 0, fname ); if (id != -1) { @@ -800,16 +880,13 @@ void wxFileCtrl::GoToParentDir() void wxFileCtrl::GoToHomeDir() { wxString s = wxGetUserHome( wxString() ); - m_dirName = s; - Update(); - SetItemState( 0, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED ); - EnsureVisible( 0 ); + GoToDir(s); } void wxFileCtrl::GoToDir( const wxString &dir ) { m_dirName = dir; - Update(); + UpdateFiles(); SetItemState( 0, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED ); EnsureVisible( 0 ); } @@ -889,16 +966,16 @@ void wxFileCtrl::OnListEndLabelEdit( wxListEvent &event ) // wxFileDialog //----------------------------------------------------------------------------- -#define ID_LIST_MODE wxID_FILEDLGG -#define ID_REPORT_MODE wxID_FILEDLGG + 1 -#define ID_UP_DIR wxID_FILEDLGG + 5 -#define ID_PARENT_DIR wxID_FILEDLGG + 6 -#define ID_NEW_DIR wxID_FILEDLGG + 7 -#define ID_CHOICE wxID_FILEDLGG + 8 -#define ID_TEXT wxID_FILEDLGG + 9 -#define ID_LIST_CTRL wxID_FILEDLGG + 10 -#define ID_ACTIVATED wxID_FILEDLGG + 11 -#define ID_CHECK wxID_FILEDLGG + 12 +#define ID_LIST_MODE (wxID_FILEDLGG ) +#define ID_REPORT_MODE (wxID_FILEDLGG + 1) +#define ID_UP_DIR (wxID_FILEDLGG + 5) +#define ID_PARENT_DIR (wxID_FILEDLGG + 6) +#define ID_NEW_DIR (wxID_FILEDLGG + 7) +#define ID_CHOICE (wxID_FILEDLGG + 8) +#define ID_TEXT (wxID_FILEDLGG + 9) +#define ID_LIST_CTRL (wxID_FILEDLGG + 10) +#define ID_ACTIVATED (wxID_FILEDLGG + 11) +#define ID_CHECK (wxID_FILEDLGG + 12) IMPLEMENT_DYNAMIC_CLASS(wxFileDialog,wxDialog) @@ -928,12 +1005,14 @@ wxFileDialog::wxFileDialog(wxWindow *parent, const wxPoint& pos ) : wxDialog( parent, -1, message, pos, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER ) { - wxBeginBusyCursor(); + wxBusyCursor bcur; if (wxConfig::Get(FALSE)) { - wxConfig::Get() -> Read(wxT("/wxWindows/wxFileDialog/ViewStyle"), &s_lastViewStyle); - wxConfig::Get() -> Read(wxT("/wxWindows/wxFileDialog/ShowHidden"), &s_lastShowHidden); + wxConfig::Get()->Read(wxT("/wxWindows/wxFileDialog/ViewStyle"), + &s_lastViewStyle); + wxConfig::Get()->Read(wxT("/wxWindows/wxFileDialog/ShowHidden"), + &s_lastShowHidden); } m_message = message; @@ -1006,13 +1085,14 @@ wxFileDialog::wxFileDialog(wxWindow *parent, buttonsizer->Add( 30, 5, 1 ); - but = new wxBitmapButton( this, ID_UP_DIR, wxBitmap( dir_up_xpm ) ); + wxWindow *butDirUp = + new wxBitmapButton( this, ID_UP_DIR, wxBitmap( dir_up_xpm ) ); #if wxUSE_TOOLTIPS - but->SetToolTip( _("Go to parent directory") ); + butDirUp->SetToolTip( _("Go to parent directory") ); #endif - buttonsizer->Add( but, 0, wxALL, 5 ); + buttonsizer->Add( butDirUp, 0, wxALL, 5 ); -#ifndef __DOS__ // VS: Home directory is senseless in MS-DOS... +#ifndef __DOS__ // VS: Home directory is meaningless in MS-DOS... but = new wxBitmapButton( this, ID_PARENT_DIR, wxBitmap(home_xpm) ); #if wxUSE_TOOLTIPS but->SetToolTip( _("Go to home directory") ); @@ -1022,11 +1102,12 @@ wxFileDialog::wxFileDialog(wxWindow *parent, buttonsizer->Add( 20, 20 ); #endif //!__DOS__ - but = new wxBitmapButton( this, ID_NEW_DIR, wxBitmap(new_dir_xpm) ); + wxWindow *butNewDir = + new wxBitmapButton( this, ID_NEW_DIR, wxBitmap(new_dir_xpm) ); #if wxUSE_TOOLTIPS - but->SetToolTip( _("Create new directory") ); + butNewDir->SetToolTip( _("Create new directory") ); #endif - buttonsizer->Add( but, 0, wxALL, 5 ); + buttonsizer->Add( butNewDir, 0, wxALL, 5 ); mainsizer->Add( buttonsizer, 0, wxALL | wxEXPAND, 5 ); @@ -1042,7 +1123,10 @@ wxFileDialog::wxFileDialog(wxWindow *parent, else m_list = new wxFileCtrl( this, ID_LIST_CTRL, m_dir, firstWild, wxDefaultPosition, wxSize(540,200), s_lastViewStyle | wxSUNKEN_BORDER | wxLC_SINGLE_SEL ); - m_list -> ShowHidden(s_lastShowHidden); + m_list->ShowHidden(s_lastShowHidden); + m_list->SetNewDirControl(butNewDir); + m_list->SetGoToParentControl(butDirUp); + mainsizer->Add( m_list, 1, wxEXPAND | wxLEFT|wxRIGHT, 10 ); wxBoxSizer *textsizer = new wxBoxSizer( wxHORIZONTAL ); @@ -1083,16 +1167,16 @@ wxFileDialog::wxFileDialog(wxWindow *parent, else */ m_text->SetFocus(); - - wxEndBusyCursor(); } wxFileDialog::~wxFileDialog() { if (wxConfig::Get(FALSE)) { - wxConfig::Get() -> Write(wxT("/wxWindows/wxFileDialog/ViewStyle"), s_lastViewStyle); - wxConfig::Get() -> Write(wxT("/wxWindows/wxFileDialog/ShowHidden"), s_lastShowHidden); + wxConfig::Get()->Write(wxT("/wxWindows/wxFileDialog/ViewStyle"), + s_lastViewStyle); + wxConfig::Get()->Write(wxT("/wxWindows/wxFileDialog/ShowHidden"), + s_lastShowHidden); } } @@ -1137,7 +1221,8 @@ void wxFileDialog::OnSelected( wxListEvent &event ) wxString dir; m_list->GetDir( dir ); - if (dir != wxT("/")) dir += wxFILE_SEP_PATH; + if (!IsTopMostDir(dir)) + dir += wxFILE_SEP_PATH; dir += filename; if (wxDirExists(dir)) return; @@ -1193,8 +1278,9 @@ void wxFileDialog::HandleAction( const wxString &fn ) return; } - if (dir != wxT("/")) dir += wxFILE_SEP_PATH; - if (filename[0u] != wxT('/')) + if (!IsTopMostDir(dir)) + dir += wxFILE_SEP_PATH; + if (!wxIsAbsolutePath(filename)) { dir += filename; filename = dir; @@ -1330,7 +1416,10 @@ void wxFileDialog::GetPaths( wxArrayString& paths ) const wxString dir; m_list->GetDir( dir ); - if (dir != wxT("/")) dir += wxFILE_SEP_PATH; +#ifdef __UNIX__ + if (dir != wxT("/")) +#endif + dir += wxFILE_SEP_PATH; wxListItem item; item.m_mask = wxLIST_MASK_TEXT;