1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/gtk/filectrl.cpp
3 // Purpose: wxGtkFileCtrl Implementation
4 // Author: Diaa M. Sami
6 // Copyright: (c) Diaa M. Sami
7 // Licence: wxWindows licence
8 ///////////////////////////////////////////////////////////////////////////////
10 #include "wx/wxprec.h"
16 #if wxUSE_FILECTRL && !defined(__WXUNIVERSAL__)
18 #include "wx/filectrl.h"
20 #include "wx/gtk/private.h"
21 #include "wx/filename.h"
22 #include "wx/scopeguard.h"
23 #include "wx/tokenzr.h"
25 //-----------------------------------------------------------------------------
26 // wxGtkFileChooser implementation
27 //-----------------------------------------------------------------------------
29 void wxGtkFileChooser::SetWidget(GtkFileChooser
*w
)
33 wxASSERT( GTK_FILE_CHOOSER( w
) );
38 wxString
wxGtkFileChooser::GetPath() const
40 wxGtkString
str( gtk_file_chooser_get_filename( m_widget
) );
44 string
= wxString::FromUTF8(str
);
48 void wxGtkFileChooser::GetFilenames( wxArrayString
& files
) const
51 for ( size_t n
= 0; n
< files
.GetCount(); ++n
)
53 const wxFileName
file( files
[n
] );
54 files
[n
] = file
.GetFullName();
58 void wxGtkFileChooser::GetPaths( wxArrayString
& paths
) const
61 if ( gtk_file_chooser_get_select_multiple( m_widget
) )
63 GSList
*gpathsi
= gtk_file_chooser_get_filenames( m_widget
);
64 GSList
*gpaths
= gpathsi
;
67 wxString
file(wxString::FromUTF8(static_cast<gchar
*>(gpathsi
->data
)));
69 g_free( gpathsi
->data
);
70 gpathsi
= gpathsi
->next
;
73 g_slist_free( gpaths
);
76 paths
.Add( GetPath() );
79 bool wxGtkFileChooser::SetPath( const wxString
& path
)
84 switch ( gtk_file_chooser_get_action( m_widget
) )
86 case GTK_FILE_CHOOSER_ACTION_SAVE
:
90 const wxString fname
= fn
.GetFullName();
91 gtk_file_chooser_set_current_name( m_widget
, fname
.utf8_str() );
93 // set the initial file name and/or directory
94 const wxString dir
= fn
.GetPath();
95 return gtk_file_chooser_set_current_folder( m_widget
,
96 dir
.utf8_str() ) != 0;
99 case GTK_FILE_CHOOSER_ACTION_OPEN
:
100 return gtk_file_chooser_set_filename( m_widget
, path
.utf8_str() ) != 0;
102 case GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER
:
103 case GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER
:
107 wxFAIL_MSG( "Unexpected file chooser type" );
112 bool wxGtkFileChooser::SetDirectory( const wxString
& dir
)
114 return gtk_file_chooser_set_current_folder( m_widget
, dir
.utf8_str() ) != 0;
117 wxString
wxGtkFileChooser::GetDirectory() const
119 const wxGtkString
str( gtk_file_chooser_get_current_folder( m_widget
) );
120 return wxString::FromUTF8(str
);
123 wxString
wxGtkFileChooser::GetFilename() const
125 return wxFileName( GetPath() ).GetFullName();
128 void wxGtkFileChooser::SetWildcard( const wxString
& wildCard
)
133 wxArrayString wildDescriptions
, wildFilters
;
135 if ( !wxParseCommonDialogsFilter( wildCard
, wildDescriptions
, wildFilters
) )
137 wxFAIL_MSG( wxT( "wxGtkFileChooser::SetWildcard - bad wildcard string" ) );
141 // Parsing went fine. Set m_wildCard to be returned by wxGtkFileChooserBase::GetWildcard
142 GtkFileChooser
* chooser
= m_widget
;
144 // empty current filter list:
145 GSList
* ifilters
= gtk_file_chooser_list_filters( chooser
);
146 GSList
* filters
= ifilters
;
148 m_ignoreNextFilterEvent
= true;
149 wxON_BLOCK_EXIT_SET(m_ignoreNextFilterEvent
, false);
153 gtk_file_chooser_remove_filter( chooser
, GTK_FILE_FILTER( ifilters
->data
) );
154 ifilters
= ifilters
->next
;
156 g_slist_free( filters
);
158 if (!wildCard
.empty())
160 // add parsed to GtkChooser
161 for ( size_t n
= 0; n
< wildFilters
.GetCount(); ++n
)
163 GtkFileFilter
* filter
= gtk_file_filter_new();
165 gtk_file_filter_set_name( filter
, wxGTK_CONV_SYS( wildDescriptions
[n
] ) );
167 wxStringTokenizer
exttok( wildFilters
[n
], wxT( ";" ) );
170 while ( exttok
.HasMoreTokens() )
172 wxString token
= exttok
.GetNextToken();
173 gtk_file_filter_add_pattern( filter
, wxGTK_CONV_SYS( token
) );
176 m_wildcards
.Add( token
); // Only add first pattern to list, used later when saving
180 gtk_file_chooser_add_filter( chooser
, filter
);
183 // Reset the filter index
189 void wxGtkFileChooser::SetFilterIndex( int filterIndex
)
192 GtkFileChooser
*chooser
= m_widget
;
193 GSList
*filters
= gtk_file_chooser_list_filters( chooser
);
195 filter
= g_slist_nth_data( filters
, filterIndex
);
197 if ( filter
!= NULL
)
199 gtk_file_chooser_set_filter( chooser
, GTK_FILE_FILTER( filter
) );
203 wxFAIL_MSG( wxT( "wxGtkFileChooser::SetFilterIndex - bad filter index" ) );
206 g_slist_free( filters
);
209 int wxGtkFileChooser::GetFilterIndex() const
211 GtkFileChooser
*chooser
= m_widget
;
212 GtkFileFilter
*filter
= gtk_file_chooser_get_filter( chooser
);
213 GSList
*filters
= gtk_file_chooser_list_filters( chooser
);
214 const gint index
= g_slist_index( filters
, filter
);
215 g_slist_free( filters
);
219 wxFAIL_MSG( wxT( "wxGtkFileChooser::GetFilterIndex - bad filter index returned by gtk+" ) );
226 bool wxGtkFileChooser::HasFilterChoice() const
228 return gtk_file_chooser_get_filter( m_widget
) != NULL
;
231 //-----------------------------------------------------------------------------
232 // end wxGtkFileChooser Implementation
233 //-----------------------------------------------------------------------------
237 // gtk signal handlers
242 gtkfilechooserwidget_file_activated_callback( GtkWidget
*WXUNUSED( widget
), wxGtkFileCtrl
*fileCtrl
)
244 GenerateFileActivatedEvent( fileCtrl
, fileCtrl
);
251 gtkfilechooserwidget_selection_changed_callback( GtkWidget
*WXUNUSED( widget
), wxGtkFileCtrl
*fileCtrl
)
253 // check next selection event and ignore it if it has 0 files
254 // because such events are redundantly generated by gtk.
255 if ( fileCtrl
->m_checkNextSelEvent
)
257 wxArrayString filenames
;
258 fileCtrl
->GetFilenames( filenames
);
260 if ( filenames
.Count() != 0 )
261 fileCtrl
->m_checkNextSelEvent
= false;
264 if ( !fileCtrl
->m_checkNextSelEvent
)
265 GenerateSelectionChangedEvent( fileCtrl
, fileCtrl
);
272 gtkfilechooserwidget_folder_changed_callback( GtkWidget
*WXUNUSED( widget
), wxGtkFileCtrl
*fileCtrl
)
274 if ( fileCtrl
->m_ignoreNextFolderChangeEvent
)
276 fileCtrl
->m_ignoreNextFolderChangeEvent
= false;
280 GenerateFolderChangedEvent( fileCtrl
, fileCtrl
);
283 fileCtrl
->m_checkNextSelEvent
= true;
290 gtkfilechooserwidget_notify_callback( GObject
*WXUNUSED( gobject
), GParamSpec
*arg1
, wxGtkFileCtrl
*fileCtrl
)
292 const char *name
= g_param_spec_get_name (arg1
);
293 if ( strcmp( name
, "filter" ) == 0 &&
294 fileCtrl
->HasFilterChoice() &&
295 !fileCtrl
->GTKShouldIgnoreNextFilterEvent() )
297 GenerateFilterChangedEvent( fileCtrl
, fileCtrl
);
302 // wxGtkFileCtrl implementation
304 IMPLEMENT_DYNAMIC_CLASS( wxGtkFileCtrl
, wxControl
)
306 wxGtkFileCtrl::~wxGtkFileCtrl()
309 GTKDisconnect(m_fcWidget
);
312 void wxGtkFileCtrl::Init()
314 m_checkNextSelEvent
= false;
316 // ignore the first folder change event which is fired upon startup.
317 m_ignoreNextFolderChangeEvent
= true;
320 bool wxGtkFileCtrl::Create( wxWindow
*parent
,
322 const wxString
& defaultDirectory
,
323 const wxString
& defaultFileName
,
324 const wxString
& wildCard
,
328 const wxString
& name
)
330 if ( !PreCreation( parent
, pos
, size
) ||
331 !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
) )
333 wxFAIL_MSG( wxT( "wxGtkFileCtrl creation failed" ) );
337 GtkFileChooserAction gtkAction
= GTK_FILE_CHOOSER_ACTION_OPEN
;
339 if ( style
& wxFC_SAVE
)
340 gtkAction
= GTK_FILE_CHOOSER_ACTION_SAVE
;
342 m_widget
= gtk_alignment_new ( 0, 0, 1, 1 );
343 g_object_ref(m_widget
);
344 m_fcWidget
= GTK_FILE_CHOOSER( gtk_file_chooser_widget_new(gtkAction
) );
345 gtk_widget_show ( GTK_WIDGET( m_fcWidget
) );
346 gtk_container_add ( GTK_CONTAINER ( m_widget
), GTK_WIDGET( m_fcWidget
) );
348 m_focusWidget
= GTK_WIDGET( m_fcWidget
);
350 g_signal_connect ( m_fcWidget
, "file-activated",
351 G_CALLBACK ( gtkfilechooserwidget_file_activated_callback
),
354 g_signal_connect ( m_fcWidget
, "current-folder-changed",
355 G_CALLBACK ( gtkfilechooserwidget_folder_changed_callback
),
358 g_signal_connect ( m_fcWidget
, "selection-changed",
359 G_CALLBACK ( gtkfilechooserwidget_selection_changed_callback
),
362 g_signal_connect ( m_fcWidget
, "notify",
363 G_CALLBACK ( gtkfilechooserwidget_notify_callback
),
366 m_fc
.SetWidget( m_fcWidget
);
368 if ( style
& wxFC_MULTIPLE
)
369 gtk_file_chooser_set_select_multiple( m_fcWidget
, true );
371 SetWildcard( wildCard
);
373 // if defaultDir is specified it should contain the directory and
374 // defaultFileName should contain the default name of the file, however if
375 // directory is not given, defaultFileName contains both
377 if ( defaultDirectory
.empty() )
378 fn
.Assign( defaultFileName
);
379 else if ( !defaultFileName
.empty() )
380 fn
.Assign( defaultDirectory
, defaultFileName
);
382 fn
.AssignDir( defaultDirectory
);
384 // set the initial file name and/or directory
385 const wxString dir
= fn
.GetPath();
388 gtk_file_chooser_set_current_folder( m_fcWidget
,
389 wxGTK_CONV_FN(dir
) );
392 const wxString fname
= fn
.GetFullName();
393 if ( style
& wxFC_SAVE
)
395 if ( !fname
.empty() )
397 gtk_file_chooser_set_current_name( m_fcWidget
,
398 wxGTK_CONV_FN(fname
) );
403 if ( !fname
.empty() )
405 gtk_file_chooser_set_filename( m_fcWidget
,
406 wxGTK_CONV_FN(fn
.GetFullPath()) );
410 m_parent
->DoAddChild( this );
412 PostCreation( size
);
417 bool wxGtkFileCtrl::SetPath( const wxString
& path
)
419 return m_fc
.SetPath( path
);
422 bool wxGtkFileCtrl::SetDirectory( const wxString
& dir
)
424 return m_fc
.SetDirectory( dir
);
427 bool wxGtkFileCtrl::SetFilename( const wxString
& name
)
429 if ( HasFlag( wxFC_SAVE
) )
431 gtk_file_chooser_set_current_name( m_fcWidget
, wxGTK_CONV( name
) );
435 return SetPath( wxFileName( GetDirectory(), name
).GetFullPath() );
438 void wxGtkFileCtrl::SetWildcard( const wxString
& wildCard
)
440 m_wildCard
= wildCard
;
442 m_fc
.SetWildcard( wildCard
);
445 void wxGtkFileCtrl::SetFilterIndex( int filterIndex
)
447 m_fc
.SetFilterIndex( filterIndex
);
450 wxString
wxGtkFileCtrl::GetPath() const
452 return m_fc
.GetPath();
455 void wxGtkFileCtrl::GetPaths( wxArrayString
& paths
) const
457 m_fc
.GetPaths( paths
);
460 wxString
wxGtkFileCtrl::GetDirectory() const
462 return m_fc
.GetDirectory();
465 wxString
wxGtkFileCtrl::GetFilename() const
467 return m_fc
.GetFilename();
470 void wxGtkFileCtrl::GetFilenames( wxArrayString
& files
) const
472 m_fc
.GetFilenames( files
);
475 void wxGtkFileCtrl::ShowHidden(bool show
)
477 gtk_file_chooser_set_show_hidden(m_fcWidget
, show
);
480 #endif // wxUSE_FILECTRL
482 #endif // wxUSE_FILECTRL && !defined(__WXUNIVERSAL__)