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