1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2
3 /*
4 * GThumb
5 *
6 * Copyright (C) 2009 The Free Software Foundation, Inc.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include <config.h>
23 #include <stdlib.h>
24 #include <glib/gi18n.h>
25 #include <gtk/gtk.h>
26 #include "glib-utils.h"
27 #include "gth-file-chooser-dialog.h"
28 #include "gth-main.h"
29 #include "gth-preferences.h"
30 #include "gtk-utils.h"
31
32
33 #define FORMAT_KEY "gthumb-format"
34
35
36 typedef struct {
37 GthImageSaver *saver;
38 char **extensions;
39 } Format;
40
41
42 static void
format_free(Format * format)43 format_free (Format *format)
44 {
45 g_object_unref (format->saver);
46 g_strfreev (format->extensions);
47 g_free (format);
48 }
49
50
51 struct _GthFileChooserDialogPrivate {
52 GList *supported_formats;
53 GtkWidget *options_checkbutton;
54 };
55
56
G_DEFINE_TYPE_WITH_CODE(GthFileChooserDialog,gth_file_chooser_dialog,GTK_TYPE_FILE_CHOOSER_DIALOG,G_ADD_PRIVATE (GthFileChooserDialog))57 G_DEFINE_TYPE_WITH_CODE (GthFileChooserDialog,
58 gth_file_chooser_dialog,
59 GTK_TYPE_FILE_CHOOSER_DIALOG,
60 G_ADD_PRIVATE (GthFileChooserDialog))
61
62
63 static void
64 gth_file_chooser_dialog_finalize (GObject *object)
65 {
66 GthFileChooserDialog *self;
67
68 self = GTH_FILE_CHOOSER_DIALOG (object);
69
70 g_list_foreach (self->priv->supported_formats, (GFunc) format_free, NULL);
71 g_list_free (self->priv->supported_formats);
72
73 G_OBJECT_CLASS (gth_file_chooser_dialog_parent_class)->finalize (object);
74 }
75
76
77 static void
gth_file_chooser_dialog_unmap(GtkWidget * widget)78 gth_file_chooser_dialog_unmap (GtkWidget *widget)
79 {
80 GthFileChooserDialog *self;
81 GSettings *settings;
82
83 self = GTH_FILE_CHOOSER_DIALOG (widget);
84
85 settings = g_settings_new (GTHUMB_SAVE_FILE_SCHEMA);
86 g_settings_set_boolean (settings, PREF_SAVE_FILE_SHOW_OPTIONS, gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (self->priv->options_checkbutton)));
87 g_object_unref (settings);
88
89 GTK_WIDGET_CLASS (gth_file_chooser_dialog_parent_class)->unmap (widget);
90 }
91
92
93 static void
gth_file_chooser_dialog_class_init(GthFileChooserDialogClass * class)94 gth_file_chooser_dialog_class_init (GthFileChooserDialogClass *class)
95 {
96 GObjectClass *object_class;
97 GtkWidgetClass *widget_class;
98
99 object_class = (GObjectClass*) class;
100 object_class->finalize = gth_file_chooser_dialog_finalize;
101
102 widget_class = (GtkWidgetClass*) class;
103 widget_class->unmap = gth_file_chooser_dialog_unmap;
104 }
105
106
107 static void
gth_file_chooser_dialog_init(GthFileChooserDialog * self)108 gth_file_chooser_dialog_init (GthFileChooserDialog *self)
109 {
110 self->priv = gth_file_chooser_dialog_get_instance_private (self);
111 self->priv->supported_formats = NULL;
112 }
113
114
115 static void
gth_file_chooser_dialog_construct(GthFileChooserDialog * self,const char * title,GtkWindow * parent,const char * allowed_savers)116 gth_file_chooser_dialog_construct (GthFileChooserDialog *self,
117 const char *title,
118 GtkWindow *parent,
119 const char *allowed_savers)
120 {
121 GtkFileFilter *filter;
122 GArray *savers;
123 int i;
124 GList *scan;
125 GSettings *settings;
126
127 if (title != NULL)
128 gtk_window_set_title (GTK_WINDOW (self), title);
129 if (parent != NULL)
130 gtk_window_set_transient_for (GTK_WINDOW (self), parent);
131
132 gtk_file_chooser_set_action (GTK_FILE_CHOOSER (self), GTK_FILE_CHOOSER_ACTION_SAVE);
133 gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (self), FALSE);
134 gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (self), TRUE);
135 gtk_dialog_set_default_response (GTK_DIALOG (self), GTK_RESPONSE_ACCEPT);
136
137 _gtk_dialog_add_to_window_group (GTK_DIALOG (self));
138
139 gtk_dialog_add_button (GTK_DIALOG (self), _GTK_LABEL_CANCEL, GTK_RESPONSE_CANCEL);
140 gtk_dialog_add_button (GTK_DIALOG (self), _GTK_LABEL_SAVE, GTK_RESPONSE_OK);
141
142 /* filters */
143
144 filter = gtk_file_filter_new ();
145 gtk_file_filter_set_name (filter, _("All Supported Files"));
146
147 savers = gth_main_get_type_set (allowed_savers);
148 for (i = 0; (savers != NULL) && (i < savers->len); i++) {
149 Format *format;
150 int e;
151
152 format = g_new (Format, 1);
153 format->saver = g_object_new (g_array_index (savers, GType, i), NULL);
154 format->extensions = g_strsplit (gth_image_saver_get_extensions (format->saver), " ", -1);
155 self->priv->supported_formats = g_list_prepend (self->priv->supported_formats, format);
156
157 for (e = 0; format->extensions[e] != NULL; e++) {
158 char *pattern = g_strconcat ("*.", format->extensions[e], NULL);
159 gtk_file_filter_add_pattern (filter, pattern);
160
161 g_free (pattern);
162 }
163
164 gtk_file_filter_add_mime_type (filter, gth_image_saver_get_mime_type (format->saver));
165 }
166
167 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (self), filter);
168 gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (self), filter);
169
170 self->priv->supported_formats = g_list_reverse (self->priv->supported_formats);
171 for (scan = self->priv->supported_formats; scan; scan = scan->next) {
172 Format *format = scan->data;
173 int i;
174
175 filter = gtk_file_filter_new ();
176 gtk_file_filter_set_name (filter, gth_image_saver_get_display_name (format->saver));
177
178 for (i = 0; format->extensions[i] != NULL; i++) {
179 char *pattern = g_strconcat ("*.", format->extensions[i], NULL);
180 gtk_file_filter_add_pattern (filter, pattern);
181
182 g_free (pattern);
183 }
184
185 gtk_file_filter_add_mime_type (filter, gth_image_saver_get_mime_type (format->saver));
186 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (self), filter);
187
188 g_object_set_data (G_OBJECT (filter), FORMAT_KEY, format);
189 }
190
191 /* extra widget */
192
193 settings = g_settings_new (GTHUMB_SAVE_FILE_SCHEMA);
194
195 self->priv->options_checkbutton = gtk_check_button_new_with_mnemonic (_("_Show Format Options"));
196 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (self->priv->options_checkbutton), g_settings_get_boolean (settings, PREF_SAVE_FILE_SHOW_OPTIONS));
197 gtk_widget_show (self->priv->options_checkbutton);
198 gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER (self), self->priv->options_checkbutton);
199
200 g_object_unref (settings);
201 }
202
203
204 GtkWidget *
gth_file_chooser_dialog_new(const char * title,GtkWindow * parent,const char * allowed_savers)205 gth_file_chooser_dialog_new (const char *title,
206 GtkWindow *parent,
207 const char *allowed_savers)
208 {
209 GthFileChooserDialog *self;
210
211 self = g_object_new (GTH_TYPE_FILE_CHOOSER_DIALOG, NULL);
212 gth_file_chooser_dialog_construct (self, title, parent, allowed_savers);
213
214 return (GtkWidget *) self;
215 }
216
217
218 static Format *
get_format_from_extension(GthFileChooserDialog * self,const char * filename)219 get_format_from_extension (GthFileChooserDialog *self,
220 const char *filename)
221 {
222 char *ext;
223 const char *only_ext;
224 GList *scan;
225
226 ext = _g_uri_get_extension (filename);
227 if (ext == NULL)
228 return NULL;
229
230 only_ext = (ext[0] == '.') ? ext + 1 : ext;
231
232 for (scan = self->priv->supported_formats; scan; scan = scan->next) {
233 Format *format = scan->data;
234 int i;
235
236 for (i = 0; format->extensions[i] != NULL; i++)
237 if (g_ascii_strcasecmp (only_ext, format->extensions[i]) == 0) {
238 g_free (ext);
239 return format;
240 }
241 }
242
243 g_free (ext);
244
245 return NULL;
246 }
247
248
249 static gboolean
_gth_file_chooser_change_format_options(GthFileChooserDialog * self,GthImageSaver * saver)250 _gth_file_chooser_change_format_options (GthFileChooserDialog *self,
251 GthImageSaver *saver)
252 {
253 GtkWidget *dialog;
254 GtkWidget *control;
255 gboolean result;
256
257 control = gth_image_saver_get_control (saver);
258 if (control == NULL)
259 return TRUE;
260
261 dialog = g_object_new (GTK_TYPE_DIALOG,
262 "title", _("Options"),
263 "transient-for", GTK_WINDOW (self),
264 "modal", TRUE,
265 "use-header-bar", _gtk_settings_get_dialogs_use_header (),
266 "default-width", 400,
267 NULL);
268 gtk_dialog_add_buttons (GTK_DIALOG (dialog),
269 _GTK_LABEL_CANCEL, GTK_RESPONSE_CANCEL,
270 _GTK_LABEL_SAVE, GTK_RESPONSE_OK,
271 NULL);
272 _gtk_dialog_add_class_to_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK, GTK_STYLE_CLASS_SUGGESTED_ACTION);
273 _gtk_dialog_add_to_window_group (GTK_DIALOG (dialog));
274
275 gtk_container_set_border_width (GTK_CONTAINER (control), 15);
276 gtk_widget_show (control);
277 gtk_container_add (GTK_CONTAINER (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), control);
278
279 result = gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK;
280 if (result)
281 gth_image_saver_save_options (saver);
282
283 gtk_widget_destroy (dialog);
284
285 return result;
286 }
287
288
289 gboolean
gth_file_chooser_dialog_get_file(GthFileChooserDialog * self,GFile ** file,const char ** mime_type)290 gth_file_chooser_dialog_get_file (GthFileChooserDialog *self,
291 GFile **file,
292 const char **mime_type)
293 {
294 char *filename;
295 Format *format;
296
297 filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (self));
298 format = get_format_from_extension (self, filename);
299 g_free (filename);
300
301 if (format == NULL) {
302 GtkFileFilter *filter;
303
304 filter = gtk_file_chooser_get_filter (GTK_FILE_CHOOSER (self));
305 format = g_object_get_data (G_OBJECT (filter), FORMAT_KEY);
306 }
307
308 if (format == NULL)
309 return FALSE;
310
311 if (file != NULL)
312 *file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (self));
313 if (mime_type != NULL)
314 *mime_type = gth_image_saver_get_mime_type (format->saver);
315
316 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (self->priv->options_checkbutton)))
317 return _gth_file_chooser_change_format_options (self, format->saver);
318 else
319 return TRUE;
320 }
321