]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/filectrl.cpp
Fix regression in wxGTK wxFilePickerCtrl due to wxFileDialog changes.
[wxWidgets.git] / src / gtk / filectrl.cpp
CommitLineData
0cf3e587
VZ
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
a82b0593 17#if wxUSE_FILECTRL && !defined(__WXUNIVERSAL__)
cc681534 18
89e5d5bb 19#include "wx/filectrl.h"
0cf3e587
VZ
20
21#include "wx/gtk/private.h"
0cf3e587 22#include "wx/filename.h"
6305f044 23#include "wx/scopeguard.h"
0cf3e587
VZ
24#include "wx/tokenzr.h"
25
26//-----------------------------------------------------------------------------
27// wxGtkFileChooser implementation
28//-----------------------------------------------------------------------------
29
30void wxGtkFileChooser::SetWidget(GtkFileChooser *w)
31{
32 // check arguments
33 wxASSERT( w );
34 wxASSERT( GTK_FILE_CHOOSER( w ) );
35
36 this->m_widget = w;
37}
38
39wxString wxGtkFileChooser::GetPath() const
40{
41 wxGtkString str( gtk_file_chooser_get_filename( m_widget ) );
42
260020e3 43 wxString string;
f069ac48 44 if (str)
b74d7c85 45 string = wxString::FromUTF8(str);
260020e3 46 return string;
0cf3e587
VZ
47}
48
49void wxGtkFileChooser::GetFilenames( wxArrayString& files ) const
50{
51 GetPaths( files );
52 for ( size_t n = 0; n < files.GetCount(); ++n )
53 {
54 const wxFileName file( files[n] );
55 files[n] = file.GetFullName();
56 }
57}
58
59void wxGtkFileChooser::GetPaths( wxArrayString& paths ) const
60{
61 paths.Empty();
62 if ( gtk_file_chooser_get_select_multiple( m_widget ) )
63 {
64 GSList *gpathsi = gtk_file_chooser_get_filenames( m_widget );
65 GSList *gpaths = gpathsi;
66 while ( gpathsi )
67 {
b74d7c85 68 wxString file(wxString::FromUTF8(static_cast<gchar *>(gpathsi->data)));
0cf3e587
VZ
69 paths.Add( file );
70 g_free( gpathsi->data );
71 gpathsi = gpathsi->next;
72 }
73
74 g_slist_free( gpaths );
75 }
76 else
77 paths.Add( GetPath() );
78}
79
80bool wxGtkFileChooser::SetPath( const wxString& path )
81{
b74d7c85
VZ
82 if ( path.empty() )
83 return true;
0cf3e587 84
9618496b
VZ
85 switch ( gtk_file_chooser_get_action( m_widget ) )
86 {
87 case GTK_FILE_CHOOSER_ACTION_SAVE:
88 {
89 wxFileName fn(path);
90
91 const wxString fname = fn.GetFullName();
92 gtk_file_chooser_set_current_name( m_widget, fname.utf8_str() );
93
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;
98 }
99
100 case GTK_FILE_CHOOSER_ACTION_OPEN:
101 return gtk_file_chooser_set_filename( m_widget, path.utf8_str() ) != 0;
102
103 case GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER:
104 case GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER:
105 break;
106 }
107
108 wxFAIL_MSG( "Unexpected file chooser type" );
109
110 return false;
0cf3e587
VZ
111}
112
113bool wxGtkFileChooser::SetDirectory( const wxString& dir )
114{
b74d7c85 115 return gtk_file_chooser_set_current_folder( m_widget, dir.utf8_str() ) != 0;
0cf3e587
VZ
116}
117
118wxString wxGtkFileChooser::GetDirectory() const
119{
120 const wxGtkString str( gtk_file_chooser_get_current_folder( m_widget ) );
b74d7c85 121 return wxString::FromUTF8(str);
0cf3e587
VZ
122}
123
124wxString wxGtkFileChooser::GetFilename() const
125{
126 return wxFileName( GetPath() ).GetFullName();
127}
128
129void wxGtkFileChooser::SetWildcard( const wxString& wildCard )
130{
20380343
RR
131 m_wildcards.Empty();
132
0cf3e587
VZ
133 // parse filters
134 wxArrayString wildDescriptions, wildFilters;
135
136 if ( !wxParseCommonDialogsFilter( wildCard, wildDescriptions, wildFilters ) )
137 {
138 wxFAIL_MSG( wxT( "wxGtkFileChooser::SetWildcard - bad wildcard string" ) );
139 }
140 else
141 {
142 // Parsing went fine. Set m_wildCard to be returned by wxGtkFileChooserBase::GetWildcard
143 GtkFileChooser* chooser = m_widget;
144
145 // empty current filter list:
146 GSList* ifilters = gtk_file_chooser_list_filters( chooser );
147 GSList* filters = ifilters;
148
6305f044
VZ
149 m_ignoreNextFilterEvent = true;
150 wxON_BLOCK_EXIT_SET(m_ignoreNextFilterEvent, false);
151
0cf3e587
VZ
152 while ( ifilters )
153 {
154 gtk_file_chooser_remove_filter( chooser, GTK_FILE_FILTER( ifilters->data ) );
155 ifilters = ifilters->next;
156 }
157 g_slist_free( filters );
158
159 if (!wildCard.empty())
160 {
161 // add parsed to GtkChooser
162 for ( size_t n = 0; n < wildFilters.GetCount(); ++n )
163 {
164 GtkFileFilter* filter = gtk_file_filter_new();
165
166 gtk_file_filter_set_name( filter, wxGTK_CONV_SYS( wildDescriptions[n] ) );
167
168 wxStringTokenizer exttok( wildFilters[n], wxT( ";" ) );
03647350 169
81d6a507 170 int n1 = 1;
0cf3e587
VZ
171 while ( exttok.HasMoreTokens() )
172 {
173 wxString token = exttok.GetNextToken();
174 gtk_file_filter_add_pattern( filter, wxGTK_CONV_SYS( token ) );
03647350 175
81d6a507 176 if (n1 == 1)
20380343 177 m_wildcards.Add( token ); // Only add first pattern to list, used later when saving
81d6a507 178 n1++;
0cf3e587
VZ
179 }
180
181 gtk_file_chooser_add_filter( chooser, filter );
182 }
183
184 // Reset the filter index
185 SetFilterIndex( 0 );
186 }
187 }
188}
189
190void wxGtkFileChooser::SetFilterIndex( int filterIndex )
191{
192 gpointer filter;
193 GtkFileChooser *chooser = m_widget;
194 GSList *filters = gtk_file_chooser_list_filters( chooser );
195
196 filter = g_slist_nth_data( filters, filterIndex );
197
198 if ( filter != NULL )
199 {
200 gtk_file_chooser_set_filter( chooser, GTK_FILE_FILTER( filter ) );
201 }
202 else
203 {
204 wxFAIL_MSG( wxT( "wxGtkFileChooser::SetFilterIndex - bad filter index" ) );
205 }
206
207 g_slist_free( filters );
208}
209
210int wxGtkFileChooser::GetFilterIndex() const
211{
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 );
217
218 if ( index == -1 )
219 {
220 wxFAIL_MSG( wxT( "wxGtkFileChooser::GetFilterIndex - bad filter index returned by gtk+" ) );
221 return 0;
222 }
223 else
224 return index;
74ab5f5b 225}
0cf3e587 226
6305f044
VZ
227bool wxGtkFileChooser::HasFilterChoice() const
228{
229 return gtk_file_chooser_get_filter( m_widget ) != NULL;
230}
231
0cf3e587
VZ
232//-----------------------------------------------------------------------------
233// end wxGtkFileChooser Implementation
234//-----------------------------------------------------------------------------
235
236#if wxUSE_FILECTRL
237
238// gtk signal handlers
239
240extern "C"
241{
242 static void
243 gtkfilechooserwidget_file_activated_callback( GtkWidget *WXUNUSED( widget ), wxGtkFileCtrl *fileCtrl )
244 {
245 GenerateFileActivatedEvent( fileCtrl, fileCtrl );
246 }
247}
248
249extern "C"
250{
251 static void
252 gtkfilechooserwidget_selection_changed_callback( GtkWidget *WXUNUSED( widget ), wxGtkFileCtrl *fileCtrl )
253 {
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 )
257 {
258 wxArrayString filenames;
259 fileCtrl->GetFilenames( filenames );
260
261 if ( filenames.Count() != 0 )
262 fileCtrl->m_checkNextSelEvent = false;
263 }
264
265 if ( !fileCtrl->m_checkNextSelEvent )
266 GenerateSelectionChangedEvent( fileCtrl, fileCtrl );
267 }
268}
269
270extern "C"
271{
272 static void
273 gtkfilechooserwidget_folder_changed_callback( GtkWidget *WXUNUSED( widget ), wxGtkFileCtrl *fileCtrl )
274 {
275 if ( fileCtrl->m_ignoreNextFolderChangeEvent )
276 {
277 fileCtrl->m_ignoreNextFolderChangeEvent = false;
278 }
279 else
280 {
281 GenerateFolderChangedEvent( fileCtrl, fileCtrl );
282 }
283
284 fileCtrl->m_checkNextSelEvent = true;
285 }
286}
287
6305f044
VZ
288extern "C"
289{
290 static void
291 gtkfilechooserwidget_notify_callback( GObject *WXUNUSED( gobject ), GParamSpec *arg1, wxGtkFileCtrl *fileCtrl )
292 {
293 const char *name = g_param_spec_get_name (arg1);
294 if ( strcmp( name, "filter" ) == 0 &&
295 fileCtrl->HasFilterChoice() &&
296 !fileCtrl->GTKShouldIgnoreNextFilterEvent() )
297 {
298 GenerateFilterChangedEvent( fileCtrl, fileCtrl );
299 }
300 }
301}
302
0cf3e587
VZ
303// wxGtkFileCtrl implementation
304
305IMPLEMENT_DYNAMIC_CLASS( wxGtkFileCtrl, wxControl )
306
8ab75332
PC
307wxGtkFileCtrl::~wxGtkFileCtrl()
308{
309 if (m_fcWidget)
310 GTKDisconnect(m_fcWidget);
311}
312
0cf3e587
VZ
313void wxGtkFileCtrl::Init()
314{
0cf3e587
VZ
315 m_checkNextSelEvent = false;
316
317 // ignore the first folder change event which is fired upon startup.
318 m_ignoreNextFolderChangeEvent = true;
319}
320
321bool wxGtkFileCtrl::Create( wxWindow *parent,
322 wxWindowID id,
323 const wxString& defaultDirectory,
324 const wxString& defaultFileName,
325 const wxString& wildCard,
326 long style,
327 const wxPoint& pos,
328 const wxSize& size,
329 const wxString& name )
330{
331 if ( !PreCreation( parent, pos, size ) ||
332 !CreateBase( parent, id, pos, size, style, wxDefaultValidator, name ) )
333 {
334 wxFAIL_MSG( wxT( "wxGtkFileCtrl creation failed" ) );
335 return false;
336 }
337
260020e3 338 GtkFileChooserAction gtkAction = GTK_FILE_CHOOSER_ACTION_OPEN;
0cf3e587
VZ
339
340 if ( style & wxFC_SAVE )
0cf3e587 341 gtkAction = GTK_FILE_CHOOSER_ACTION_SAVE;
0cf3e587
VZ
342
343 m_widget = gtk_alignment_new ( 0, 0, 1, 1 );
9ff9d30c 344 g_object_ref(m_widget);
260020e3 345 m_fcWidget = GTK_FILE_CHOOSER( gtk_file_chooser_widget_new(gtkAction) );
0cf3e587
VZ
346 gtk_widget_show ( GTK_WIDGET( m_fcWidget ) );
347 gtk_container_add ( GTK_CONTAINER ( m_widget ), GTK_WIDGET( m_fcWidget ) );
348
349 m_focusWidget = GTK_WIDGET( m_fcWidget );
350
351 g_signal_connect ( m_fcWidget, "file-activated",
352 G_CALLBACK ( gtkfilechooserwidget_file_activated_callback ),
353 this );
354
355 g_signal_connect ( m_fcWidget, "current-folder-changed",
356 G_CALLBACK ( gtkfilechooserwidget_folder_changed_callback ),
357 this );
358
359 g_signal_connect ( m_fcWidget, "selection-changed",
360 G_CALLBACK ( gtkfilechooserwidget_selection_changed_callback ),
361 this );
362
6305f044
VZ
363 g_signal_connect ( m_fcWidget, "notify",
364 G_CALLBACK ( gtkfilechooserwidget_notify_callback ),
365 this );
366
0cf3e587
VZ
367 m_fc.SetWidget( m_fcWidget );
368
369 if ( style & wxFC_MULTIPLE )
370 gtk_file_chooser_set_select_multiple( m_fcWidget, true );
371
372 SetWildcard( wildCard );
373
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
377 wxFileName fn;
378 if ( defaultDirectory.empty() )
379 fn.Assign( defaultFileName );
380 else if ( !defaultFileName.empty() )
381 fn.Assign( defaultDirectory, defaultFileName );
382 else
383 fn.AssignDir( defaultDirectory );
384
385 // set the initial file name and/or directory
386 const wxString dir = fn.GetPath();
387 if ( !dir.empty() )
388 {
389 gtk_file_chooser_set_current_folder( m_fcWidget,
c282e47d 390 wxGTK_CONV_FN(dir) );
0cf3e587
VZ
391 }
392
393 const wxString fname = fn.GetFullName();
394 if ( style & wxFC_SAVE )
395 {
396 if ( !fname.empty() )
397 {
398 gtk_file_chooser_set_current_name( m_fcWidget,
c282e47d 399 wxGTK_CONV_FN(fname) );
0cf3e587
VZ
400 }
401 }
402 else // wxFC_OPEN
403 {
404 if ( !fname.empty() )
405 {
406 gtk_file_chooser_set_filename( m_fcWidget,
c282e47d 407 wxGTK_CONV_FN(fn.GetFullPath()) );
0cf3e587
VZ
408 }
409 }
410
411 m_parent->DoAddChild( this );
412
413 PostCreation( size );
414
415 return TRUE;
416}
417
418bool wxGtkFileCtrl::SetPath( const wxString& path )
419{
420 return m_fc.SetPath( path );
421}
422
423bool wxGtkFileCtrl::SetDirectory( const wxString& dir )
424{
425 return m_fc.SetDirectory( dir );
426}
427
428bool wxGtkFileCtrl::SetFilename( const wxString& name )
429{
700d08c1 430 if ( HasFlag( wxFC_SAVE ) )
0cf3e587 431 {
700d08c1
RR
432 gtk_file_chooser_set_current_name( m_fcWidget, wxGTK_CONV( name ) );
433 return true;
0cf3e587 434 }
700d08c1
RR
435 else
436 return SetPath( wxFileName( GetDirectory(), name ).GetFullPath() );
0cf3e587
VZ
437}
438
439void wxGtkFileCtrl::SetWildcard( const wxString& wildCard )
440{
441 m_wildCard = wildCard;
442
443 m_fc.SetWildcard( wildCard );
444}
445
446void wxGtkFileCtrl::SetFilterIndex( int filterIndex )
447{
448 m_fc.SetFilterIndex( filterIndex );
449}
450
451wxString wxGtkFileCtrl::GetPath() const
452{
453 return m_fc.GetPath();
454}
455
456void wxGtkFileCtrl::GetPaths( wxArrayString& paths ) const
457{
458 m_fc.GetPaths( paths );
459}
460
461wxString wxGtkFileCtrl::GetDirectory() const
462{
463 return m_fc.GetDirectory();
464}
465
466wxString wxGtkFileCtrl::GetFilename() const
467{
468 return m_fc.GetFilename();
469}
470
471void wxGtkFileCtrl::GetFilenames( wxArrayString& files ) const
472{
473 m_fc.GetFilenames( files );
474}
475
260020e3 476void wxGtkFileCtrl::ShowHidden(bool show)
0cf3e587 477{
89e5d5bb 478 gtk_file_chooser_set_show_hidden(m_fcWidget, show);
0cf3e587
VZ
479}
480
ff654490 481#endif // wxUSE_FILECTRL
cc681534 482
a82b0593 483#endif // wxUSE_FILECTRL && !defined(__WXUNIVERSAL__)