From f9e9b19c92204988cd536586dfb29cfc2c65e5fb Mon Sep 17 00:00:00 2001 From: Ian McInerney Date: Wed, 8 Jan 2020 19:51:00 +0000 Subject: [PATCH] Add wxDD_MULTIPLE wxDirDialog style and implement it for GTK Add wxDirDialog::GetPaths() similar to the existing member of wxFileDialog with the same name and also taking, for consistency, wxArrayString as the output parameter. --- include/wx/dirdlg.h | 14 ++++++++++++++ include/wx/gtk/dirdlg.h | 3 ++- interface/wx/dirdlg.h | 17 +++++++++++++++++ src/gtk/dirdlg.cpp | 35 ++++++++++++++++++++++++++++++----- 4 files changed, 63 insertions(+), 6 deletions(-) diff --git a/include/wx/dirdlg.h b/include/wx/dirdlg.h index dfdbffc737..a53efee977 100644 --- a/include/wx/dirdlg.h +++ b/include/wx/dirdlg.h @@ -25,8 +25,21 @@ extern WXDLLIMPEXP_DATA_CORE(const char) wxDirDialogNameStr[]; extern WXDLLIMPEXP_DATA_CORE(const char) wxDirDialogDefaultFolderStr[]; extern WXDLLIMPEXP_DATA_CORE(const char) wxDirSelectorPromptStr[]; + +/* + The flags below must coexist with the following flags in m_windowStyle + #define wxCAPTION 0x20000000 + #define wxMAXIMIZE 0x00002000 + #define wxCLOSE_BOX 0x00001000 + #define wxSYSTEM_MENU 0x00000800 + wxBORDER_NONE = 0x00200000 + #define wxRESIZE_BORDER 0x00000040 + #define wxDIALOG_NO_PARENT 0x00000020 +*/ + #define wxDD_CHANGE_DIR 0x0100 #define wxDD_DIR_MUST_EXIST 0x0200 +#define wxDD_MULTIPLE 0x0400 // deprecated, on by default now, use wxDD_DIR_MUST_EXIST to disable it #define wxDD_NEW_DIR_BUTTON 0 @@ -75,6 +88,7 @@ public: virtual wxString GetMessage() const { return m_message; } virtual wxString GetPath() const { return m_path; } + virtual void GetPaths(wxArrayString& paths) const { paths.Empty(); paths.Add(m_path); } protected: wxString m_message; diff --git a/include/wx/gtk/dirdlg.h b/include/wx/gtk/dirdlg.h index 1e4473ee66..d4b00cf0d8 100644 --- a/include/wx/gtk/dirdlg.h +++ b/include/wx/gtk/dirdlg.h @@ -39,6 +39,7 @@ public: // overrides from wxGenericDirDialog wxString GetPath() const wxOVERRIDE; void SetPath(const wxString& path) wxOVERRIDE; + void GetPaths(wxArrayString& paths) const wxOVERRIDE; // Implementation only. @@ -55,7 +56,7 @@ protected: private: - wxString m_selectedDirectory; + wxArrayString m_paths; wxDECLARE_DYNAMIC_CLASS(wxDirDialog); }; diff --git a/interface/wx/dirdlg.h b/interface/wx/dirdlg.h index 19d9827a9b..b5b638666c 100644 --- a/interface/wx/dirdlg.h +++ b/interface/wx/dirdlg.h @@ -7,6 +7,8 @@ #define wxDD_CHANGE_DIR 0x0100 #define wxDD_DIR_MUST_EXIST 0x0200 +#define wxDD_MULTIPLE 0x0400 + #define wxDD_NEW_DIR_BUTTON 0 // deprecated, on by default now, #define wxDD_DEFAULT_STYLE (wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER) @@ -43,6 +45,11 @@ const char wxDirDialogNameStr[] = "wxDirCtrl"; @style{wxDD_CHANGE_DIR} Change the current working directory to the directory chosen by the user. + @note This flag cannot be used with the @c wxDD_MULTIPLE style. + @style{wxDD_MULTIPLE} + Allow the user to select multiple directories. + This flag is only available since wxWidgets 3.1.4 + @endStyleTable Notice that @c wxRESIZE_BORDER has special side effect under Windows @@ -109,6 +116,16 @@ public: */ virtual wxString GetPath() const; + /** + Fills the array @a paths with the full paths of the chosen directories. + + @note This function should only be used with the dialogs which have @c wxDD_MULTIPLE style, + use GetPath() for the others. + + @since 3.1.4 + */ + virtual void GetPaths(wxArrayString& paths) const; + /** Sets the message that will be displayed on the dialog. */ diff --git a/src/gtk/dirdlg.cpp b/src/gtk/dirdlg.cpp index 005771a54e..88e352df3b 100644 --- a/src/gtk/dirdlg.cpp +++ b/src/gtk/dirdlg.cpp @@ -71,6 +71,9 @@ bool wxDirDialog::Create(wxWindow* parent, { m_message = title; + wxASSERT_MSG( !( (style & wxDD_MULTIPLE) && (style & wxDD_CHANGE_DIR) ), + "wxDD_CHANGE_DIR can't be used together with wxDD_MULTIPLE" ); + parent = GetParentForModalDialog(parent, style); if (!PreCreation(parent, pos, wxDefaultSize) || @@ -110,10 +113,15 @@ bool wxDirDialog::Create(wxWindow* parent, if (wx_is_at_least_gtk2(18)) { gtk_file_chooser_set_create_folders( - GTK_FILE_CHOOSER(m_widget), (style & wxDD_DIR_MUST_EXIST) == 0); + GTK_FILE_CHOOSER(m_widget), !HasFlag(wxDD_DIR_MUST_EXIST) ); } #endif + // Enable multiple selection if desired + gtk_file_chooser_set_select_multiple( + GTK_FILE_CHOOSER(m_widget), HasFlag(wxDD_MULTIPLE) ); + + // local-only property could be set to false to allow non-local files to be loaded. // In that case get/set_uri(s) should be used instead of get/set_filename(s) everywhere // and the GtkFileChooserDialog should probably also be created with a backend, @@ -132,13 +140,24 @@ bool wxDirDialog::Create(wxWindow* parent, void wxDirDialog::GTKOnAccept() { - wxGtkString str(gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(m_widget))); - m_selectedDirectory = wxString::FromUTF8(str); + GSList *fnamesi = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(m_widget)); + GSList *fnames = fnamesi; + + while ( fnamesi ) + { + wxString dir(wxString::FromUTF8(static_cast(fnamesi->data))); + m_paths.Add(dir); + + g_free(fnamesi->data); + fnamesi = fnamesi->next; + } + + g_slist_free(fnames); // change to the directory where the user went if asked if (HasFlag(wxDD_CHANGE_DIR)) { - wxSetWorkingDirectory(m_selectedDirectory); + wxSetWorkingDirectory(m_paths.Last()); } EndDialog(wxID_OK); @@ -168,7 +187,13 @@ void wxDirDialog::SetPath(const wxString& dir) wxString wxDirDialog::GetPath() const { - return m_selectedDirectory; + return m_paths.Last(); +} + +void wxDirDialog::GetPaths(wxArrayString& paths) const +{ + paths.Empty(); + paths = m_paths; } #endif // wxUSE_DIRDLG