]> Pileus Git - ~andy/gtk/blob - gtk/gtkfilechooserdialog.c
Intern some more strings.
[~andy/gtk] / gtk / gtkfilechooserdialog.c
1 /* GTK - The GIMP Toolkit
2  * gtkfilechooserdialog.c: File selector dialog
3  * Copyright (C) 2003, Red Hat, Inc.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20
21 #include <config.h>
22 #include "gtkfilechooserdialog.h"
23 #include "gtkfilechooserwidget.h"
24 #include "gtkfilechooserutils.h"
25 #include "gtkfilechooserembed.h"
26 #include "gtkfilesystem.h"
27 #include "gtktypebuiltins.h"
28 #include "gtkintl.h"
29 #include "gtkalias.h"
30
31 #include <stdarg.h>
32
33 struct _GtkFileChooserDialogPrivate
34 {
35   GtkWidget *widget;
36   
37   char *file_system;
38
39   /* for use with GtkFileChooserEmbed */
40   gint default_width;
41   gint default_height;
42   gboolean resize_horizontally;
43   gboolean resize_vertically;
44 };
45
46 #define GTK_FILE_CHOOSER_DIALOG_GET_PRIVATE(o)  (GTK_FILE_CHOOSER_DIALOG (o)->priv)
47
48 static void gtk_file_chooser_dialog_class_init (GtkFileChooserDialogClass *class);
49 static void gtk_file_chooser_dialog_init       (GtkFileChooserDialog      *dialog);
50 static void gtk_file_chooser_dialog_finalize   (GObject                   *object);
51
52 static GObject* gtk_file_chooser_dialog_constructor  (GType                  type,
53                                                       guint                  n_construct_properties,
54                                                       GObjectConstructParam *construct_params);
55 static void     gtk_file_chooser_dialog_set_property (GObject               *object,
56                                                       guint                  prop_id,
57                                                       const GValue          *value,
58                                                       GParamSpec            *pspec);
59 static void     gtk_file_chooser_dialog_get_property (GObject               *object,
60                                                       guint                  prop_id,
61                                                       GValue                *value,
62                                                       GParamSpec            *pspec);
63
64 static void     gtk_file_chooser_dialog_map          (GtkWidget             *widget);
65 static void     gtk_file_chooser_dialog_unmap        (GtkWidget             *widget);
66 static void     gtk_file_chooser_dialog_style_set    (GtkWidget             *widget,
67                                                       GtkStyle              *previous_style);
68
69 static void response_cb (GtkDialog *dialog,
70                          gint       response_id);
71
72 static GObjectClass *parent_class;
73
74 GType
75 gtk_file_chooser_dialog_get_type (void)
76 {
77   static GType file_chooser_dialog_type = 0;
78
79   if (!file_chooser_dialog_type)
80     {
81       static const GTypeInfo file_chooser_dialog_info =
82       {
83         sizeof (GtkFileChooserDialogClass),
84         NULL,           /* base_init */
85         NULL,           /* base_finalize */
86         (GClassInitFunc) gtk_file_chooser_dialog_class_init,
87         NULL,           /* class_finalize */
88         NULL,           /* class_data */
89         sizeof (GtkFileChooserDialog),
90         0,              /* n_preallocs */
91         (GInstanceInitFunc) gtk_file_chooser_dialog_init,
92       };
93
94       static const GInterfaceInfo file_chooser_info =
95       {
96         (GInterfaceInitFunc) _gtk_file_chooser_delegate_iface_init, /* interface_init */
97         NULL,                                                       /* interface_finalize */
98         NULL                                                        /* interface_data */
99       };
100
101       file_chooser_dialog_type = g_type_register_static (GTK_TYPE_DIALOG, I_("GtkFileChooserDialog"),
102                                                          &file_chooser_dialog_info, 0);
103       g_type_add_interface_static (file_chooser_dialog_type,
104                                    GTK_TYPE_FILE_CHOOSER,
105                                    &file_chooser_info);
106     }
107
108   return file_chooser_dialog_type;
109 }
110
111 static void
112 gtk_file_chooser_dialog_class_init (GtkFileChooserDialogClass *class)
113 {
114   GObjectClass *gobject_class = G_OBJECT_CLASS (class);
115   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
116
117   parent_class = g_type_class_peek_parent (class);
118
119   gobject_class->constructor = gtk_file_chooser_dialog_constructor;
120   gobject_class->set_property = gtk_file_chooser_dialog_set_property;
121   gobject_class->get_property = gtk_file_chooser_dialog_get_property;
122   gobject_class->finalize = gtk_file_chooser_dialog_finalize;
123
124   widget_class->map       = gtk_file_chooser_dialog_map;
125   widget_class->unmap     = gtk_file_chooser_dialog_unmap;
126   widget_class->style_set = gtk_file_chooser_dialog_style_set;
127
128   _gtk_file_chooser_install_properties (gobject_class);
129
130   g_type_class_add_private (class, sizeof (GtkFileChooserDialogPrivate));
131 }
132
133 static void
134 gtk_file_chooser_dialog_init (GtkFileChooserDialog *dialog)
135 {
136   GtkFileChooserDialogPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (dialog,
137                                                                    GTK_TYPE_FILE_CHOOSER_DIALOG,
138                                                                    GtkFileChooserDialogPrivate);
139   dialog->priv = priv;
140   dialog->priv->default_width = -1;
141   dialog->priv->default_height = -1;
142   dialog->priv->resize_horizontally = TRUE;
143   dialog->priv->resize_vertically = TRUE;
144
145   gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
146
147   /* We do a signal connection here rather than overriding the method in
148    * class_init because GtkDialog::response is a RUN_LAST signal.  We want *our*
149    * handler to be run *first*, regardless of whether the user installs response
150    * handlers of his own.
151    */
152   g_signal_connect (dialog, "response",
153                     G_CALLBACK (response_cb), NULL);
154 }
155
156 static void
157 gtk_file_chooser_dialog_finalize (GObject *object)
158 {
159   GtkFileChooserDialog *dialog = GTK_FILE_CHOOSER_DIALOG (object);
160
161   g_free (dialog->priv->file_system);
162
163   G_OBJECT_CLASS (parent_class)->finalize (object);  
164 }
165
166 /* Callback used when the user activates a file in the file chooser widget */
167 static void
168 file_chooser_widget_file_activated (GtkFileChooser       *chooser,
169                                     GtkFileChooserDialog *dialog)
170 {
171   GList *children, *l;
172
173   if (gtk_window_activate_default (GTK_WINDOW (dialog)))
174     return;
175
176   /* There probably isn't a default widget, so make things easier for the
177    * programmer by looking for a reasonable button on our own.
178    */
179
180   children = gtk_container_get_children (GTK_CONTAINER (GTK_DIALOG (dialog)->action_area));
181
182   for (l = children; l; l = l->next)
183     {
184       GtkWidget *widget;
185       int response_id;
186
187       widget = GTK_WIDGET (l->data);
188       response_id = gtk_dialog_get_response_for_widget (GTK_DIALOG (dialog), widget);
189       if (response_id == GTK_RESPONSE_ACCEPT
190           || response_id == GTK_RESPONSE_OK
191           || response_id == GTK_RESPONSE_YES
192           || response_id == GTK_RESPONSE_APPLY)
193         {
194           gtk_widget_activate (widget); /* Should we gtk_dialog_response (dialog, response_id) instead? */
195           break;
196         }
197     }
198
199   g_list_free (children);
200 }
201
202 static void
203 file_chooser_widget_update_hints (GtkFileChooserDialog *dialog)
204 {
205   GtkFileChooserDialogPrivate *priv;
206   GdkGeometry geometry;
207
208   priv = GTK_FILE_CHOOSER_DIALOG_GET_PRIVATE (dialog);
209
210   geometry.min_width = -1;
211   geometry.min_height = -1;
212   geometry.max_width = (priv->resize_horizontally?G_MAXSHORT:-1);
213   geometry.max_height = (priv->resize_vertically?G_MAXSHORT:-1);
214
215   gtk_window_set_geometry_hints (GTK_WINDOW (dialog), NULL,
216                                  &geometry,
217                                  GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE);
218 }
219
220 static void
221 clamp_to_screen (GtkWidget *widget,
222                  gint      *width,
223                  gint      *height)
224 {
225   GdkScreen *screen;
226   int monitor_num;
227   GdkRectangle monitor;
228
229   g_return_if_fail (GTK_WIDGET_REALIZED (widget));
230   
231   screen = gtk_widget_get_screen (widget);
232   monitor_num = gdk_screen_get_monitor_at_window (screen, widget->window);
233
234   gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
235
236   if (width)
237     *width = MIN (*width, (monitor.width * 3) / 4);
238
239   if (height)
240     *height = MIN (*height, (monitor.height * 3) / 4);
241 }
242
243 static void
244 file_chooser_widget_default_realized_size_changed (GtkWidget            *widget,
245                                                    GtkFileChooserDialog *dialog)
246 {
247   GtkFileChooserDialogPrivate *priv;
248   gint width;
249   gint height;
250   gint default_width, default_height;
251   GtkRequisition req;
252   gboolean resize_horizontally;
253   gboolean resize_vertically;
254   gboolean update_hints;
255   gint dx = 0, dy = 0;
256   gint cur_width, cur_height;
257
258   priv = GTK_FILE_CHOOSER_DIALOG_GET_PRIVATE (dialog);
259
260   /* Force a size request of everything before we start.  This will make sure
261    * that widget->requisition is meaningful. */
262   gtk_widget_size_request (GTK_WIDGET (dialog), &req);
263   gtk_window_get_size (GTK_WINDOW (dialog), &cur_width, &cur_height);
264   width = GTK_WIDGET (dialog)->requisition.width - priv->widget->requisition.width;
265   height = GTK_WIDGET (dialog)->requisition.height - priv->widget->requisition.height;
266   _gtk_file_chooser_embed_get_default_size (GTK_FILE_CHOOSER_EMBED (priv->widget),
267                                             &default_width, &default_height);
268
269   /* Ideal target size modulo any resizing */
270   width = default_width + width;
271   height = default_height + height;
272
273   /* Now, we test for resizability */
274   update_hints = FALSE;
275   _gtk_file_chooser_embed_get_resizable_hints (GTK_FILE_CHOOSER_EMBED (priv->widget),
276                                                &resize_horizontally,
277                                                &resize_vertically);
278   resize_vertically = (!! resize_vertically);     /* normalize */
279   resize_horizontally = (!! resize_horizontally);
280
281   if (resize_horizontally && priv->resize_horizontally)
282     {
283       dx = default_width - priv->default_width;
284       priv->default_width = default_width;
285     }
286   else if (resize_horizontally && ! priv->resize_horizontally)
287     {
288       /* We restore to the ideal size + any change in default_size (which is not
289        * expected).  It would be nicer to store the older size to restore to in
290        * the future. */
291       dx = default_width - priv->default_width;
292       dx += width - cur_width;
293       priv->default_width = default_width;
294       update_hints = TRUE;
295     }
296   else
297     {
298       update_hints = TRUE;
299     }
300   
301   if (resize_vertically && priv->resize_vertically)
302     {
303       dy = default_height - priv->default_height;
304       priv->default_height = default_height;
305     }
306   else if (resize_vertically && ! priv->resize_vertically)
307     {
308       dy = default_height - priv->default_height;
309       dy += height - cur_height;
310       priv->default_height = default_height;
311       update_hints = TRUE;
312     }
313   else
314     {
315       update_hints = TRUE;
316     }
317
318   priv->resize_horizontally = resize_horizontally;
319   priv->resize_vertically = resize_vertically;
320
321   if (dx != 0 || dy != 0)
322     {
323       gint new_width = cur_width + dx;
324       gint new_height = cur_height + dy;
325
326       clamp_to_screen (GTK_WIDGET (dialog), &new_width, &new_height);
327       
328       gtk_window_resize (GTK_WINDOW (dialog), new_width, new_height);
329     }
330
331   /* Only store the size if we can resize in that direction. */
332   if (update_hints)
333     file_chooser_widget_update_hints (dialog);
334 }
335
336 static void
337 file_chooser_widget_default_unrealized_size_changed (GtkWidget            *widget,
338                                                      GtkFileChooserDialog *dialog)
339 {
340   GtkFileChooserDialogPrivate *priv;
341   GtkRequisition req;
342   gint width, height;
343
344   priv = GTK_FILE_CHOOSER_DIALOG_GET_PRIVATE (dialog);
345   gtk_widget_size_request (GTK_WIDGET (dialog), &req);
346
347   _gtk_file_chooser_embed_get_resizable_hints (GTK_FILE_CHOOSER_EMBED (priv->widget),
348                                                &(priv->resize_horizontally),
349                                                &(priv->resize_vertically));
350   _gtk_file_chooser_embed_get_default_size (GTK_FILE_CHOOSER_EMBED (priv->widget),
351                                             &(priv->default_width), &(priv->default_height));
352   
353   /* Determine how much space the rest of the dialog uses compared to priv->widget */
354   width = priv->default_width + GTK_WIDGET (dialog)->requisition.width - priv->widget->requisition.width;
355   height = priv->default_height + GTK_WIDGET (dialog)->requisition.height - priv->widget->requisition.height;
356
357   gtk_window_set_default_size (GTK_WINDOW (dialog), width, height);
358   file_chooser_widget_update_hints (dialog);
359 }
360
361 static void
362 file_chooser_widget_default_size_changed (GtkWidget            *widget,
363                                           GtkFileChooserDialog *dialog)
364 {
365   if (GTK_WIDGET_REALIZED (dialog))
366     file_chooser_widget_default_realized_size_changed (widget, dialog);
367   else
368     file_chooser_widget_default_unrealized_size_changed (widget, dialog);
369 }
370   
371 static GObject*
372 gtk_file_chooser_dialog_constructor (GType                  type,
373                                      guint                  n_construct_properties,
374                                      GObjectConstructParam *construct_params)
375 {
376   GtkFileChooserDialogPrivate *priv;
377   GObject *object;
378
379   object = parent_class->constructor (type,
380                                       n_construct_properties,
381                                       construct_params);
382   priv = GTK_FILE_CHOOSER_DIALOG_GET_PRIVATE (object);
383
384   gtk_widget_push_composite_child ();
385
386   if (priv->file_system)
387     priv->widget = g_object_new (GTK_TYPE_FILE_CHOOSER_WIDGET,
388                                  "file-system-backend", priv->file_system,
389                                  NULL);
390   else
391     priv->widget = g_object_new (GTK_TYPE_FILE_CHOOSER_WIDGET, NULL);
392
393   g_signal_connect (priv->widget, "file-activated",
394                     G_CALLBACK (file_chooser_widget_file_activated), object);
395   g_signal_connect (priv->widget, "default-size-changed",
396                     G_CALLBACK (file_chooser_widget_default_size_changed), object);
397
398   gtk_box_pack_start (GTK_BOX (GTK_DIALOG (object)->vbox), priv->widget, TRUE, TRUE, 0);
399
400   gtk_widget_show (priv->widget);
401
402   _gtk_file_chooser_set_delegate (GTK_FILE_CHOOSER (object),
403                                   GTK_FILE_CHOOSER (priv->widget));
404
405   gtk_widget_pop_composite_child ();
406
407   return object;
408 }
409
410 static void
411 gtk_file_chooser_dialog_set_property (GObject         *object,
412                                       guint            prop_id,
413                                       const GValue    *value,
414                                       GParamSpec      *pspec)
415
416 {
417   GtkFileChooserDialogPrivate *priv = GTK_FILE_CHOOSER_DIALOG_GET_PRIVATE (object);
418
419   switch (prop_id)
420     {
421     case GTK_FILE_CHOOSER_PROP_FILE_SYSTEM_BACKEND:
422       g_free (priv->file_system);
423       priv->file_system = g_value_dup_string (value);
424       break;
425     default:
426       g_object_set_property (G_OBJECT (priv->widget), pspec->name, value);
427       break;
428     }
429 }
430
431 static void
432 gtk_file_chooser_dialog_get_property (GObject         *object,
433                                       guint            prop_id,
434                                       GValue          *value,
435                                       GParamSpec      *pspec)
436 {
437   GtkFileChooserDialogPrivate *priv = GTK_FILE_CHOOSER_DIALOG_GET_PRIVATE (object);
438
439   g_object_get_property (G_OBJECT (priv->widget), pspec->name, value);
440 }
441
442 #if 0
443 static void
444 set_default_size (GtkFileChooserDialog *dialog)
445 {
446   GtkWidget *widget;
447   GtkWindow *window;
448   int default_width, default_height;
449   int width, height;
450   int font_size;
451   GdkScreen *screen;
452   int monitor_num;
453   GtkRequisition req;
454   GdkRectangle monitor;
455
456   widget = GTK_WIDGET (dialog);
457   window = GTK_WINDOW (dialog);
458
459   /* Size based on characters */
460
461   font_size = pango_font_description_get_size (widget->style->font_desc);
462   font_size = PANGO_PIXELS (font_size);
463
464   width = font_size * NUM_CHARS;
465   height = font_size * NUM_LINES;
466
467   /* Use at least the requisition size... */
468
469   gtk_widget_size_request (widget, &req);
470   width = MAX (width, req.width);
471   height = MAX (height, req.height);
472
473   /* ... but no larger than the monitor */
474
475   screen = gtk_widget_get_screen (widget);
476   monitor_num = gdk_screen_get_monitor_at_window (screen, widget->window);
477
478   gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
479
480   width = MIN (width, monitor.width * 3 / 4);
481   height = MIN (height, monitor.height * 3 / 4);
482
483   /* Set size */
484
485   gtk_window_get_default_size (window, &default_width, &default_height);
486
487   gtk_window_set_default_size (window,
488                                (default_width == -1) ? width : default_width,
489                                (default_height == -1) ? height : default_height);
490 }
491 #endif
492
493 /* GtkWidget::map handler */
494 static void
495 gtk_file_chooser_dialog_map (GtkWidget *widget)
496 {
497   GtkFileChooserDialog *dialog = GTK_FILE_CHOOSER_DIALOG (widget);
498   GtkFileChooserDialogPrivate *priv = GTK_FILE_CHOOSER_DIALOG_GET_PRIVATE (dialog);
499
500   if (!GTK_WIDGET_MAPPED (priv->widget))
501     gtk_widget_map (priv->widget);
502
503   GTK_WIDGET_CLASS (parent_class)->map (widget);
504
505   _gtk_file_chooser_embed_initial_focus (GTK_FILE_CHOOSER_EMBED (priv->widget));
506 }
507
508 /* GtkWidget::unmap handler */
509 static void
510 gtk_file_chooser_dialog_unmap (GtkWidget *widget)
511 {
512   GtkFileChooserDialog *dialog = GTK_FILE_CHOOSER_DIALOG (widget);
513   GtkFileChooserDialogPrivate *priv = GTK_FILE_CHOOSER_DIALOG_GET_PRIVATE (dialog);
514
515   GTK_WIDGET_CLASS (parent_class)->unmap (widget);
516
517   /* See bug #145470.  We unmap the GtkFileChooserWidget so that if the dialog
518    * is remapped, the widget will be remapped as well.  Implementations should
519    * refresh their contents when this happens, as some applications keep a
520    * single file chooser alive and map/unmap it as needed, rather than creating
521    * a new file chooser every time they need one.
522    */
523   gtk_widget_unmap (priv->widget);
524 }
525
526 static void
527 gtk_file_chooser_dialog_style_set (GtkWidget *widget,
528                                    GtkStyle  *previous_style)
529 {
530   GtkDialog *dialog;
531
532   if (GTK_WIDGET_CLASS (parent_class)->style_set)
533     GTK_WIDGET_CLASS (parent_class)->style_set (widget, previous_style);
534
535   dialog = GTK_DIALOG (widget);
536
537   /* Override the style properties with HIG-compliant spacings.  Ugh.
538    * http://developer.gnome.org/projects/gup/hig/1.0/layout.html#layout-dialogs
539    * http://developer.gnome.org/projects/gup/hig/1.0/windows.html#alert-spacing
540    */
541
542   gtk_container_set_border_width (GTK_CONTAINER (dialog->vbox), 12);
543   gtk_box_set_spacing (GTK_BOX (dialog->vbox), 24);
544
545   gtk_container_set_border_width (GTK_CONTAINER (dialog->action_area), 0);
546   gtk_box_set_spacing (GTK_BOX (dialog->action_area), 6);
547 }
548
549 /* GtkDialog::response handler */
550 static void
551 response_cb (GtkDialog *dialog,
552              gint       response_id)
553 {
554   GtkFileChooserDialogPrivate *priv;
555
556   priv = GTK_FILE_CHOOSER_DIALOG_GET_PRIVATE (dialog);
557
558   /* Act only on response IDs we recognize */
559   if (!(response_id == GTK_RESPONSE_ACCEPT
560         || response_id == GTK_RESPONSE_OK
561         || response_id == GTK_RESPONSE_YES
562         || response_id == GTK_RESPONSE_APPLY))
563     return;
564
565   if (!_gtk_file_chooser_embed_should_respond (GTK_FILE_CHOOSER_EMBED (priv->widget)))
566     g_signal_stop_emission_by_name (dialog, "response");
567 }
568
569 static GtkWidget *
570 gtk_file_chooser_dialog_new_valist (const gchar          *title,
571                                     GtkWindow            *parent,
572                                     GtkFileChooserAction  action,
573                                     const gchar          *backend,
574                                     const gchar          *first_button_text,
575                                     va_list               varargs)
576 {
577   GtkWidget *result;
578   const char *button_text = first_button_text;
579   gint response_id;
580
581   result = g_object_new (GTK_TYPE_FILE_CHOOSER_DIALOG,
582                          "title", title,
583                          "action", action,
584                          "file-system-backend", backend,
585                          NULL);
586
587   if (parent)
588     gtk_window_set_transient_for (GTK_WINDOW (result), parent);
589
590   while (button_text)
591     {
592       response_id = va_arg (varargs, gint);
593       gtk_dialog_add_button (GTK_DIALOG (result), button_text, response_id);
594       button_text = va_arg (varargs, const gchar *);
595     }
596
597   return result;
598 }
599
600 /**
601  * gtk_file_chooser_dialog_new:
602  * @title: Title of the dialog, or %NULL
603  * @parent: Transient parent of the dialog, or %NULL
604  * @action: Open or save mode for the dialog
605  * @first_button_text: stock ID or text to go in the first button, or %NULL
606  * @Varargs: response ID for the first button, then additional (button, id) pairs, ending with %NULL
607  *
608  * Creates a new #GtkFileChooserDialog.  This function is analogous to
609  * gtk_dialog_new_with_buttons().
610  *
611  * Return value: a new #GtkFileChooserDialog
612  *
613  * Since: 2.4
614  **/
615 GtkWidget *
616 gtk_file_chooser_dialog_new (const gchar         *title,
617                              GtkWindow           *parent,
618                              GtkFileChooserAction action,
619                              const gchar         *first_button_text,
620                              ...)
621 {
622   GtkWidget *result;
623   va_list varargs;
624   
625   va_start (varargs, first_button_text);
626   result = gtk_file_chooser_dialog_new_valist (title, parent, action,
627                                                NULL, first_button_text,
628                                                varargs);
629   va_end (varargs);
630
631   return result;
632 }
633
634 /**
635  * gtk_file_chooser_dialog_new_with_backend:
636  * @title: Title of the dialog, or %NULL
637  * @parent: Transient parent of the dialog, or %NULL
638  * @action: Open or save mode for the dialog
639  * @backend: The name of the specific filesystem backend to use.
640  * @first_button_text: stock ID or text to go in the first button, or %NULL
641  * @Varargs: response ID for the first button, then additional (button, id) pairs, ending with %NULL
642  *
643  * Creates a new #GtkFileChooserDialog with a specified backend. This is
644  * especially useful if you use gtk_file_chooser_set_local_only() to allow
645  * non-local files and you use a more expressive vfs, such as gnome-vfs,
646  * to load files.
647  *
648  * Return value: a new #GtkFileChooserDialog
649  *
650  * Since: 2.4
651  **/
652 GtkWidget *
653 gtk_file_chooser_dialog_new_with_backend (const gchar          *title,
654                                           GtkWindow            *parent,
655                                           GtkFileChooserAction  action,
656                                           const gchar          *backend,
657                                           const gchar          *first_button_text,
658                                           ...)
659 {
660   GtkWidget *result;
661   va_list varargs;
662   
663   va_start (varargs, first_button_text);
664   result = gtk_file_chooser_dialog_new_valist (title, parent, action,
665                                                backend, first_button_text,
666                                                varargs);
667   va_end (varargs);
668
669   return result;
670 }
671
672 #define __GTK_FILE_CHOOSER_DIALOG_C__
673 #include "gtkaliasdef.c"