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