fa3d8dc8c799405a79d1841bc995fd58975205cd
[wxWidgets.git] / src / gtk / filectrl.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/gtk/filectrl.cpp
3 // Purpose: wxGtkFileCtrl Implementation
4 // Author: Diaa M. Sami
5 // Created: 2007-08-10
6 // RCS-ID: $Id$
7 // Copyright: (c) Diaa M. Sami
8 // Licence: wxWindows licence
9 ///////////////////////////////////////////////////////////////////////////////
10
11 #include "wx/wxprec.h"
12
13 #ifdef __BORLANDC__
14 #pragma hdrstop
15 #endif
16
17 #include "wx/filectrl.h"
18
19 #ifndef WX_PRECOMP
20 # include "wx/sizer.h"
21 # include "wx/debug.h"
22 #endif
23
24 #include "wx/gtk/private.h"
25 #include "wx/filedlg.h"
26 #include "wx/filename.h"
27 #include "wx/tokenzr.h"
28
29 //-----------------------------------------------------------------------------
30 // wxGtkFileChooser implementation
31 //-----------------------------------------------------------------------------
32
33 void wxGtkFileChooser::SetWidget(GtkFileChooser *w)
34 {
35 // check arguments
36 wxASSERT( w );
37 wxASSERT( GTK_FILE_CHOOSER( w ) );
38
39 this->m_widget = w;
40 }
41
42 wxString wxGtkFileChooser::GetPath() const
43 {
44 wxGtkString str( gtk_file_chooser_get_filename( m_widget ) );
45
46 if ( str.c_str() == NULL )
47 return wxEmptyString;
48
49 return wxConvFileName->cMB2WX( str );
50 }
51
52 void wxGtkFileChooser::GetFilenames( wxArrayString& files ) const
53 {
54 GetPaths( files );
55 for ( size_t n = 0; n < files.GetCount(); ++n )
56 {
57 const wxFileName file( files[n] );
58 files[n] = file.GetFullName();
59 }
60 }
61
62 void wxGtkFileChooser::GetPaths( wxArrayString& paths ) const
63 {
64 paths.Empty();
65 if ( gtk_file_chooser_get_select_multiple( m_widget ) )
66 {
67 GSList *gpathsi = gtk_file_chooser_get_filenames( m_widget );
68 GSList *gpaths = gpathsi;
69 while ( gpathsi )
70 {
71 wxString file( wxConvFileName->cMB2WX( ( gchar* ) gpathsi->data ) );
72 paths.Add( file );
73 g_free( gpathsi->data );
74 gpathsi = gpathsi->next;
75 }
76
77 g_slist_free( gpaths );
78 }
79 else
80 paths.Add( GetPath() );
81 }
82
83 bool wxGtkFileChooser::SetPath( const wxString& path )
84 {
85 if ( path.empty() ) return true;
86
87 return gtk_file_chooser_set_filename( m_widget,
88 wxConvFileName->cWX2MB( path.c_str() ) );
89 }
90
91 bool wxGtkFileChooser::SetDirectory( const wxString& dir )
92 {
93 const gboolean b =
94 gtk_file_chooser_set_current_folder( m_widget,
95 wxConvFileName->cWX2MB( dir.c_str() ) );
96 return b == TRUE;
97 }
98
99 wxString wxGtkFileChooser::GetDirectory() const
100 {
101 const wxGtkString str( gtk_file_chooser_get_current_folder( m_widget ) );
102 return wxString( str, *wxConvFileName );
103 }
104
105 wxString wxGtkFileChooser::GetFilename() const
106 {
107 return wxFileName( GetPath() ).GetFullName();
108 }
109
110 void wxGtkFileChooser::SetWildcard( const wxString& wildCard )
111 {
112 // parse filters
113 wxArrayString wildDescriptions, wildFilters;
114
115 if ( !wxParseCommonDialogsFilter( wildCard, wildDescriptions, wildFilters ) )
116 {
117 wxFAIL_MSG( wxT( "wxGtkFileChooser::SetWildcard - bad wildcard string" ) );
118 }
119 else
120 {
121 // Parsing went fine. Set m_wildCard to be returned by wxGtkFileChooserBase::GetWildcard
122 GtkFileChooser* chooser = m_widget;
123
124 // empty current filter list:
125 GSList* ifilters = gtk_file_chooser_list_filters( chooser );
126 GSList* filters = ifilters;
127
128 while ( ifilters )
129 {
130 gtk_file_chooser_remove_filter( chooser, GTK_FILE_FILTER( ifilters->data ) );
131 ifilters = ifilters->next;
132 }
133 g_slist_free( filters );
134
135 if (!wildCard.empty())
136 {
137 // add parsed to GtkChooser
138 for ( size_t n = 0; n < wildFilters.GetCount(); ++n )
139 {
140 GtkFileFilter* filter = gtk_file_filter_new();
141
142 gtk_file_filter_set_name( filter, wxGTK_CONV_SYS( wildDescriptions[n] ) );
143
144 wxStringTokenizer exttok( wildFilters[n], wxT( ";" ) );
145 while ( exttok.HasMoreTokens() )
146 {
147 wxString token = exttok.GetNextToken();
148 gtk_file_filter_add_pattern( filter, wxGTK_CONV_SYS( token ) );
149 }
150
151 gtk_file_chooser_add_filter( chooser, filter );
152 }
153
154 // Reset the filter index
155 SetFilterIndex( 0 );
156 }
157 }
158 }
159
160 void wxGtkFileChooser::SetFilterIndex( int filterIndex )
161 {
162 gpointer filter;
163 GtkFileChooser *chooser = m_widget;
164 GSList *filters = gtk_file_chooser_list_filters( chooser );
165
166 filter = g_slist_nth_data( filters, filterIndex );
167
168 if ( filter != NULL )
169 {
170 gtk_file_chooser_set_filter( chooser, GTK_FILE_FILTER( filter ) );
171 }
172 else
173 {
174 wxFAIL_MSG( wxT( "wxGtkFileChooser::SetFilterIndex - bad filter index" ) );
175 }
176
177 g_slist_free( filters );
178 }
179
180 int wxGtkFileChooser::GetFilterIndex() const
181 {
182 GtkFileChooser *chooser = m_widget;
183 GtkFileFilter *filter = gtk_file_chooser_get_filter( chooser );
184 GSList *filters = gtk_file_chooser_list_filters( chooser );
185 const gint index = g_slist_index( filters, filter );
186 g_slist_free( filters );
187
188 if ( index == -1 )
189 {
190 wxFAIL_MSG( wxT( "wxGtkFileChooser::GetFilterIndex - bad filter index returned by gtk+" ) );
191 return 0;
192 }
193 else
194 return index;
195 };
196
197 //-----------------------------------------------------------------------------
198 // end wxGtkFileChooser Implementation
199 //-----------------------------------------------------------------------------
200
201 #if wxUSE_FILECTRL
202
203 // gtk signal handlers
204
205 extern "C"
206 {
207 static void
208 gtkfilechooserwidget_file_activated_callback( GtkWidget *WXUNUSED( widget ), wxGtkFileCtrl *fileCtrl )
209 {
210 GenerateFileActivatedEvent( fileCtrl, fileCtrl );
211 }
212 }
213
214 extern "C"
215 {
216 static void
217 gtkfilechooserwidget_selection_changed_callback( GtkWidget *WXUNUSED( widget ), wxGtkFileCtrl *fileCtrl )
218 {
219 // check next selection event and ignore it if it has 0 files
220 // because such events are redundantly generated by gtk.
221 if ( fileCtrl->m_checkNextSelEvent )
222 {
223 wxArrayString filenames;
224 fileCtrl->GetFilenames( filenames );
225
226 if ( filenames.Count() != 0 )
227 fileCtrl->m_checkNextSelEvent = false;
228 }
229
230 if ( !fileCtrl->m_checkNextSelEvent )
231 GenerateSelectionChangedEvent( fileCtrl, fileCtrl );
232 }
233 }
234
235 extern "C"
236 {
237 static void
238 gtkfilechooserwidget_folder_changed_callback( GtkWidget *WXUNUSED( widget ), wxGtkFileCtrl *fileCtrl )
239 {
240 if ( fileCtrl->m_ignoreNextFolderChangeEvent )
241 {
242 fileCtrl->m_ignoreNextFolderChangeEvent = false;
243 }
244 else
245 {
246 GenerateFolderChangedEvent( fileCtrl, fileCtrl );
247 }
248
249 fileCtrl->m_checkNextSelEvent = true;
250 }
251 }
252
253 // wxGtkFileCtrl implementation
254
255 IMPLEMENT_DYNAMIC_CLASS( wxGtkFileCtrl, wxControl )
256
257 void wxGtkFileCtrl::Init()
258 {
259 m_hasFocus = false;
260 m_checkNextSelEvent = false;
261
262 // ignore the first folder change event which is fired upon startup.
263 m_ignoreNextFolderChangeEvent = true;
264 }
265
266 bool wxGtkFileCtrl::Create( wxWindow *parent,
267 wxWindowID id,
268 const wxString& defaultDirectory,
269 const wxString& defaultFileName,
270 const wxString& wildCard,
271 long style,
272 const wxPoint& pos,
273 const wxSize& size,
274 const wxString& name )
275 {
276 if ( !PreCreation( parent, pos, size ) ||
277 !CreateBase( parent, id, pos, size, style, wxDefaultValidator, name ) )
278 {
279 wxFAIL_MSG( wxT( "wxGtkFileCtrl creation failed" ) );
280 return false;
281 }
282
283 GtkFileChooserAction gtkAction;
284
285 if ( style & wxFC_SAVE )
286 {
287 gtkAction = GTK_FILE_CHOOSER_ACTION_SAVE;
288 }
289 else if ( style & wxFC_OPEN )
290 {
291 gtkAction = GTK_FILE_CHOOSER_ACTION_OPEN;
292 }
293
294 m_widget = gtk_alignment_new ( 0, 0, 1, 1 );
295 m_fcWidget = GTK_FILE_CHOOSER( gtk_file_chooser_widget_new( GTK_FILE_CHOOSER_ACTION_OPEN ) );
296 gtk_widget_show ( GTK_WIDGET( m_fcWidget ) );
297 gtk_container_add ( GTK_CONTAINER ( m_widget ), GTK_WIDGET( m_fcWidget ) );
298
299 m_focusWidget = GTK_WIDGET( m_fcWidget );
300
301 g_signal_connect ( m_fcWidget, "file-activated",
302 G_CALLBACK ( gtkfilechooserwidget_file_activated_callback ),
303 this );
304
305 g_signal_connect ( m_fcWidget, "current-folder-changed",
306 G_CALLBACK ( gtkfilechooserwidget_folder_changed_callback ),
307 this );
308
309 g_signal_connect ( m_fcWidget, "selection-changed",
310 G_CALLBACK ( gtkfilechooserwidget_selection_changed_callback ),
311 this );
312
313 m_fc.SetWidget( m_fcWidget );
314
315 if ( style & wxFC_MULTIPLE )
316 gtk_file_chooser_set_select_multiple( m_fcWidget, true );
317
318 SetWildcard( wildCard );
319
320 // if defaultDir is specified it should contain the directory and
321 // defaultFileName should contain the default name of the file, however if
322 // directory is not given, defaultFileName contains both
323 wxFileName fn;
324 if ( defaultDirectory.empty() )
325 fn.Assign( defaultFileName );
326 else if ( !defaultFileName.empty() )
327 fn.Assign( defaultDirectory, defaultFileName );
328 else
329 fn.AssignDir( defaultDirectory );
330
331 // set the initial file name and/or directory
332 const wxString dir = fn.GetPath();
333 if ( !dir.empty() )
334 {
335 gtk_file_chooser_set_current_folder( m_fcWidget,
336 dir.fn_str() );
337 }
338
339 const wxString fname = fn.GetFullName();
340 if ( style & wxFC_SAVE )
341 {
342 if ( !fname.empty() )
343 {
344 gtk_file_chooser_set_current_name( m_fcWidget,
345 fname.fn_str() );
346 }
347 }
348 else // wxFC_OPEN
349 {
350 if ( !fname.empty() )
351 {
352 gtk_file_chooser_set_filename( m_fcWidget,
353 fn.GetFullPath().fn_str() );
354 }
355 }
356
357 m_parent->DoAddChild( this );
358
359 PostCreation( size );
360
361 return TRUE;
362 }
363
364 bool wxGtkFileCtrl::SetPath( const wxString& path )
365 {
366 return m_fc.SetPath( path );
367 }
368
369 bool wxGtkFileCtrl::SetDirectory( const wxString& dir )
370 {
371 return m_fc.SetDirectory( dir );
372 }
373
374 bool wxGtkFileCtrl::SetFilename( const wxString& name )
375 {
376 if ( !gtk_check_version( 2, 4, 0 ) )
377 {
378 if ( HasFlag( wxFC_SAVE ) )
379 {
380 gtk_file_chooser_set_current_name( m_fcWidget, wxGTK_CONV( name ) );
381 return true;
382 }
383 else
384 return SetPath( wxFileName( GetDirectory(), name ).GetFullPath() );
385 }
386
387 return false;
388 }
389
390 void wxGtkFileCtrl::SetWildcard( const wxString& wildCard )
391 {
392 m_wildCard = wildCard;
393
394 m_fc.SetWildcard( wildCard );
395 }
396
397 void wxGtkFileCtrl::SetFilterIndex( int filterIndex )
398 {
399 m_fc.SetFilterIndex( filterIndex );
400 }
401
402 wxString wxGtkFileCtrl::GetPath() const
403 {
404 return m_fc.GetPath();
405 }
406
407 void wxGtkFileCtrl::GetPaths( wxArrayString& paths ) const
408 {
409 m_fc.GetPaths( paths );
410 }
411
412 wxString wxGtkFileCtrl::GetDirectory() const
413 {
414 return m_fc.GetDirectory();
415 }
416
417 wxString wxGtkFileCtrl::GetFilename() const
418 {
419 return m_fc.GetFilename();
420 }
421
422 void wxGtkFileCtrl::GetFilenames( wxArrayString& files ) const
423 {
424 m_fc.GetFilenames( files );
425 }
426
427 void wxGtkFileCtrl::ShowHidden(const bool show)
428 {
429 gtk_file_chooser_set_show_hidden( m_fcWidget, ( show == true ) ? TRUE : FALSE );
430 }
431
432 #endif // wxUSE_FILECTRL