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