From c61f4f6dbd971245f694eb01034c86040a44db00 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Tue, 7 Dec 1999 00:48:45 +0000 Subject: [PATCH] 1. wxFileDialog patch for multiple selection applied (with some small changes), added demo for it in the sample and documented 2. wxMimeTypeManager works a bit better under Windows (doesn't ignore the extensions without filetypes) git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@4850 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- docs/latex/wx/filedlg.tex | 17 +++++ include/wx/filedlg.h | 10 +++ include/wx/generic/filedlgg.h | 14 +--- include/wx/msw/filedlg.h | 67 +++++++++--------- samples/console/console.cpp | 5 ++ samples/dialogs/dialogs.cpp | 43 ++++++++++-- samples/dialogs/dialogs.h | 8 ++- src/common/mimetype.cpp | 45 +++++++++--- src/msw/filedlg.cpp | 126 ++++++++++++++++++++++++++-------- 9 files changed, 241 insertions(+), 94 deletions(-) diff --git a/docs/latex/wx/filedlg.tex b/docs/latex/wx/filedlg.tex index f6fe6531e1..63d4a9bd1a 100644 --- a/docs/latex/wx/filedlg.tex +++ b/docs/latex/wx/filedlg.tex @@ -68,6 +68,7 @@ Constructor. Use \helpref{wxFileDialog::ShowModal}{wxfiledialogshowmodal} to sho \twocolitem{{\bf wxSAVE}}{This is a save dialog.} \twocolitem{{\bf wxHIDE\_READONLY}}{Hide read-only files.} \twocolitem{{\bf wxOVERWRITE\_PROMPT}}{Prompt for a conformation if a file will be overridden.} +\twocolitem{{\bf wxMULTIPLE}}{For open dialog only: allows selecting multiple files} \end{twocollist}% } @@ -91,6 +92,14 @@ Returns the default directory. Returns the default filename. +\membersection{wxFileDialog::GetFilenames}\label{wxfiledialoggetfilenames} + +\constfunc{void}{GetFilenames}{\param{wxArrayString\& }{filenames}} + +Fills the array {\it filenames} with the names of the files chosen. This +function should only be used with the dialogs which have {\tt wxMULTIPLE} style, +use \helpref{GetFilename}{wxfiledialoggetfilename} for the others. + \membersection{wxFileDialog::GetFilterIndex}\label{wxfiledialoggetfilterindex} \constfunc{int}{GetFilterIndex}{\void} @@ -111,6 +120,14 @@ Returns the message that will be displayed on the dialog. Returns the full path (directory and filename) of the selected file. +\membersection{wxFileDialog::GetPaths}\label{wxfiledialoggetpaths} + +\constfunc{void}{GetPaths}{\param{wxArrayString\& }{paths}} + +Fills the array {\it paths} with the full paths of the files chosen. This +function should only be used with the dialogs which have {\tt wxMULTIPLE} style, +use \helpref{GetPath}{wxfiledialoggetpath} for the others. + \membersection{wxFileDialog::GetStyle}\label{wxfiledialoggetstyle} \constfunc{long}{GetStyle}{\void} diff --git a/include/wx/filedlg.h b/include/wx/filedlg.h index 14b0010184..b35e63d016 100644 --- a/include/wx/filedlg.h +++ b/include/wx/filedlg.h @@ -1,6 +1,16 @@ #ifndef _WX_FILEDLG_H_BASE_ #define _WX_FILEDLG_H_BASE_ +enum +{ + wxOPEN = 1, + wxSAVE = 2, + wxOVERWRITE_PROMPT = 4, + wxHIDE_READONLY = 8, + wxFILE_MUST_EXIST = 16, + wxMULTIPLE = 32 +}; + #if defined(__WXMSW__) #include "wx/msw/filedlg.h" #elif defined(__WXMOTIF__) diff --git a/include/wx/generic/filedlgg.h b/include/wx/generic/filedlgg.h index 2fc5b07319..dbc7494b18 100644 --- a/include/wx/generic/filedlgg.h +++ b/include/wx/generic/filedlgg.h @@ -155,7 +155,7 @@ public: wxString GetWildcard() const { return m_wildCard; } long GetStyle() const { return m_dialogStyle; } int GetFilterIndex() const { return m_filterIndex; } - + // for multiple file selection void GetPaths(wxArrayString& paths) const; void GetFilenames(wxArrayString& files) const; @@ -171,7 +171,7 @@ public: void OnChoice( wxCommandEvent &event ); void OnTextEnter( wxCommandEvent &event ); void OnCheck( wxCommandEvent &event ); - + void HandleAction( const wxString &fn ); protected: @@ -193,16 +193,6 @@ private: DECLARE_EVENT_TABLE() }; -enum -{ - wxOPEN = 1, - wxSAVE = 2, - wxOVERWRITE_PROMPT = 4, - wxHIDE_READONLY = 8, - wxFILE_MUST_EXIST = 16, - wxMULTIPLE = 32 -}; - // File selector - backward compatibility WXDLLEXPORT wxString wxFileSelector(const wxChar *message = wxFileSelectorPromptStr, diff --git a/include/wx/msw/filedlg.h b/include/wx/msw/filedlg.h index 65a4badb0c..e146c83928 100644 --- a/include/wx/msw/filedlg.h +++ b/include/wx/msw/filedlg.h @@ -13,7 +13,7 @@ #define _WX_FILEDLG_H_ #ifdef __GNUG__ -#pragma interface "filedlg.h" + #pragma interface "filedlg.h" #endif #include "wx/dialog.h" @@ -27,48 +27,46 @@ WXDLLEXPORT_DATA(extern const wxChar*) wxFileSelectorDefaultWildcardStr; class WXDLLEXPORT wxFileDialog: public wxDialog { -DECLARE_DYNAMIC_CLASS(wxFileDialog) - public: wxFileDialog(wxWindow *parent, const wxString& message = wxFileSelectorPromptStr, const wxString& defaultDir = wxEmptyString, const wxString& defaultFile = wxEmptyString, const wxString& wildCard = wxFileSelectorDefaultWildcardStr, long style = 0, const wxPoint& pos = wxDefaultPosition); - inline void SetMessage(const wxString& message) { m_message = message; } - inline void SetPath(const wxString& path) { m_path = path; } - inline void SetDirectory(const wxString& dir) { m_dir = dir; } - inline void SetFilename(const wxString& name) { m_fileName = name; } - inline void SetWildcard(const wxString& wildCard) { m_wildCard = wildCard; } - inline void SetStyle(long style) { m_dialogStyle = style; } - inline void SetFilterIndex(int filterIndex) { m_filterIndex = filterIndex; } - - inline wxString GetMessage(void) const { return m_message; } - inline wxString GetPath(void) const { return m_path; } - inline wxString GetDirectory(void) const { return m_dir; } - inline wxString GetFilename(void) const { return m_fileName; } - inline wxString GetWildcard(void) const { return m_wildCard; } - inline long GetStyle(void) const { return m_dialogStyle; } - inline int GetFilterIndex(void) const { return m_filterIndex ; } - - int ShowModal(void); + void SetMessage(const wxString& message) { m_message = message; } + void SetPath(const wxString& path) { m_path = path; } + void SetDirectory(const wxString& dir) { m_dir = dir; } + void SetFilename(const wxString& name) { m_fileName = name; } + void SetWildcard(const wxString& wildCard) { m_wildCard = wildCard; } + void SetStyle(long style) { m_dialogStyle = style; } + void SetFilterIndex(int filterIndex) { m_filterIndex = filterIndex; } + + wxString GetMessage() const { return m_message; } + wxString GetPath() const { return m_path; } + void GetPaths(wxArrayString& paths) const; + wxString GetDirectory() const { return m_dir; } + wxString GetFilename() const { return m_fileName; } + void GetFilenames(wxArrayString& files) const { files = m_fileNames; } + wxString GetWildcard() const { return m_wildCard; } + long GetStyle() const { return m_dialogStyle; } + int GetFilterIndex() const { return m_filterIndex ; } + + int ShowModal(); protected: - wxString m_message; - long m_dialogStyle; - wxWindow * m_parent; - wxString m_dir; - wxString m_path; // Full path - wxString m_fileName; - wxString m_wildCard; - int m_filterIndex; + wxString m_message; + long m_dialogStyle; + wxWindow * m_parent; + wxString m_dir; + wxString m_path; // Full path + wxString m_fileName; + wxArrayString m_fileNames; + wxString m_wildCard; + int m_filterIndex; + +private: + DECLARE_DYNAMIC_CLASS(wxFileDialog) }; -#define wxOPEN 0x0001 -#define wxSAVE 0x0002 -#define wxOVERWRITE_PROMPT 0x0004 -#define wxHIDE_READONLY 0x0008 -#define wxFILE_MUST_EXIST 0x0010 - // File selector - backward compatibility WXDLLEXPORT wxString wxFileSelector(const wxChar *message = wxFileSelectorPromptStr, @@ -107,3 +105,4 @@ wxSaveFileSelector(const wxChar *what, #endif // _WX_FILEDLG_H_ + diff --git a/samples/console/console.cpp b/samples/console/console.cpp index 52fef9185c..9bd6269738 100644 --- a/samples/console/console.cpp +++ b/samples/console/console.cpp @@ -65,7 +65,12 @@ static void TestMimeEnum() { wxFileType *filetype = mimeTM.GetFileTypeFromMimeType(mimetypes[n]); if ( !filetype ) + { + printf("nothing known about the filetype '%s'!\n", + mimetypes[n].c_str()); continue; + } + filetype->GetDescription(&desc); filetype->GetExtensions(exts); diff --git a/samples/dialogs/dialogs.cpp b/samples/dialogs/dialogs.cpp index 06adc34fb2..552de089ff 100644 --- a/samples/dialogs/dialogs.cpp +++ b/samples/dialogs/dialogs.cpp @@ -75,18 +75,19 @@ bool MyApp::OnInit(void) #endif file_menu->AppendSeparator(); - file_menu->Append(DIALOGS_MESSAGE_BOX, "&Message box"); - file_menu->Append(DIALOGS_TEXT_ENTRY, "Text &entry"); + file_menu->Append(DIALOGS_MESSAGE_BOX, "&Message box\tCtrl-M"); + file_menu->Append(DIALOGS_TEXT_ENTRY, "Text &entry\tCtrl-E"); file_menu->Append(DIALOGS_NUM_ENTRY, "&Numeric entry\tCtrl-N"); - file_menu->Append(DIALOGS_SINGLE_CHOICE, "&Single choice"); + file_menu->Append(DIALOGS_SINGLE_CHOICE, "&Single choice\tCtrl-S"); file_menu->AppendSeparator(); - file_menu->Append(DIALOGS_TIP, "&Tip of the day"); + file_menu->Append(DIALOGS_TIP, "&Tip of the day\tCtrl-T"); file_menu->AppendSeparator(); - file_menu->Append(DIALOGS_FILE_OPEN, "&Open file"); + file_menu->Append(DIALOGS_FILE_OPEN, "&Open file\tCtrl-O"); + file_menu->Append(DIALOGS_FILES_OPEN, "&Open files\tCtrl-Q"); file_menu->Append(DIALOGS_FILE_SAVE, "Sa&ve file"); - file_menu->Append(DIALOGS_DIR_CHOOSE, "&Choose a directory"); + file_menu->Append(DIALOGS_DIR_CHOOSE, "&Choose a directory\tCtrl-D"); file_menu->AppendSeparator(); - file_menu->Append(wxID_EXIT, "E&xit"); + file_menu->Append(wxID_EXIT, "E&xit\tAlt-X"); wxMenuBar *menu_bar = new wxMenuBar; menu_bar->Append(file_menu, "&File"); frame->SetMenuBar(menu_bar); @@ -269,6 +270,33 @@ void MyFrame::FileOpen(wxCommandEvent& WXUNUSED(event) ) } } +void MyFrame::FilesOpen(wxCommandEvent& WXUNUSED(event) ) +{ + wxFileDialog dialog(this, "Testing open multiple file dialog", + "", "", "*.*", wxMULTIPLE); + + if (dialog.ShowModal() == wxID_OK) + { + wxArrayString paths, filenames; + + dialog.GetPaths(paths); + dialog.GetFilenames(filenames); + + wxString msg, s; + size_t count = paths.GetCount(); + for ( size_t n = 0; n < count; n++ ) + { + s.Printf(_T("File %d: %s (%s)\n"), + n, paths[n].c_str(), filenames[n].c_str()); + + msg += s; + } + + wxMessageDialog dialog2(this, msg, "Selected files"); + dialog2.ShowModal(); + } +} + void MyFrame::FileSave(wxCommandEvent& WXUNUSED(event) ) { wxFileDialog dialog(this, "Testing save file dialog", "", "myletter.txt", @@ -354,6 +382,7 @@ BEGIN_EVENT_TABLE(MyFrame, wxFrame) EVT_MENU(DIALOGS_NUM_ENTRY, MyFrame::NumericEntry) EVT_MENU(DIALOGS_SINGLE_CHOICE, MyFrame::SingleChoice) EVT_MENU(DIALOGS_FILE_OPEN, MyFrame::FileOpen) + EVT_MENU(DIALOGS_FILES_OPEN, MyFrame::FilesOpen) EVT_MENU(DIALOGS_FILE_SAVE, MyFrame::FileSave) EVT_MENU(DIALOGS_DIR_CHOOSE, MyFrame::DirChoose) EVT_MENU(DIALOGS_TIP, MyFrame::ShowTip) diff --git a/samples/dialogs/dialogs.h b/samples/dialogs/dialogs.h index 9c0cc248f5..a45fcd828d 100644 --- a/samples/dialogs/dialogs.h +++ b/samples/dialogs/dialogs.h @@ -36,6 +36,7 @@ public: void TextEntry(wxCommandEvent& event); void NumericEntry(wxCommandEvent& event); void FileOpen(wxCommandEvent& event); + void FilesOpen(wxCommandEvent& event); void FileSave(wxCommandEvent& event); void DirChoose(wxCommandEvent& event); void ShowTip(wxCommandEvent& event); @@ -70,9 +71,10 @@ public: #define DIALOGS_SINGLE_CHOICE 6 #define DIALOGS_TEXT_ENTRY 7 #define DIALOGS_FILE_OPEN 8 -#define DIALOGS_FILE_SAVE 9 -#define DIALOGS_DIR_CHOOSE 10 -#define DIALOGS_TIP 11 +#define DIALOGS_FILES_OPEN 9 +#define DIALOGS_FILE_SAVE 10 +#define DIALOGS_DIR_CHOOSE 11 +#define DIALOGS_TIP 12 #define DIALOGS_NUM_ENTRY 13 #endif diff --git a/src/common/mimetype.cpp b/src/common/mimetype.cpp index 0100ef9217..f3a4c6bd64 100644 --- a/src/common/mimetype.cpp +++ b/src/common/mimetype.cpp @@ -119,8 +119,8 @@ private: // we use either m_info or read the data from the registry if m_info == NULL const wxFileTypeInfo *m_info; - wxString m_strFileType, - m_ext; + wxString m_strFileType, // may be empty + m_ext; }; WX_DECLARE_EXPORTED_OBJARRAY(wxFileTypeInfo, wxArrayFileTypeInfo); @@ -670,9 +670,20 @@ wxString wxFileTypeImpl::GetCommand(const wxChar *verb) const // suppress possible error messages wxLogNull nolog; wxString strKey; - strKey << m_strFileType << wxT("\\shell\\") << verb << wxT("\\command"); - wxRegKey key(wxRegKey::HKCR, strKey); + if ( wxRegKey(wxRegKey::HKCR, m_ext + _T("\\shell")).Exists() ) + strKey = m_ext; + if ( wxRegKey(wxRegKey::HKCR, m_strFileType + _T("\\shell")).Exists() ) + strKey = m_strFileType; + + if ( !strKey ) + { + // no info + return wxEmptyString; + } + + strKey << wxT("\\shell\\") << verb << wxT("\\command"); + wxRegKey key(wxRegKey::HKCR, strKey); wxString command; if ( key.Open() ) { // it's the default value of the key @@ -701,8 +712,8 @@ wxString wxFileTypeImpl::GetCommand(const wxChar *verb) const } } } + //else: no such file type or no value, will return empty string - // no such file type or no value return command; } @@ -775,7 +786,7 @@ bool wxFileTypeImpl::GetMimeType(wxString *mimeType) const // suppress possible error messages wxLogNull nolog; - wxRegKey key(wxRegKey::HKCR, /*m_strFileType*/ wxT(".") + m_ext); + wxRegKey key(wxRegKey::HKCR, wxT(".") + m_ext); if ( key.Open() && key.QueryValue(wxT("Content Type"), *mimeType) ) { return TRUE; } @@ -877,6 +888,8 @@ wxMimeTypesManagerImpl::GetFileTypeFromExtension(const wxString& ext) // suppress possible error messages wxLogNull nolog; + bool knownExtension = FALSE; + wxString strFileType; wxRegKey key(wxRegKey::HKCR, str); if ( key.Open() ) { @@ -888,6 +901,12 @@ wxMimeTypesManagerImpl::GetFileTypeFromExtension(const wxString& ext) return fileType; } + else { + // this extension doesn't have a filetype, but it's known to the + // system and may be has some other useful keys (open command or + // content-type), so still return a file type object for it + knownExtension = TRUE; + } } // check the fallbacks @@ -903,8 +922,18 @@ wxMimeTypesManagerImpl::GetFileTypeFromExtension(const wxString& ext) } } - // unknown extension - return NULL; + if ( knownExtension ) + { + wxFileType *fileType = new wxFileType; + fileType->m_impl->Init(wxEmptyString, ext); + + return fileType; + } + else + { + // unknown extension + return NULL; + } } // MIME type -> extension -> file type diff --git a/src/msw/filedlg.cpp b/src/msw/filedlg.cpp index acdf6567db..ba1869e1c5 100644 --- a/src/msw/filedlg.cpp +++ b/src/msw/filedlg.cpp @@ -180,15 +180,32 @@ wxFileDialog::wxFileDialog(wxWindow *parent, const wxString& message, { m_message = message; m_dialogStyle = style; + if ( ( m_dialogStyle & wxMULTIPLE ) && ( m_dialogStyle & wxSAVE ) ) + m_dialogStyle &= ~wxMULTIPLE; m_parent = parent; m_path = wxT(""); m_fileName = defaultFileName; m_dir = defaultDir; m_wildCard = wildCard; - m_filterIndex = 0; + m_filterIndex = 1; } -int wxFileDialog::ShowModal(void) +void wxFileDialog::GetPaths(wxArrayString& paths) const +{ + paths.Empty(); + + wxString dir(m_dir); + if ( m_dir.Last() != _T('\\') ) + dir += _T('\\'); + + size_t count = m_fileNames.GetCount(); + for ( size_t n = 0; n < count; n++ ) + { + paths.Add(dir + m_fileNames[n]); + } +} + +int wxFileDialog::ShowModal() { HWND hWnd = 0; if (m_parent) hWnd = (HWND) m_parent->GetHWND(); @@ -204,6 +221,12 @@ int wxFileDialog::ShowModal(void) msw_flags |= OFN_HIDEREADONLY; if ( m_dialogStyle & wxFILE_MUST_EXIST ) msw_flags |= OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST; + if (m_dialogStyle & wxMULTIPLE ) + msw_flags |= +#if defined(OFN_EXPLORER) + OFN_EXPLORER | +#endif // OFN_EXPLORER + OFN_ALLOWMULTISELECT; OPENFILENAME of; memset(&of, 0, sizeof(OPENFILENAME)); @@ -274,7 +297,7 @@ int wxFileDialog::ShowModal(void) } of.lpstrFilter = (LPTSTR)(const wxChar *)filterBuffer; - of.nFilterIndex = m_filterIndex + 1; // m_filterIndex is zero-based, but nFilterIndex is 1-based + of.nFilterIndex = m_filterIndex; //=== Setting defaultFileName >>========================================= @@ -291,42 +314,84 @@ int wxFileDialog::ShowModal(void) if ( success ) { - const wxChar* extension = NULL; + m_fileNames.Empty(); + + if ( ( m_dialogStyle & wxMULTIPLE ) && +#if defined(OFN_EXPLORER) + ( fileNameBuffer[of.nFileOffset-1] == wxT('\0') ) ) +#else + ( fileNameBuffer[of.nFileOffset-1] == wxT(' ') ) ) +#endif // OFN_EXPLORER + { +#if defined(OFN_EXPLORER) + m_dir = fileNameBuffer; + i = of.nFileOffset; + m_fileName = &fileNameBuffer[i]; + m_fileNames.Add(m_fileName); + i += m_fileName.Len() + 1; + + while (fileNameBuffer[i] != wxT('\0')) + { + m_fileNames.Add(&fileNameBuffer[i]); + i += wxStrlen(&fileNameBuffer[i]) + 1; + } +#else + wxStringTokenizer toke(fileNameBuffer, " \t\r\n"); + m_dir = toke.GetNextToken(); + m_fileName = toke.GetNextToken(); + m_fileNames.Add(m_fileName); + + while (toke.HasMoreTokens()) + m_fileNames.Add(toke.GetNextToken()); +#endif // OFN_EXPLORER + + wxString dir(m_dir); + if ( m_dir.Last() != _T('\\') ) + dir += _T('\\'); + + m_fileNames.Sort(); + m_path = dir + m_fileName; + } + else + { + const wxChar* extension = NULL; - //=== Adding the correct extension >>================================= + //=== Adding the correct extension >>================================= - m_filterIndex = wxMax((int)of.nFilterIndex - 1, 0); + m_filterIndex = (int)of.nFilterIndex; - if ( of.nFileExtension && fileNameBuffer[ of.nFileExtension-1] != wxT('.') ) - { // user has typed an filename - // without an extension: + if ( of.nFileExtension && fileNameBuffer[ of.nFileExtension-1] != wxT('.') ) + { // user has typed an filename + // without an extension: - int maxFilter = (int)(of.nFilterIndex*2L-1L); - extension = filterBuffer; + int maxFilter = (int)(of.nFilterIndex*2L-1L); + extension = filterBuffer; - for( int i = 0; i < maxFilter; i++ ) { // get extension - extension = extension + wxStrlen( extension ) +1; - } + for( int i = 0; i < maxFilter; i++ ) { // get extension + extension = extension + wxStrlen( extension ) +1; + } - extension = wxStrrchr( extension, wxT('.') ); - if ( extension // != "blabla" - && !wxStrrchr( extension, wxT('*') ) // != "blabla.*" - && !wxStrrchr( extension, wxT('?') ) // != "blabla.?" - && extension[1] // != "blabla." - && extension[1] != wxT(' ') ) // != "blabla. " - { - // now concat extension to the fileName: - m_fileName = wxString(fileNameBuffer) + extension; + extension = wxStrrchr( extension, wxT('.') ); + if ( extension // != "blabla" + && !wxStrrchr( extension, wxT('*') ) // != "blabla.*" + && !wxStrrchr( extension, wxT('?') ) // != "blabla.?" + && extension[1] // != "blabla." + && extension[1] != wxT(' ') ) // != "blabla. " + { + // now concat extension to the fileName: + m_fileName = wxString(fileNameBuffer) + extension; - int len = wxStrlen( fileNameBuffer ); - wxStrncpy( fileNameBuffer + len, extension, MAXPATH - len ); - fileNameBuffer[ MAXPATH -1 ] = wxT('\0'); + int len = wxStrlen( fileNameBuffer ); + wxStrncpy( fileNameBuffer + len, extension, MAXPATH - len ); + fileNameBuffer[ MAXPATH -1 ] = wxT('\0'); + } } - } - m_path = fileNameBuffer; - m_fileName = wxFileNameFromPath(fileNameBuffer); - m_dir = wxPathOnly(fileNameBuffer); + m_path = fileNameBuffer; + m_fileName = wxFileNameFromPath(fileNameBuffer); + m_fileNames.Add(m_fileName); + m_dir = wxPathOnly(fileNameBuffer); + } //=== Simulating the wxOVERWRITE_PROMPT >>============================ @@ -405,3 +470,4 @@ WXDLLEXPORT wxString wxSaveFileSelector(const wxChar *what, return wxDefaultFileSelector(FALSE, what, extension, default_name, parent); } + -- 2.45.2