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);
143 /* Callback used when the user activates a file in the file chooser widget */
145 file_chooser_widget_file_activated (GtkFileChooser *chooser,
146 GtkFileChooserDialog *dialog)
148 gtk_window_activate_default (GTK_WINDOW (dialog));
152 gtk_file_chooser_dialog_constructor (GType type,
153 guint n_construct_properties,
154 GObjectConstructParam *construct_params)
156 GtkFileChooserDialogPrivate *priv;
159 object = parent_class->constructor (type,
160 n_construct_properties,
162 priv = GTK_FILE_CHOOSER_DIALOG_GET_PRIVATE (object);
164 gtk_widget_push_composite_child ();
166 if (priv->file_system)
167 priv->widget = g_object_new (GTK_TYPE_FILE_CHOOSER_WIDGET,
168 "file-system-backend", priv->file_system,
171 priv->widget = g_object_new (GTK_TYPE_FILE_CHOOSER_WIDGET, NULL);
173 g_signal_connect (priv->widget, "file-activated",
174 G_CALLBACK (file_chooser_widget_file_activated), object);
176 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (object)->vbox), priv->widget, TRUE, TRUE, 0);
177 gtk_widget_show (priv->widget);
179 _gtk_file_chooser_set_delegate (GTK_FILE_CHOOSER (object),
180 GTK_FILE_CHOOSER (priv->widget));
182 gtk_widget_pop_composite_child ();
188 gtk_file_chooser_dialog_set_property (GObject *object,
194 GtkFileChooserDialogPrivate *priv = GTK_FILE_CHOOSER_DIALOG_GET_PRIVATE (object);
198 case GTK_FILE_CHOOSER_PROP_FILE_SYSTEM_BACKEND:
199 g_free (priv->file_system);
200 priv->file_system = g_value_dup_string (value);
203 g_object_set_property (G_OBJECT (priv->widget), pspec->name, value);
209 gtk_file_chooser_dialog_get_property (GObject *object,
214 GtkFileChooserDialogPrivate *priv = GTK_FILE_CHOOSER_DIALOG_GET_PRIVATE (object);
216 g_object_get_property (G_OBJECT (priv->widget), pspec->name, value);
220 set_default_size (GtkFileChooserDialog *dialog)
224 int default_width, default_height;
230 GdkRectangle monitor;
232 widget = GTK_WIDGET (dialog);
233 window = GTK_WINDOW (dialog);
235 /* Size based on characters */
237 font_size = pango_font_description_get_size (widget->style->font_desc);
238 font_size = PANGO_PIXELS (font_size);
240 width = font_size * NUM_CHARS;
241 height = font_size * NUM_LINES;
243 /* Use at least the requisition size... */
245 gtk_widget_size_request (widget, &req);
246 width = MAX (width, req.width);
247 height = MAX (height, req.height);
249 /* ... but no larger than the monitor */
251 screen = gtk_widget_get_screen (widget);
252 monitor_num = gdk_screen_get_monitor_at_window (screen, widget->window);
254 gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
256 width = MIN (width, monitor.width * 3 / 4);
257 height = MIN (height, monitor.height * 3 / 4);
261 gtk_window_get_default_size (window, &default_width, &default_height);
263 gtk_window_set_default_size (window,
264 (default_width == -1) ? width : default_width,
265 (default_height == -1) ? height : default_height);
269 gtk_file_chooser_dialog_realize (GtkWidget *widget)
271 GTK_WIDGET_CLASS (parent_class)->realize (widget);
272 set_default_size (GTK_FILE_CHOOSER_DIALOG (widget));
276 gtk_file_chooser_dialog_style_set (GtkWidget *widget,
277 GtkStyle *previous_style)
281 if (GTK_WIDGET_CLASS (parent_class)->style_set)
282 GTK_WIDGET_CLASS (parent_class)->style_set (widget, previous_style);
284 if (GTK_WIDGET_REALIZED (widget))
285 set_default_size (GTK_FILE_CHOOSER_DIALOG (widget));
287 dialog = GTK_DIALOG (widget);
289 /* Override the style properties with HIG-compliant spacings. Ugh.
290 * http://developer.gnome.org/projects/gup/hig/1.0/layout.html#layout-dialogs
291 * http://developer.gnome.org/projects/gup/hig/1.0/windows.html#alert-spacing
294 gtk_container_set_border_width (GTK_CONTAINER (dialog->vbox), 12);
295 gtk_box_set_spacing (GTK_BOX (dialog->vbox), 24);
297 gtk_container_set_border_width (GTK_CONTAINER (dialog->action_area), 0);
298 gtk_box_set_spacing (GTK_BOX (dialog->action_area), 6);
302 gtk_file_chooser_dialog_screen_changed (GtkWidget *widget,
303 GdkScreen *previous_screen)
305 if (GTK_WIDGET_CLASS (parent_class)->screen_changed)
306 GTK_WIDGET_CLASS (parent_class)->screen_changed (widget, previous_screen);
308 if (GTK_WIDGET_REALIZED (widget))
309 set_default_size (GTK_FILE_CHOOSER_DIALOG (widget));
313 gtk_file_chooser_dialog_new_valist (const gchar *title,
315 GtkFileChooserAction action,
316 const gchar *backend,
317 const gchar *first_button_text,
321 const char *button_text = first_button_text;
324 result = g_object_new (GTK_TYPE_FILE_CHOOSER_DIALOG,
327 "file-system-backend", backend,
331 gtk_window_set_transient_for (GTK_WINDOW (result), parent);
335 response_id = va_arg (varargs, gint);
336 gtk_dialog_add_button (GTK_DIALOG (result), button_text, response_id);
337 button_text = va_arg (varargs, const gchar *);
344 * gtk_file_chooser_dialog_new:
345 * @title: Title of the dialog, or %NULL
346 * @parent: Transient parent of the dialog, or %NULL
347 * @action: Open or save mode for the dialog
348 * @first_button_text: stock ID or text to go in the first button, or %NULL
349 * @Varargs: response ID for the first button, then additional (button, id) pairs, ending with %NULL
351 * Creates a new #GtkFileChooserDialog. This function is analogous to
352 * gtk_dialog_new_with_buttons().
354 * Return value: a new #GtkFileChooserDialog
359 gtk_file_chooser_dialog_new (const gchar *title,
361 GtkFileChooserAction action,
362 const gchar *first_button_text,
368 va_start (varargs, first_button_text);
369 result = gtk_file_chooser_dialog_new_valist (title, parent, action,
370 NULL, first_button_text,
378 * gtk_file_chooser_dialog_new_with_backend:
379 * @title: Title of the dialog, or %NULL
380 * @parent: Transient parent of the dialog, or %NULL
381 * @backend: The name of the specific filesystem backend to use.
382 * @action: Open or save mode for the dialog
383 * @first_button_text: stock ID or text to go in the first button, or %NULL
384 * @Varargs: response ID for the first button, then additional (button, id) pairs, ending with %NULL
386 * Creates a new #GtkFileChooserDialog with a specified backend. This is
387 * especially useful if you use gtk_file_chooser_set_local_only() to allow
388 * non-local files and you use a more expressive vfs, such as gnome-vfs,
391 * Return value: a new #GtkFileChooserDialog
396 gtk_file_chooser_dialog_new_with_backend (const gchar *title,
398 GtkFileChooserAction action,
399 const gchar *backend,
400 const gchar *first_button_text,
406 va_start (varargs, first_button_text);
407 result = gtk_file_chooser_dialog_new_valist (title, parent, action,
408 backend, first_button_text,