1 /* GTK - The GIMP Toolkit
2 * gtkfilechooserdialog.c: File selector dialog
3 * Copyright (C) 2003, Red Hat, Inc.
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.
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.
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.
21 #include "gtkfilechooserdialog.h"
22 #include "gtkfilechooserwidget.h"
23 #include "gtkfilechooserutils.h"
24 #include "gtkfilesystem.h"
25 #include "gtktypebuiltins.h"
32 struct _GtkFileChooserDialogPrivate
39 #define GTK_FILE_CHOOSER_DIALOG_GET_PRIVATE(o) (GTK_FILE_CHOOSER_DIALOG (o)->priv)
41 static void gtk_file_chooser_dialog_class_init (GtkFileChooserDialogClass *class);
42 static void gtk_file_chooser_dialog_init (GtkFileChooserDialog *dialog);
43 static void gtk_file_chooser_dialog_finalize (GObject *object);
45 static GObject* gtk_file_chooser_dialog_constructor (GType type,
46 guint n_construct_properties,
47 GObjectConstructParam *construct_params);
48 static void gtk_file_chooser_dialog_set_property (GObject *object,
52 static void gtk_file_chooser_dialog_get_property (GObject *object,
57 static void gtk_file_chooser_dialog_realize (GtkWidget *widget);
58 static void gtk_file_chooser_dialog_style_set (GtkWidget *widget,
59 GtkStyle *previous_style);
60 static void gtk_file_chooser_dialog_screen_changed (GtkWidget *widget,
61 GdkScreen *previous_screen);
63 static GObjectClass *parent_class;
66 gtk_file_chooser_dialog_get_type (void)
68 static GType file_chooser_dialog_type = 0;
70 if (!file_chooser_dialog_type)
72 static const GTypeInfo file_chooser_dialog_info =
74 sizeof (GtkFileChooserDialogClass),
76 NULL, /* base_finalize */
77 (GClassInitFunc) gtk_file_chooser_dialog_class_init,
78 NULL, /* class_finalize */
79 NULL, /* class_data */
80 sizeof (GtkFileChooserDialog),
82 (GInstanceInitFunc) gtk_file_chooser_dialog_init,
85 static const GInterfaceInfo file_chooser_info =
87 (GInterfaceInitFunc) _gtk_file_chooser_delegate_iface_init, /* interface_init */
88 NULL, /* interface_finalize */
89 NULL /* interface_data */
92 file_chooser_dialog_type = g_type_register_static (GTK_TYPE_DIALOG, "GtkFileChooserDialog",
93 &file_chooser_dialog_info, 0);
94 g_type_add_interface_static (file_chooser_dialog_type,
95 GTK_TYPE_FILE_CHOOSER,
99 return file_chooser_dialog_type;
103 gtk_file_chooser_dialog_class_init (GtkFileChooserDialogClass *class)
105 GObjectClass *gobject_class = G_OBJECT_CLASS (class);
106 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
108 parent_class = g_type_class_peek_parent (class);
110 gobject_class->constructor = gtk_file_chooser_dialog_constructor;
111 gobject_class->set_property = gtk_file_chooser_dialog_set_property;
112 gobject_class->get_property = gtk_file_chooser_dialog_get_property;
113 gobject_class->finalize = gtk_file_chooser_dialog_finalize;
115 widget_class->realize = gtk_file_chooser_dialog_realize;
116 widget_class->style_set = gtk_file_chooser_dialog_style_set;
117 widget_class->screen_changed = gtk_file_chooser_dialog_screen_changed;
119 _gtk_file_chooser_install_properties (gobject_class);
121 g_type_class_add_private (class, sizeof (GtkFileChooserDialogPrivate));
125 gtk_file_chooser_dialog_init (GtkFileChooserDialog *dialog)
127 GtkFileChooserDialogPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (dialog,
128 GTK_TYPE_FILE_CHOOSER_DIALOG,
129 GtkFileChooserDialogPrivate);
132 gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
136 gtk_file_chooser_dialog_finalize (GObject *object)
138 GtkFileChooserDialog *dialog = GTK_FILE_CHOOSER_DIALOG (object);
140 g_free (dialog->priv->file_system);
142 G_OBJECT_CLASS (parent_class)->finalize (object);
145 /* Callback used when the user activates a file in the file chooser widget */
147 file_chooser_widget_file_activated (GtkFileChooser *chooser,
148 GtkFileChooserDialog *dialog)
150 gtk_window_activate_default (GTK_WINDOW (dialog));
154 gtk_file_chooser_dialog_constructor (GType type,
155 guint n_construct_properties,
156 GObjectConstructParam *construct_params)
158 GtkFileChooserDialogPrivate *priv;
161 object = parent_class->constructor (type,
162 n_construct_properties,
164 priv = GTK_FILE_CHOOSER_DIALOG_GET_PRIVATE (object);
166 gtk_widget_push_composite_child ();
168 if (priv->file_system)
169 priv->widget = g_object_new (GTK_TYPE_FILE_CHOOSER_WIDGET,
170 "file-system-backend", priv->file_system,
173 priv->widget = g_object_new (GTK_TYPE_FILE_CHOOSER_WIDGET, NULL);
175 g_signal_connect (priv->widget, "file-activated",
176 G_CALLBACK (file_chooser_widget_file_activated), object);
178 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (object)->vbox), priv->widget, TRUE, TRUE, 0);
179 gtk_widget_show (priv->widget);
181 _gtk_file_chooser_set_delegate (GTK_FILE_CHOOSER (object),
182 GTK_FILE_CHOOSER (priv->widget));
184 gtk_widget_pop_composite_child ();
190 gtk_file_chooser_dialog_set_property (GObject *object,
196 GtkFileChooserDialogPrivate *priv = GTK_FILE_CHOOSER_DIALOG_GET_PRIVATE (object);
200 case GTK_FILE_CHOOSER_PROP_FILE_SYSTEM_BACKEND:
201 g_free (priv->file_system);
202 priv->file_system = g_value_dup_string (value);
205 g_object_set_property (G_OBJECT (priv->widget), pspec->name, value);
211 gtk_file_chooser_dialog_get_property (GObject *object,
216 GtkFileChooserDialogPrivate *priv = GTK_FILE_CHOOSER_DIALOG_GET_PRIVATE (object);
218 g_object_get_property (G_OBJECT (priv->widget), pspec->name, value);
222 set_default_size (GtkFileChooserDialog *dialog)
226 int default_width, default_height;
232 GdkRectangle monitor;
234 widget = GTK_WIDGET (dialog);
235 window = GTK_WINDOW (dialog);
237 /* Size based on characters */
239 font_size = pango_font_description_get_size (widget->style->font_desc);
240 font_size = PANGO_PIXELS (font_size);
242 width = font_size * NUM_CHARS;
243 height = font_size * NUM_LINES;
245 /* Use at least the requisition size... */
247 gtk_widget_size_request (widget, &req);
248 width = MAX (width, req.width);
249 height = MAX (height, req.height);
251 /* ... but no larger than the monitor */
253 screen = gtk_widget_get_screen (widget);
254 monitor_num = gdk_screen_get_monitor_at_window (screen, widget->window);
256 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
258 width = MIN (width, monitor.width * 3 / 4);
259 height = MIN (height, monitor.height * 3 / 4);
263 gtk_window_get_default_size (window, &default_width, &default_height);
265 gtk_window_set_default_size (window,
266 (default_width == -1) ? width : default_width,
267 (default_height == -1) ? height : default_height);
271 gtk_file_chooser_dialog_realize (GtkWidget *widget)
273 GTK_WIDGET_CLASS (parent_class)->realize (widget);
274 set_default_size (GTK_FILE_CHOOSER_DIALOG (widget));
278 gtk_file_chooser_dialog_style_set (GtkWidget *widget,
279 GtkStyle *previous_style)
283 if (GTK_WIDGET_CLASS (parent_class)->style_set)
284 GTK_WIDGET_CLASS (parent_class)->style_set (widget, previous_style);
286 if (GTK_WIDGET_REALIZED (widget))
287 set_default_size (GTK_FILE_CHOOSER_DIALOG (widget));
289 dialog = GTK_DIALOG (widget);
291 /* Override the style properties with HIG-compliant spacings. Ugh.
292 * http://developer.gnome.org/projects/gup/hig/1.0/layout.html#layout-dialogs
293 * http://developer.gnome.org/projects/gup/hig/1.0/windows.html#alert-spacing
296 gtk_container_set_border_width (GTK_CONTAINER (dialog->vbox), 12);
297 gtk_box_set_spacing (GTK_BOX (dialog->vbox), 24);
299 gtk_container_set_border_width (GTK_CONTAINER (dialog->action_area), 0);
300 gtk_box_set_spacing (GTK_BOX (dialog->action_area), 6);
304 gtk_file_chooser_dialog_screen_changed (GtkWidget *widget,
305 GdkScreen *previous_screen)
307 if (GTK_WIDGET_CLASS (parent_class)->screen_changed)
308 GTK_WIDGET_CLASS (parent_class)->screen_changed (widget, previous_screen);
310 if (GTK_WIDGET_REALIZED (widget))
311 set_default_size (GTK_FILE_CHOOSER_DIALOG (widget));
315 gtk_file_chooser_dialog_new_valist (const gchar *title,
317 GtkFileChooserAction action,
318 const gchar *backend,
319 const gchar *first_button_text,
323 const char *button_text = first_button_text;
326 result = g_object_new (GTK_TYPE_FILE_CHOOSER_DIALOG,
329 "file-system-backend", backend,
333 gtk_window_set_transient_for (GTK_WINDOW (result), parent);
337 response_id = va_arg (varargs, gint);
338 gtk_dialog_add_button (GTK_DIALOG (result), button_text, response_id);
339 button_text = va_arg (varargs, const gchar *);
346 * gtk_file_chooser_dialog_new:
347 * @title: Title of the dialog, or %NULL
348 * @parent: Transient parent of the dialog, or %NULL
349 * @action: Open or save mode for the dialog
350 * @first_button_text: stock ID or text to go in the first button, or %NULL
351 * @Varargs: response ID for the first button, then additional (button, id) pairs, ending with %NULL
353 * Creates a new #GtkFileChooserDialog. This function is analogous to
354 * gtk_dialog_new_with_buttons().
356 * Return value: a new #GtkFileChooserDialog
361 gtk_file_chooser_dialog_new (const gchar *title,
363 GtkFileChooserAction action,
364 const gchar *first_button_text,
370 va_start (varargs, first_button_text);
371 result = gtk_file_chooser_dialog_new_valist (title, parent, action,
372 NULL, first_button_text,
380 * gtk_file_chooser_dialog_new_with_backend:
381 * @title: Title of the dialog, or %NULL
382 * @parent: Transient parent of the dialog, or %NULL
383 * @backend: The name of the specific filesystem backend to use.
384 * @action: Open or save mode for the dialog
385 * @first_button_text: stock ID or text to go in the first button, or %NULL
386 * @Varargs: response ID for the first button, then additional (button, id) pairs, ending with %NULL
388 * Creates a new #GtkFileChooserDialog with a specified backend. This is
389 * especially useful if you use gtk_file_chooser_set_local_only() to allow
390 * non-local files and you use a more expressive vfs, such as gnome-vfs,
393 * Return value: a new #GtkFileChooserDialog
398 gtk_file_chooser_dialog_new_with_backend (const gchar *title,
400 GtkFileChooserAction action,
401 const gchar *backend,
402 const gchar *first_button_text,
408 va_start (varargs, first_button_text);
409 result = gtk_file_chooser_dialog_new_valist (title, parent, action,
410 backend, first_button_text,