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 switch ( gtk_file_chooser_get_action( m_widget
) )
87 case GTK_FILE_CHOOSER_ACTION_SAVE
:
91 const wxString fname
= fn
.GetFullName();
92 gtk_file_chooser_set_current_name( m_widget
, fname
.utf8_str() );
94 // set the initial file name and/or directory
95 const wxString dir
= fn
.GetPath();
96 return gtk_file_chooser_set_current_folder( m_widget
,
97 dir
.utf8_str() ) != 0;
100 case GTK_FILE_CHOOSER_ACTION_OPEN
:
101 return gtk_file_chooser_set_filename( m_widget
, path
.utf8_str() ) != 0;
103 case GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER
:
104 case GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER
:
108 wxFAIL_MSG( "Unexpected file chooser type" );
113 bool wxGtkFileChooser::SetDirectory( const wxString
& dir
)
115 return gtk_file_chooser_set_current_folder( m_widget
, dir
.utf8_str() ) != 0;
118 wxString
wxGtkFileChooser::GetDirectory() const
120 const wxGtkString
str( gtk_file_chooser_get_current_folder( m_widget
) );
121 return wxString::FromUTF8(str
);
124 wxString
wxGtkFileChooser::GetFilename() const
126 return wxFileName( GetPath() ).GetFullName();
129 void wxGtkFileChooser::SetWildcard( const wxString
& wildCard
)
134 wxArrayString wildDescriptions
, wildFilters
;
136 if ( !wxParseCommonDialogsFilter( wildCard
, wildDescriptions
, wildFilters
) )
138 wxFAIL_MSG( wxT( "wxGtkFileChooser::SetWildcard - bad wildcard string" ) );
142 // Parsing went fine. Set m_wildCard to be returned by wxGtkFileChooserBase::GetWildcard
143 GtkFileChooser
* chooser
= m_widget
;
145 // empty current filter list:
146 GSList
* ifilters
= gtk_file_chooser_list_filters( chooser
);
147 GSList
* filters
= ifilters
;
149 m_ignoreNextFilterEvent
= true;
150 wxON_BLOCK_EXIT_SET(m_ignoreNextFilterEvent
, false);
154 gtk_file_chooser_remove_filter( chooser
, GTK_FILE_FILTER( ifilters
->data
) );
155 ifilters
= ifilters
->next
;
157 g_slist_free( filters
);
159 if (!wildCard
.empty())
161 // add parsed to GtkChooser
162 for ( size_t n
= 0; n
< wildFilters
.GetCount(); ++n
)
164 GtkFileFilter
* filter
= gtk_file_filter_new();
166 gtk_file_filter_set_name( filter
, wxGTK_CONV_SYS( wildDescriptions
[n
] ) );
168 wxStringTokenizer
exttok( wildFilters
[n
], wxT( ";" ) );
171 while ( exttok
.HasMoreTokens() )
173 wxString token
= exttok
.GetNextToken();
174 gtk_file_filter_add_pattern( filter
, wxGTK_CONV_SYS( token
) );
177 m_wildcards
.Add( token
); // Only add first pattern to list, used later when saving
181 gtk_file_chooser_add_filter( chooser
, filter
);
184 // Reset the filter index
190 void wxGtkFileChooser::SetFilterIndex( int filterIndex
)
193 GtkFileChooser
*chooser
= m_widget
;
194 GSList
*filters
= gtk_file_chooser_list_filters( chooser
);
196 filter
= g_slist_nth_data( filters
, filterIndex
);
198 if ( filter
!= NULL
)
200 gtk_file_chooser_set_filter( chooser
, GTK_FILE_FILTER( filter
) );
204 wxFAIL_MSG( wxT( "wxGtkFileChooser::SetFilterIndex - bad filter index" ) );
207 g_slist_free( filters
);
210 int wxGtkFileChooser::GetFilterIndex() const
212 GtkFileChooser
*chooser
= m_widget
;
213 GtkFileFilter
*filter
= gtk_file_chooser_get_filter( chooser
);
214 GSList
*filters
= gtk_file_chooser_list_filters( chooser
);
215 const gint index
= g_slist_index( filters
, filter
);
216 g_slist_free( filters
);
220 wxFAIL_MSG( wxT( "wxGtkFileChooser::GetFilterIndex - bad filter index returned by gtk+" ) );
227 bool wxGtkFileChooser::HasFilterChoice() const
229 return gtk_file_chooser_get_filter( m_widget
) != NULL
;
232 //-----------------------------------------------------------------------------
233 // end wxGtkFileChooser Implementation
234 //-----------------------------------------------------------------------------
238 // gtk signal handlers
243 gtkfilechooserwidget_file_activated_callback( GtkWidget
*WXUNUSED( widget
), wxGtkFileCtrl
*fileCtrl
)
245 GenerateFileActivatedEvent( fileCtrl
, fileCtrl
);
252 gtkfilechooserwidget_selection_changed_callback( GtkWidget
*WXUNUSED( widget
), wxGtkFileCtrl
*fileCtrl
)
254 // check next selection event and ignore it if it has 0 files
255 // because such events are redundantly generated by gtk.
256 if ( fileCtrl
->m_checkNextSelEvent
)
258 wxArrayString filenames
;
259 fileCtrl
->GetFilenames( filenames
);
261 if ( filenames
.Count() != 0 )
262 fileCtrl
->m_checkNextSelEvent
= false;
265 if ( !fileCtrl
->m_checkNextSelEvent
)
266 GenerateSelectionChangedEvent( fileCtrl
, fileCtrl
);
273 gtkfilechooserwidget_folder_changed_callback( GtkWidget
*WXUNUSED( widget
), wxGtkFileCtrl
*fileCtrl
)
275 if ( fileCtrl
->m_ignoreNextFolderChangeEvent
)
277 fileCtrl
->m_ignoreNextFolderChangeEvent
= false;
281 GenerateFolderChangedEvent( fileCtrl
, fileCtrl
);
284 fileCtrl
->m_checkNextSelEvent
= true;
291 gtkfilechooserwidget_notify_callback( GObject
*WXUNUSED( gobject
), GParamSpec
*arg1
, wxGtkFileCtrl
*fileCtrl
)
293 const char *name
= g_param_spec_get_name (arg1
);
294 if ( strcmp( name
, "filter" ) == 0 &&
295 fileCtrl
->HasFilterChoice() &&
296 !fileCtrl
->GTKShouldIgnoreNextFilterEvent() )
298 GenerateFilterChangedEvent( fileCtrl
, fileCtrl
);
303 // wxGtkFileCtrl implementation
305 IMPLEMENT_DYNAMIC_CLASS( wxGtkFileCtrl
, wxControl
)
307 wxGtkFileCtrl::~wxGtkFileCtrl()
310 GTKDisconnect(m_fcWidget
);
313 void wxGtkFileCtrl::Init()
315 m_checkNextSelEvent
= false;
317 // ignore the first folder change event which is fired upon startup.
318 m_ignoreNextFolderChangeEvent
= true;
321 bool wxGtkFileCtrl::Create( wxWindow
*parent
,
323 const wxString
& defaultDirectory
,
324 const wxString
& defaultFileName
,
325 const wxString
& wildCard
,
329 const wxString
& name
)
331 if ( !PreCreation( parent
, pos
, size
) ||
332 !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name
) )
334 wxFAIL_MSG( wxT( "wxGtkFileCtrl creation failed" ) );
338 GtkFileChooserAction gtkAction
= GTK_FILE_CHOOSER_ACTION_OPEN
;
340 if ( style
& wxFC_SAVE
)
341 gtkAction
= GTK_FILE_CHOOSER_ACTION_SAVE
;
343 m_widget
= gtk_alignment_new ( 0, 0, 1, 1 );
344 g_object_ref(m_widget
);
345 m_fcWidget
= GTK_FILE_CHOOSER( gtk_file_chooser_widget_new(gtkAction
) );
346 gtk_widget_show ( GTK_WIDGET( m_fcWidget
) );
347 gtk_container_add ( GTK_CONTAINER ( m_widget
), GTK_WIDGET( m_fcWidget
) );
349 m_focusWidget
= GTK_WIDGET( m_fcWidget
);
351 g_signal_connect ( m_fcWidget
, "file-activated",
352 G_CALLBACK ( gtkfilechooserwidget_file_activated_callback
),
355 g_signal_connect ( m_fcWidget
, "current-folder-changed",
356 G_CALLBACK ( gtkfilechooserwidget_folder_changed_callback
),
359 g_signal_connect ( m_fcWidget
, "selection-changed",
360 G_CALLBACK ( gtkfilechooserwidget_selection_changed_callback
),
363 g_signal_connect ( m_fcWidget
, "notify",
364 G_CALLBACK ( gtkfilechooserwidget_notify_callback
),
367 m_fc
.SetWidget( m_fcWidget
);
369 if ( style
& wxFC_MULTIPLE
)
370 gtk_file_chooser_set_select_multiple( m_fcWidget
, true );
372 SetWildcard( wildCard
);
374 // if defaultDir is specified it should contain the directory and
375 // defaultFileName should contain the default name of the file, however if
376 // directory is not given, defaultFileName contains both
378 if ( defaultDirectory
.empty() )
379 fn
.Assign( defaultFileName
);
380 else if ( !defaultFileName
.empty() )
381 fn
.Assign( defaultDirectory
, defaultFileName
);
383 fn
.AssignDir( defaultDirectory
);
385 // set the initial file name and/or directory
386 const wxString dir
= fn
.GetPath();
389 gtk_file_chooser_set_current_folder( m_fcWidget
,
390 wxGTK_CONV_FN(dir
) );
393 const wxString fname
= fn
.GetFullName();
394 if ( style
& wxFC_SAVE
)
396 if ( !fname
.empty() )
398 gtk_file_chooser_set_current_name( m_fcWidget
,
399 wxGTK_CONV_FN(fname
) );
404 if ( !fname
.empty() )
406 gtk_file_chooser_set_filename( m_fcWidget
,
407 wxGTK_CONV_FN(fn
.GetFullPath()) );
411 m_parent
->DoAddChild( this );
413 PostCreation( size
);
418 bool wxGtkFileCtrl::SetPath( const wxString
& path
)
420 return m_fc
.SetPath( path
);
423 bool wxGtkFileCtrl::SetDirectory( const wxString
& dir
)
425 return m_fc
.SetDirectory( dir
);
428 bool wxGtkFileCtrl::SetFilename( const wxString
& name
)
430 if ( HasFlag( wxFC_SAVE
) )
432 gtk_file_chooser_set_current_name( m_fcWidget
, wxGTK_CONV( name
) );
436 return SetPath( wxFileName( GetDirectory(), name
).GetFullPath() );
439 void wxGtkFileCtrl::SetWildcard( const wxString
& wildCard
)
441 m_wildCard
= wildCard
;
443 m_fc
.SetWildcard( wildCard
);
446 void wxGtkFileCtrl::SetFilterIndex( int filterIndex
)
448 m_fc
.SetFilterIndex( filterIndex
);
451 wxString
wxGtkFileCtrl::GetPath() const
453 return m_fc
.GetPath();
456 void wxGtkFileCtrl::GetPaths( wxArrayString
& paths
) const
458 m_fc
.GetPaths( paths
);
461 wxString
wxGtkFileCtrl::GetDirectory() const
463 return m_fc
.GetDirectory();
466 wxString
wxGtkFileCtrl::GetFilename() const
468 return m_fc
.GetFilename();
471 void wxGtkFileCtrl::GetFilenames( wxArrayString
& files
) const
473 m_fc
.GetFilenames( files
);
476 void wxGtkFileCtrl::ShowHidden(bool show
)
478 gtk_file_chooser_set_show_hidden(m_fcWidget
, show
);
481 #endif // wxUSE_FILECTRL
483 #endif // wxUSE_FILECTRL && !defined(__WXUNIVERSAL__)