1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/gtk/filectrl.cpp
3 // Purpose: wxGtkFileCtrl Implementation
4 // Author: Diaa M. Sami
7 // Copyright: (c) Diaa M. Sami
8 // Licence: wxWindows licence
9 ///////////////////////////////////////////////////////////////////////////////
11 #include "wx/wxprec.h"
17 #if wxUSE_FILECTRL && !defined(__WXUNIVERSAL__)
19 #include "wx/filectrl.h"
21 #include "wx/gtk/private.h"
22 #include "wx/filename.h"
23 #include "wx/scopeguard.h"
24 #include "wx/tokenzr.h"
26 //-----------------------------------------------------------------------------
27 // wxGtkFileChooser implementation
28 //-----------------------------------------------------------------------------
30 void wxGtkFileChooser::SetWidget(GtkFileChooser
*w
)
34 wxASSERT( GTK_FILE_CHOOSER( w
) );
39 wxString
wxGtkFileChooser::GetPath() const
41 wxGtkString
str( gtk_file_chooser_get_filename( m_widget
) );
45 string
= wxString::FromUTF8(str
);
49 void wxGtkFileChooser::GetFilenames( wxArrayString
& files
) const
52 for ( size_t n
= 0; n
< files
.GetCount(); ++n
)
54 const wxFileName
file( files
[n
] );
55 files
[n
] = file
.GetFullName();
59 void wxGtkFileChooser::GetPaths( wxArrayString
& paths
) const
62 if ( gtk_file_chooser_get_select_multiple( m_widget
) )
64 GSList
*gpathsi
= gtk_file_chooser_get_filenames( m_widget
);
65 GSList
*gpaths
= gpathsi
;
68 wxString
file(wxString::FromUTF8(static_cast<gchar
*>(gpathsi
->data
)));
70 g_free( gpathsi
->data
);
71 gpathsi
= gpathsi
->next
;
74 g_slist_free( gpaths
);
77 paths
.Add( GetPath() );
80 bool wxGtkFileChooser::SetPath( const wxString
& path
)
85 return gtk_file_chooser_set_filename( m_widget
, path
.utf8_str() ) != 0;
88 bool wxGtkFileChooser::SetDirectory( const wxString
& dir
)
90 return gtk_file_chooser_set_current_folder( m_widget
, dir
.utf8_str() ) != 0;
93 wxString
wxGtkFileChooser::GetDirectory() const
95 const wxGtkString
str( gtk_file_chooser_get_current_folder( m_widget
) );
96 return wxString::FromUTF8(str
);
99 wxString
wxGtkFileChooser::GetFilename() const
101 return wxFileName( GetPath() ).GetFullName();
104 void wxGtkFileChooser::SetWildcard( const wxString
& wildCard
)
109 wxArrayString wildDescriptions
, wildFilters
;
111 if ( !wxParseCommonDialogsFilter( wildCard
, wildDescriptions
, wildFilters
) )
113 wxFAIL_MSG( wxT( "wxGtkFileChooser::SetWildcard - bad wildcard string" ) );
117 // Parsing went fine. Set m_wildCard to be returned by wxGtkFileChooserBase::GetWildcard
118 GtkFileChooser
* chooser
= m_widget
;
120 // empty current filter list:
121 GSList
* ifilters
= gtk_file_chooser_list_filters( chooser
);
122 GSList
* filters
= ifilters
;
124 m_ignoreNextFilterEvent
= true;
125 wxON_BLOCK_EXIT_SET(m_ignoreNextFilterEvent
, false);
129 gtk_file_chooser_remove_filter( chooser
, GTK_FILE_FILTER( ifilters
->data
) );
130 ifilters
= ifilters
->next
;
132 g_slist_free( filters
);
134 if (!wildCard
.empty())
136 // add parsed to GtkChooser
137 for ( size_t n
= 0; n
< wildFilters
.GetCount(); ++n
)
139 GtkFileFilter
* filter
= gtk_file_filter_new();
141 gtk_file_filter_set_name( filter
, wxGTK_CONV_SYS( wildDescriptions
[n
] ) );
143 wxStringTokenizer
exttok( wildFilters
[n
], wxT( ";" ) );
146 while ( exttok
.HasMoreTokens() )
148 wxString token
= exttok
.GetNextToken();
149 gtk_file_filter_add_pattern( filter
, wxGTK_CONV_SYS( token
) );
152 m_wildcards
.Add( token
); // Only add first pattern to list, used later when saving
156 gtk_file_chooser_add_filter( chooser
, filter
);
159 // Reset the filter index
165 void wxGtkFileChooser::SetFilterIndex( int filterIndex
)
168 GtkFileChooser
*chooser
= m_widget
;
169 GSList
*filters
= gtk_file_chooser_list_filters( chooser
);
171 filter
= g_slist_nth_data( filters
, filterIndex
);
173 if ( filter
!= NULL
)
175 gtk_file_chooser_set_filter( chooser
, GTK_FILE_FILTER( filter
) );
179 wxFAIL_MSG( wxT( "wxGtkFileChooser::SetFilterIndex - bad filter index" ) );
182 g_slist_free( filters
);
185 int wxGtkFileChooser::GetFilterIndex() const
187 GtkFileChooser
*chooser
= m_widget
;
188 GtkFileFilter
*filter
= gtk_file_chooser_get_filter( chooser
);
189 GSList
*filters
= gtk_file_chooser_list_filters( chooser
);
190 const gint index
= g_slist_index( filters
, filter
);
191 g_slist_free( filters
);
195 wxFAIL_MSG( wxT( "wxGtkFileChooser::GetFilterIndex - bad filter index returned by gtk+" ) );
202 bool wxGtkFileChooser::HasFilterChoice() const
204 return gtk_file_chooser_get_filter( m_widget
) != NULL
;
207 //-----------------------------------------------------------------------------
208 // end wxGtkFileChooser Implementation
209 //-----------------------------------------------------------------------------
213 // gtk signal handlers
218 gtkfilechooserwidget_file_activated_callback( GtkWidget
*WXUNUSED( widget
), wxGtkFileCtrl
*fileCtrl
)
220 GenerateFileActivatedEvent( fileCtrl
, fileCtrl
);
227 gtkfilechooserwidget_selection_changed_callback( GtkWidget
*WXUNUSED( widget
), wxGtkFileCtrl
*fileCtrl
)
229 // check next selection event and ignore it if it has 0 files
230 // because such events are redundantly generated by gtk.
231 if ( fileCtrl
->m_checkNextSelEvent
)
233 wxArrayString filenames
;
234 fileCtrl
->GetFilenames( filenames
);
236 if ( filenames
.Count() != 0 )
237 fileCtrl
->m_checkNextSelEvent
= false;
240 if ( !fileCtrl
->m_checkNextSelEvent
)
241 GenerateSelectionChangedEvent( fileCtrl
, fileCtrl
);
248 gtkfilechooserwidget_folder_changed_callback( GtkWidget
*WXUNUSED( widget
), wxGtkFileCtrl
*fileCtrl
)
250 if ( fileCtrl
->m_ignoreNextFolderChangeEvent
)
252 fileCtrl
->m_ignoreNextFolderChangeEvent
= false;
256 GenerateFolderChangedEvent( fileCtrl
, fileCtrl
);
259 fileCtrl
->m_checkNextSelEvent
= true;
266 gtkfilechooserwidget_notify_callback( GObject
*WXUNUSED( gobject
), GParamSpec
*arg1
, wxGtkFileCtrl
*fileCtrl
)
268 const char *name
= g_param_spec_get_name (arg1
);
269 if ( strcmp( name
, "filter" ) == 0 &&
270 fileCtrl
->HasFilterChoice() &&
271 !fileCtrl
->GTKShouldIgnoreNextFilterEvent() )
273 GenerateFilterChangedEvent( fileCtrl
, fileCtrl
);
278 // wxGtkFileCtrl implementation
280 IMPLEMENT_DYNAMIC_CLASS( wxGtkFileCtrl
, wxControl
)
282 wxGtkFileCtrl::~wxGtkFileCtrl()
285 GTKDisconnect(m_fcWidget
);
288 void wxGtkFileCtrl::Init()
290 m_checkNextSelEvent
= false;
292 // ignore the first folder change event which is fired upon startup.
293 m_ignoreNextFolderChangeEvent
= true;
296 bool wxGtkFileCtrl::Create( wxWindow
*parent
,
298 const wxString
& defaultDirectory
,
299 const wxString
& defaultFileName
,
300 const wxString
& wildCard
,
304 const wxString
& name
)
306 if ( !PreCreation( parent
, pos
, size
) ||
307 !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
) )
309 wxFAIL_MSG( wxT( "wxGtkFileCtrl creation failed" ) );
313 GtkFileChooserAction gtkAction
= GTK_FILE_CHOOSER_ACTION_OPEN
;
315 if ( style
& wxFC_SAVE
)
316 gtkAction
= GTK_FILE_CHOOSER_ACTION_SAVE
;
318 m_widget
= gtk_alignment_new ( 0, 0, 1, 1 );
319 g_object_ref(m_widget
);
320 m_fcWidget
= GTK_FILE_CHOOSER( gtk_file_chooser_widget_new(gtkAction
) );
321 gtk_widget_show ( GTK_WIDGET( m_fcWidget
) );
322 gtk_container_add ( GTK_CONTAINER ( m_widget
), GTK_WIDGET( m_fcWidget
) );
324 m_focusWidget
= GTK_WIDGET( m_fcWidget
);
326 g_signal_connect ( m_fcWidget
, "file-activated",
327 G_CALLBACK ( gtkfilechooserwidget_file_activated_callback
),
330 g_signal_connect ( m_fcWidget
, "current-folder-changed",
331 G_CALLBACK ( gtkfilechooserwidget_folder_changed_callback
),
334 g_signal_connect ( m_fcWidget
, "selection-changed",
335 G_CALLBACK ( gtkfilechooserwidget_selection_changed_callback
),
338 g_signal_connect ( m_fcWidget
, "notify",
339 G_CALLBACK ( gtkfilechooserwidget_notify_callback
),
342 m_fc
.SetWidget( m_fcWidget
);
344 if ( style
& wxFC_MULTIPLE
)
345 gtk_file_chooser_set_select_multiple( m_fcWidget
, true );
347 SetWildcard( wildCard
);
349 // if defaultDir is specified it should contain the directory and
350 // defaultFileName should contain the default name of the file, however if
351 // directory is not given, defaultFileName contains both
353 if ( defaultDirectory
.empty() )
354 fn
.Assign( defaultFileName
);
355 else if ( !defaultFileName
.empty() )
356 fn
.Assign( defaultDirectory
, defaultFileName
);
358 fn
.AssignDir( defaultDirectory
);
360 // set the initial file name and/or directory
361 const wxString dir
= fn
.GetPath();
364 gtk_file_chooser_set_current_folder( m_fcWidget
,
365 wxGTK_CONV_FN(dir
) );
368 const wxString fname
= fn
.GetFullName();
369 if ( style
& wxFC_SAVE
)
371 if ( !fname
.empty() )
373 gtk_file_chooser_set_current_name( m_fcWidget
,
374 wxGTK_CONV_FN(fname
) );
379 if ( !fname
.empty() )
381 gtk_file_chooser_set_filename( m_fcWidget
,
382 wxGTK_CONV_FN(fn
.GetFullPath()) );
386 m_parent
->DoAddChild( this );
388 PostCreation( size
);
393 bool wxGtkFileCtrl::SetPath( const wxString
& path
)
395 return m_fc
.SetPath( path
);
398 bool wxGtkFileCtrl::SetDirectory( const wxString
& dir
)
400 return m_fc
.SetDirectory( dir
);
403 bool wxGtkFileCtrl::SetFilename( const wxString
& name
)
405 if ( HasFlag( wxFC_SAVE
) )
407 gtk_file_chooser_set_current_name( m_fcWidget
, wxGTK_CONV( name
) );
411 return SetPath( wxFileName( GetDirectory(), name
).GetFullPath() );
414 void wxGtkFileCtrl::SetWildcard( const wxString
& wildCard
)
416 m_wildCard
= wildCard
;
418 m_fc
.SetWildcard( wildCard
);
421 void wxGtkFileCtrl::SetFilterIndex( int filterIndex
)
423 m_fc
.SetFilterIndex( filterIndex
);
426 wxString
wxGtkFileCtrl::GetPath() const
428 return m_fc
.GetPath();
431 void wxGtkFileCtrl::GetPaths( wxArrayString
& paths
) const
433 m_fc
.GetPaths( paths
);
436 wxString
wxGtkFileCtrl::GetDirectory() const
438 return m_fc
.GetDirectory();
441 wxString
wxGtkFileCtrl::GetFilename() const
443 return m_fc
.GetFilename();
446 void wxGtkFileCtrl::GetFilenames( wxArrayString
& files
) const
448 m_fc
.GetFilenames( files
);
451 void wxGtkFileCtrl::ShowHidden(bool show
)
453 gtk_file_chooser_set_show_hidden(m_fcWidget
, show
);
456 #endif // wxUSE_FILECTRL
458 #endif // wxUSE_FILECTRL && !defined(__WXUNIVERSAL__)