1 /* gtkam-save.c
2  *
3  * Copyright 2001,2002      Lutz Mueller <lutz@users.sf.net>
4  * Copyright 2003,2004,2005 Andrew Burton <adburton@users.sourceforge.net>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program. If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include "config.h"
21 #include "gtkam-save.h"
22 #include "i18n.h"
23 
24 #include <stdio.h>
25 #include <string.h>
26 #include <stdlib.h>
27 
28 #include <gtk/gtk.h>
29 #include <gtk/gtktogglebutton.h>
30 #include <gtk/gtkbutton.h>
31 #include <gtk/gtkhbox.h>
32 #include <gtk/gtkvbox.h>
33 #include <gtk/gtkframe.h>
34 #include <gtk/gtkentry.h>
35 #include <gtk/gtkwindow.h>
36 #include <gtk/gtkspinbutton.h>
37 #include <gtk/gtktooltips.h>
38 #include <gtk/gtkcheckbutton.h>
39 #include <gtk/gtklabel.h>
40 
41 #include <gphoto2/gphoto2-setting.h>
42 
43 #include "util.h"
44 
45 #include "gtkam-cancel.h"
46 #include "gtkam-close.h"
47 #include "gtkam-error.h"
48 #include "gtkam-status.h"
49 
50 typedef struct _GtkamSaveData GtkamSaveData;
51 struct _GtkamSaveData {
52 	GtkamCamera *camera;
53 	gchar *folder;
54 	gchar *name;
55 };
56 
57 
58 struct _GtkamSavePrivate
59 {
60 	GSList *data;
61 	GString *filelist;
62 
63 	GtkToggleButton *toggle_preview, *toggle_normal, *toggle_raw,
64 			*toggle_audio, *toggle_exif;
65 	GtkToggleButton *toggle_filename_camera;
66 	GtkEntry *program;
67 
68 	GtkWidget *spin_entry, *prefix_entry, *hbox_prefix;
69 
70 	gboolean quiet, err_shown;
71 
72 	GtkWidget *status;
73 	GtkWindow *main_window;
74 };
75 
76 #define PARENT_TYPE GTK_TYPE_FILE_CHOOSER_DIALOG
77 static GtkFileChooserDialog *parent_class;
78 
79 static void
gtkam_save_destroy(GtkObject * object)80 gtkam_save_destroy (GtkObject *object)
81 {
82 	GtkamSave *save = GTKAM_SAVE (object);
83 	gint i;
84 	GtkamSaveData *data;
85 
86 	if (save->priv->data) {
87 		for (i = g_slist_length (save->priv->data) - 1; i >= 0; i--) {
88 			data = g_slist_nth_data (save->priv->data, i);
89 			g_object_unref (G_OBJECT (data->camera));
90 			g_free (data->folder);
91 			g_free (data->name);
92 			g_free (data);
93 		}
94 		g_slist_free (save->priv->data);
95 		save->priv->data = NULL;
96 	}
97 
98 	GTK_OBJECT_CLASS (parent_class)->destroy (object);
99 }
100 
101 static void
gtkam_save_finalize(GObject * object)102 gtkam_save_finalize (GObject *object)
103 {
104 	GtkamSave *save = GTKAM_SAVE (object);
105 
106 	g_free (save->priv);
107 
108 	G_OBJECT_CLASS (parent_class)->finalize (object);
109 }
110 
111 static void
gtkam_save_class_init(gpointer g_class,gpointer class_data)112 gtkam_save_class_init (gpointer g_class, gpointer class_data)
113 {
114 	GtkObjectClass *object_class;
115 	GObjectClass *gobject_class;
116 
117 	object_class = GTK_OBJECT_CLASS (g_class);
118 	object_class->destroy  = gtkam_save_destroy;
119 
120 	gobject_class = G_OBJECT_CLASS (g_class);
121 	gobject_class->finalize = gtkam_save_finalize;
122 
123 	parent_class = g_type_class_peek_parent (g_class);
124 }
125 
126 static void
gtkam_save_init(GTypeInstance * instance,gpointer g_class)127 gtkam_save_init (GTypeInstance *instance, gpointer g_class)
128 {
129 	GtkamSave *save = GTKAM_SAVE (instance);
130 
131 	save->priv = g_new0 (GtkamSavePrivate, 1);
132 }
133 
134 GType
gtkam_save_get_type(void)135 gtkam_save_get_type (void)
136 {
137 	static GType type = 0;
138 
139 	if (!type) {
140 		GTypeInfo ti;
141 
142 		memset (&ti, 0, sizeof (GTypeInfo));
143 		ti.class_size     = sizeof (GtkamSaveClass);
144 		ti.class_init     = gtkam_save_class_init;
145 		ti.instance_size  = sizeof (GtkamSave);
146 		ti.instance_init  = gtkam_save_init;
147 
148 		type = g_type_register_static (PARENT_TYPE, "GtkamSave",
149 				&ti, 0);
150 	}
151 
152 	return (type);
153 }
154 
155 static void
on_cancel_clicked(GtkButton * button,GtkamSave * save)156 on_cancel_clicked (GtkButton *button, GtkamSave *save)
157 {
158 	gtk_widget_destroy (GTK_WIDGET (save));
159 }
160 
161 static int
default_numbering_start(const GtkamSave * save)162 default_numbering_start(const GtkamSave *save)
163 {
164 	GDir *dir;
165 	const gchar *file;
166 	gchar *tail,*prefix;
167 	int max = 1;
168 	int plen, current;
169 	gchar *filename ;
170 
171 	filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (save));
172 	if (filename == NULL) return 1;
173 	if (!(dir = g_dir_open (filename , 0, NULL))) return 1;
174 	prefix = g_strdup (gtk_entry_get_text
175 					(GTK_ENTRY (save->priv->prefix_entry)));
176 	plen = strlen (prefix);
177 	while ((file = g_dir_read_name (dir))) {
178 		/* compare prefix */
179 		if (strncmp (prefix, file, plen)) continue;
180 		/* check number */
181 		current = strtol (file+plen, &tail, 10);
182 		if (tail - (file + plen) != 4) continue;
183 		/* FIXME: check for regular file here */
184 		if (max <= current) max = current + 1;
185 	}
186 
187 	g_free (prefix);
188 	g_dir_close (dir);
189 	return max;
190 }
191 
192 static void
on_filename_camera_toggled(GtkToggleButton * toggle,GtkamSave * save)193 on_filename_camera_toggled (GtkToggleButton *toggle, GtkamSave *save)
194 {
195 	/*
196 	 * Give the users the possibility to specify prefix and numbering.
197 	 * No direct entry of filename is allowed.
198 	 */
199 	gtk_widget_show (save->priv->hbox_prefix);
200 	gtk_widget_set_sensitive (GTK_WIDGET (save->priv->prefix_entry),
201 			!toggle->active);
202 	gtk_widget_set_sensitive (GTK_WIDGET (save->priv->spin_entry),
203 			!toggle->active);
204 	if (!toggle->active) {
205 		/* Calculate default start number */
206 		gtk_spin_button_set_value (
207 			GTK_SPIN_BUTTON (save->priv->spin_entry),
208 			default_numbering_start (save));
209 	}
210 }
211 
212 static gchar *
create_full_filename(const gchar * filename,CameraFileType type)213 create_full_filename (const gchar *filename, CameraFileType type)
214 {
215 	gchar *full_filename;
216 
217 	switch (type) {
218 	case GP_FILE_TYPE_PREVIEW:
219 		full_filename = g_strdup_printf ("thumb_%s", filename);
220 		break;
221 	case GP_FILE_TYPE_RAW:
222 		full_filename = g_strdup_printf ("raw_%s", filename);
223 		break;
224 	case GP_FILE_TYPE_AUDIO:
225 		full_filename = g_strdup_printf ("audio_%s", filename);
226 		break;
227 	case GP_FILE_TYPE_EXIF:
228 		full_filename = g_strdup_printf ("exif_%s", filename);
229 		break;
230 	default:
231 		full_filename = g_strdup (filename);
232 		break;
233 	}
234 
235 	return (full_filename);
236 }
237 
238 static gchar *
concat_dir_and_file(const gchar * dirname,const gchar * filename)239 concat_dir_and_file (const gchar *dirname, const gchar *filename)
240 {
241 	gchar *full_path;
242 
243 	if (!strcmp (dirname, "/"))
244 		full_path = g_strdup_printf ("/%s", filename);
245 	else if (dirname[strlen (dirname) - 1] == '/')
246 		full_path = g_strdup_printf ("%s%s", dirname, filename);
247 	else
248 		full_path = g_strdup_printf ("%s/%s", dirname, filename);
249 	return (full_path);
250 }
251 
252 static int
save_file(GtkamSave * save,const char * filename,CameraFile * file,CameraFileType type,guint n)253 save_file (GtkamSave *save, const char *filename, CameraFile *file, CameraFileType type, guint n)
254 {
255 	gchar *full_path, *full_filename, *msg, *number_filename;
256 	const char *mime_type;
257 	const gchar *fsel_path, *prefix, *suffix;
258 	GtkWidget *dialog;
259 	int result;
260 
261 	gp_file_get_mime_type (file, &mime_type);
262 
263 	fsel_path = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (save));
264 
265 	if ((save->priv->toggle_filename_camera->active) ||
266 		(g_slist_length (save->priv->data) == 1)) {
267 
268 		/* Use filename provided by the CameraFile */
269 		full_filename = create_full_filename (filename, type);
270 
271 		if (g_slist_length (save->priv->data) == 1)
272 			full_path = g_strdup(fsel_path);
273 		else
274 			full_path = concat_dir_and_file (fsel_path, full_filename);
275 
276 		g_free (full_filename);
277 
278 	} else {
279 		/* Use filename in prefix */
280 		prefix = g_locale_from_utf8 (gtk_entry_get_text
281 					(GTK_ENTRY (save->priv->prefix_entry)), -1,
282 					NULL, NULL, NULL);
283 
284 		suffix = strrchr (mime_type, '/');
285 		suffix++;
286 		number_filename = g_strdup_printf ("%s%04i.%s", prefix,
287 								n, suffix);
288 		full_filename = create_full_filename (number_filename,
289 								type);
290 		g_free (number_filename);
291 
292 		full_path = concat_dir_and_file (fsel_path,
293 							full_filename);
294 		g_free (full_filename);
295 	}
296 
297 	/* FIXME Check which is user, and prompt the user */
298 	if (!save->priv->quiet && file_exists (full_path)) {
299 		msg = g_strdup_printf (_("The file '%s' already exists."),
300 				       full_path);
301 		if (!save->priv->err_shown) {
302 			dialog = gtkam_error_new (GP_ERROR_FILE_EXISTS, NULL, GTK_WIDGET (save), msg);
303 			gtk_window_set_transient_for (GTK_WINDOW (dialog),
304 						      save->priv->main_window);
305 			gtk_widget_show (dialog);
306 			g_free (msg);
307 			g_free (full_path);
308 			save->priv->err_shown = TRUE;
309 		}
310 		return -1;
311 	}
312 
313 	/* FIXME Check for sufficient disk space for this file, or
314 	   calculate total disk space required for all files before
315 	   save process starts */
316 
317 	result = gp_file_save (file, full_path);
318 	if (result < 0) {
319 		if (!save->priv->err_shown) {
320 			dialog = gtkam_error_new (result, NULL, GTK_WIDGET (save),
321 					_("Could not save file to '%s'."), full_path);
322 			gtk_widget_show (dialog);
323 			save->priv->err_shown = TRUE;
324 		}
325 	} else {
326 		/* Add the file to the list of files to be opened with
327 		   the specified external program */
328 		if (!save->priv->filelist)
329 				save->priv->filelist = g_string_new ("");
330 		g_string_append_printf (save->priv->filelist, " %s", full_path);
331 	}
332 
333 	g_free (full_path);
334 
335 	return result;
336 }
337 
338 static int
get_file(GtkamSave * save,GtkamCamera * camera,const gchar * folder,const gchar * name,CameraFileType type,guint n,GtkamContext * context)339 get_file (GtkamSave *save, GtkamCamera *camera,
340 	  const gchar *folder, const gchar *name, CameraFileType type, guint n,
341 	  GtkamContext *context)
342 {
343 	int result;
344 	GtkWidget *dialog;
345 	CameraFile *file;
346 
347 	gp_file_new (&file);
348 	result = gp_camera_file_get (camera->camera, folder, name, type, file,
349 				     context->context);
350 	if (camera->multi)
351 		gp_camera_exit (camera->camera, NULL);
352 	switch (result) {
353 	case GP_OK:
354 		result = save_file (save, name, file, type, n);
355 		break;
356 	case GP_ERROR_CANCEL:
357 		break;
358 	default:
359 		if (!save->priv->err_shown) {
360 			dialog = gtkam_error_new (result, context,
361 				GTK_WIDGET (save), _("Could not get '%s' "
362 				"from folder '%s'."),
363 				name, folder);
364 			gtk_widget_show (dialog);
365 			save->priv->err_shown = TRUE;
366 		}
367 	}
368 	gp_file_unref (file);
369 
370 	return result;
371 }
372 
373 static void
store_save_settings(GtkamSave * save)374 store_save_settings(GtkamSave *save)
375 {
376 	gchar *savedir,*t;
377 	gchar buf[5];
378 
379 	/* Directory */
380 	savedir = g_strdup (gtk_file_chooser_get_filename (
381 			      GTK_FILE_CHOOSER (save)));
382 	if (savedir) {
383 		if (strlen (savedir) > 255)
384 			savedir[255] = '\0';
385 
386 		if (!g_file_test (savedir, G_FILE_TEST_IS_DIR)) {
387 			t = g_path_get_dirname (savedir);
388 			g_free (savedir);
389 			savedir = t;
390 		}
391 		gp_setting_set ("gtkam", "save-dir", savedir);
392 		g_free (savedir);
393 	}
394 
395 	/* toggle buttons */
396 #define STORE_TOGGLE(NAME) \
397 	snprintf(buf,sizeof(buf), "%d", gtk_toggle_button_get_active(	\
398 		save->priv->toggle_ ## NAME)); 				\
399 	gp_setting_set("gtkam","save-" #NAME,buf)
400 
401 	STORE_TOGGLE(preview);
402 	STORE_TOGGLE(normal);
403 	STORE_TOGGLE(raw);
404 	STORE_TOGGLE(audio);
405 	STORE_TOGGLE(exif);
406 	STORE_TOGGLE(filename_camera);
407 
408 	/* prefix entry */
409 	if (g_slist_length (save->priv->data) > 1) {
410 		/* only when saving several files */
411 		gp_setting_set("gtkam", "save-prefix", (gchar *)
412 			gtk_entry_get_text (GTK_ENTRY (save->priv->prefix_entry)));
413 	}
414 }
415 
416 static void
load_save_settings(GtkamSave * save)417 load_save_settings(GtkamSave *save)
418 {
419 	gchar buf[1024];
420 	gchar *dir;
421 
422 	/* directory */
423 	if (gp_setting_get("gtkam","save-dir",buf) == GP_OK) {
424 		dir = g_strdup (buf);
425 		strcat (buf, G_DIR_SEPARATOR_S);
426 		gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (save), buf);
427 	} else {
428 		dir = g_strdup (gtk_file_chooser_get_filename (
429 			GTK_FILE_CHOOSER (save)));
430 	}
431 	/* prefix entry */
432 	gp_setting_get ("gtkam", "save-prefix", buf);
433 	gtk_entry_set_text (GTK_ENTRY (save->priv->prefix_entry), buf);
434 
435 	/* toggle buttons */
436 #define LOAD_TOGGLE(NAME) \
437 	gp_setting_get("gtkam","save-" #NAME,buf); 			\
438 	gtk_toggle_button_set_active(save->priv->toggle_ ## NAME, atoi(buf))
439 
440 	LOAD_TOGGLE(preview);
441 	LOAD_TOGGLE(normal);
442 	LOAD_TOGGLE(raw);
443 	LOAD_TOGGLE(audio);
444 	LOAD_TOGGLE(exif);
445 	LOAD_TOGGLE(filename_camera);
446 	g_free(dir);
447 }
448 
449 static int
count_items(GtkamSave * save)450 count_items (GtkamSave *save)
451 {
452 	int items_to_save = 0;
453 
454 	if (save->priv->toggle_normal &&
455 		    save->priv->toggle_normal->active)
456 		items_to_save++;
457 
458 	if (save->priv->toggle_preview &&
459 	    save->priv->toggle_preview->active)
460 		items_to_save++;
461 
462 	if (save->priv->toggle_raw &&
463 	    save->priv->toggle_raw->active)
464 		items_to_save++;
465 
466 	if (save->priv->toggle_audio &&
467 	    save->priv->toggle_audio->active)
468 		items_to_save++;
469 
470 	if (save->priv->toggle_exif &&
471 	    save->priv->toggle_exif->active)
472 		items_to_save++;
473 
474 	return items_to_save;
475 }
476 
477 static void
on_ok_clicked(GtkButton * button,GtkamSave * save)478 on_ok_clicked (GtkButton *button, GtkamSave *save)
479 {
480 	guint i, count, j = 1;
481 	int result = -1;
482 	GtkWidget *s, *dialog;
483 	unsigned int id = 0;
484 	GtkamSaveData *data;
485 	gchar *command;
486 	const gchar *progname;
487 	GError *error = NULL;
488 
489 	if (count_items (save) == 0) {
490 		if (!save->priv->err_shown) {
491 
492 			dialog = gtkam_error_new (result, NULL,
493 					GTK_WIDGET (save), _("There is nothing to be saved."));
494 			gtk_widget_show (dialog);
495 		}
496 
497 		return;
498 	}
499 
500 	store_save_settings(save);
501 	gtk_widget_hide (GTK_WIDGET (save));
502 
503 	count = g_slist_length (save->priv->data);
504 	if (count == 1)
505 		s = gtkam_cancel_new (_("Downloading file"));
506 	else
507 		s = gtkam_cancel_new (_("Downloading %i files"), count);
508 	gtk_window_set_transient_for (GTK_WINDOW (s), save->priv->main_window);
509 	gtk_widget_show (s);
510 
511 	if (count > 1)
512 		id = gp_context_progress_start (
513 			GTKAM_CANCEL (s)->context->context, count,
514 			_("Downloading %i files..."), count);
515 
516 	if (!save->priv->toggle_filename_camera->active)
517 		j = gtk_spin_button_get_value_as_int (
518 				GTK_SPIN_BUTTON (save->priv->spin_entry));
519 
520 	for (i = 0; i < count; i++) {
521 		data = g_slist_nth_data (save->priv->data, i);
522 
523 		/* Check for shutdown */
524 		if (!GTKAM_IS_SAVE (save))
525 			return;
526 
527 		if (save->priv->toggle_normal &&
528 		    save->priv->toggle_normal->active)
529 			result = get_file (save, data->camera,
530 				  data->folder, data->name,
531 				  GP_FILE_TYPE_NORMAL, i + j,
532 				  GTKAM_CANCEL (s)->context);
533 		if (save->priv->toggle_preview &&
534 		    save->priv->toggle_preview->active &&
535 		    (!result < 0))
536 			result = get_file (save, data->camera,
537 				  data->folder, data->name,
538 				  GP_FILE_TYPE_PREVIEW, i + j,
539 				  GTKAM_CANCEL (s)->context);
540 		if (save->priv->toggle_raw &&
541 		    save->priv->toggle_raw->active &&
542 		    (!result < 0))
543 			result = get_file (save, data->camera,
544 				  data->folder, data->name, GP_FILE_TYPE_RAW,
545 				  i + j, GTKAM_CANCEL (s)->context);
546 		if (save->priv->toggle_audio &&
547 		    save->priv->toggle_audio->active &&
548 		    (!result < 0))
549 			result = get_file (save, data->camera,
550 				  data->folder, data->name, GP_FILE_TYPE_AUDIO,
551 				  i + j, GTKAM_CANCEL (s)->context);
552 		if (save->priv->toggle_exif &&
553 		    save->priv->toggle_exif->active &&
554 		    (!result < 0))
555 			result = get_file (save, data->camera,
556 				  data->folder, data->name, GP_FILE_TYPE_EXIF,
557 				  i + j, GTKAM_CANCEL (s)->context);
558 
559 		if (result < 0)
560 		{
561 			if (count > 1)
562 				gp_context_progress_stop (GTKAM_CANCEL (s)->context->context, id);
563 			if (!save->priv->err_shown) {
564 				dialog = gtkam_error_new (result, GTKAM_CANCEL (s)->context,
565 						GTK_WIDGET (save), _("Problem getting '%s' "
566 						"from folder '%s'."),
567 						data->name, data->folder);
568 				gtk_widget_show (dialog);
569 				save->priv->err_shown = TRUE;
570 			}
571 
572 			gtk_object_destroy (GTK_OBJECT (s));
573 			gtk_object_destroy (GTK_OBJECT (save));
574 			return;
575 		}
576 
577 		if (count > 1)
578 			gp_context_progress_update (
579 				GTKAM_CANCEL (s)->context->context, id, i + 1);
580 		gp_context_idle (GTKAM_CANCEL (s)->context->context);
581 		if (gp_context_cancel (GTKAM_CANCEL (s)->context->context) ==
582 				GP_CONTEXT_FEEDBACK_CANCEL)
583 			break;
584 	}
585 	if (count > 1)
586 		gp_context_progress_stop (
587 				GTKAM_CANCEL (s)->context->context, id);
588 
589 	gtk_object_destroy (GTK_OBJECT (s));
590 
591 	/* If file(s) were saved and a program specified, load the program
592    passing the filenames */
593 	if (result >= 0)
594 	{
595 		progname = gtk_entry_get_text (save->priv->program);
596 
597 		if (progname && progname[0] != '\0') {
598 			command = g_strdup_printf ("%s%s", progname, save->priv->filelist->str);
599 
600 			/* FIXME Report any arising errors */
601 			if (!g_spawn_command_line_async (command, &error)) {
602 				g_warning ("Error running command\n");
603 				g_error_free (error);
604 			}
605 
606 			g_free (command);
607 			g_string_free (save->priv->filelist, TRUE);
608 		}
609 	}
610 
611 	gtk_object_destroy (GTK_OBJECT (save));
612 }
613 
614 GtkWidget *
gtkam_save_new(GtkWindow * main_window)615 gtkam_save_new (GtkWindow *main_window)
616 {
617 	GtkamSave *save;
618 	GtkWidget *hbox, *frame, *main_vbox, *check, *label, *entry, *button;
619 	GtkObject *a;
620 	GtkTooltips *tooltips;
621 
622 	save = g_object_new (GTKAM_TYPE_SAVE, NULL);
623 
624 	button = gtk_button_new_from_stock (GTK_STOCK_CANCEL);
625 	gtk_widget_show (button);
626 	g_signal_connect (GTK_OBJECT (button),
627 			  "clicked", GTK_SIGNAL_FUNC (on_cancel_clicked), save);
628 	gtk_container_add (GTK_CONTAINER (GTK_DIALOG (save)->action_area),
629 			   button);
630 
631 	button = gtk_button_new_from_stock (GTK_STOCK_OK);
632 	gtk_widget_show (button);
633 	g_signal_connect (GTK_OBJECT (button), "clicked",
634 			    GTK_SIGNAL_FUNC (on_ok_clicked), save);
635 	gtk_container_add (GTK_CONTAINER (GTK_DIALOG (save)->action_area),
636 			   button);
637 
638 	tooltips = gtk_tooltips_new ();
639 
640 	frame = gtk_frame_new (_("What to save:"));
641 	gtk_widget_show (frame);
642 	gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER (save), frame);
643 
644 	main_vbox = gtk_vbox_new (TRUE, 5);
645 	gtk_widget_show (main_vbox);
646 	gtk_container_add (GTK_CONTAINER (frame), main_vbox);
647 
648 	hbox = gtk_hbox_new (TRUE, 5);
649 	gtk_widget_show (hbox);
650 	gtk_container_add (GTK_CONTAINER (main_vbox), hbox);
651 
652 	check = gtk_check_button_new_with_label (_("Save photos"));
653 	gtk_widget_show (check);
654 	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check), TRUE);
655 	gtk_box_pack_start (GTK_BOX (hbox), check, TRUE, TRUE, 0);
656 	gtk_tooltips_set_tip (tooltips, check, _("Photos will be saved if "
657 			      "this is checked"), NULL);
658 	save->priv->toggle_normal = GTK_TOGGLE_BUTTON (check);
659 
660 	check = gtk_check_button_new_with_label (_("Save raw data"));
661 	gtk_widget_show (check);
662 	gtk_box_pack_start (GTK_BOX (hbox), check, TRUE, TRUE, 0);
663 	gtk_tooltips_set_tip (tooltips, check, _("Raw data will be "
664 			      "saved if this is checked"), NULL);
665 	save->priv->toggle_raw = GTK_TOGGLE_BUTTON (check);
666 
667 	check = gtk_check_button_new_with_label (_("Save audio data"));
668 	gtk_widget_show (check);
669 	gtk_box_pack_start (GTK_BOX (hbox), check, TRUE, TRUE, 0);
670 	gtk_tooltips_set_tip (tooltips, check, _("Audio data will be "
671 			      "saved if this is checked"), NULL);
672 	save->priv->toggle_audio = GTK_TOGGLE_BUTTON (check);
673 
674 	check = gtk_check_button_new_with_label (_("Save thumbnails"));
675 	gtk_widget_show (check);
676 	gtk_box_pack_start (GTK_BOX (hbox), check, TRUE, TRUE, 0);
677 	gtk_tooltips_set_tip (tooltips, check, _("Thumbnails will be "
678 			      "saved if this is checked"), NULL);
679 	save->priv->toggle_preview = GTK_TOGGLE_BUTTON (check);
680 
681 	check = gtk_check_button_new_with_label (_("Save EXIF data"));
682 	gtk_widget_show (check);
683 	gtk_box_pack_start (GTK_BOX (hbox), check, TRUE, TRUE, 0);
684 	gtk_tooltips_set_tip (tooltips, check, _("EXIF data will be "
685 		"saved if this is checked"), NULL);
686 	save->priv->toggle_exif = GTK_TOGGLE_BUTTON (check);
687 
688 	hbox = gtk_hbox_new (FALSE, 0);
689 	gtk_widget_show (hbox);
690 	gtk_box_pack_start (GTK_BOX (main_vbox),
691 			    hbox, TRUE, TRUE, 0);
692 
693 	label = gtk_label_new (_("Open image(s) with: "));
694 	gtk_widget_show (label);
695 	gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
696 
697 	entry = gtk_entry_new ();
698 	gtk_widget_show (entry);
699 	gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0);
700 	gtk_tooltips_set_tip (tooltips, entry, _("Type in the name of the "
701 			      "program you want to run, leave blank "
702 			      "for none"), NULL);
703 	save->priv->program = GTK_ENTRY (entry);
704 
705 	/* Filenames provided by camera */
706 	check = gtk_check_button_new_with_label (_("Use filename(s) provided by the camera"));
707 	gtk_widget_show (check);
708 	gtk_box_pack_start (GTK_BOX (main_vbox),
709 			    check, TRUE, TRUE, 0);
710 	gtk_tooltips_set_tip (tooltips, check, _("Choose whether to use the "
711 			      "filename provided by the camera"), NULL);
712 	save->priv->toggle_filename_camera = GTK_TOGGLE_BUTTON (check);
713 	gtk_toggle_button_set_active (save->priv->toggle_filename_camera, TRUE);
714 	g_signal_connect (G_OBJECT (check), "toggled",
715 			  G_CALLBACK (on_filename_camera_toggled), save);
716 
717 	hbox = gtk_hbox_new (FALSE, 5);
718 	gtk_widget_show (hbox);
719 	gtk_box_pack_start (GTK_BOX (main_vbox),
720 			    hbox, TRUE, TRUE, 0);
721 
722 	save->priv->hbox_prefix = hbox;
723 
724 	label = gtk_label_new (_("Filename prefix: "));
725 	gtk_widget_show (label);
726 	gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
727 
728 	save->priv->prefix_entry = gtk_entry_new ();
729 	gtk_widget_show (save->priv->prefix_entry);
730 	gtk_box_pack_start (GTK_BOX (hbox), save->priv->prefix_entry,
731 			    TRUE, TRUE, 0);
732 
733 	label = gtk_label_new (_("Start numbering with: "));
734 	gtk_widget_show (label);
735 	gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
736 
737 	a = gtk_adjustment_new (1.0, 1.0, 10000.0, 1.0, 10.0, 10.0);
738 	save->priv->spin_entry = gtk_spin_button_new (GTK_ADJUSTMENT (a),
739 				 1.0, 0);
740 	gtk_widget_show (save->priv->spin_entry);
741 	gtk_box_pack_start (GTK_BOX (hbox), save->priv->spin_entry,
742 			    FALSE, FALSE, 0);
743 
744 	load_save_settings(save);
745 
746 	/* Remember the main window (if given) */
747 	save->priv->main_window = main_window ? main_window : GTK_WINDOW (save);
748 
749 	return (GTK_WIDGET (save));
750 }
751 
752 void
gtkam_save_add(GtkamSave * save,GtkamCamera * camera,const gchar * folder,const gchar * name)753 gtkam_save_add (GtkamSave *save, GtkamCamera *camera,
754 		const gchar *folder, const gchar *name)
755 {
756 	GtkamSaveData *data;
757 	gchar *title;
758 
759 	g_return_if_fail (GTKAM_IS_SAVE (save));
760 	g_return_if_fail (GTKAM_IS_CAMERA (camera));
761 	g_return_if_fail (folder != NULL);
762 	g_return_if_fail (name != NULL);
763 
764 	data = g_new0 (GtkamSaveData, 1);
765 	data->camera = camera;
766 	g_object_ref (G_OBJECT (camera));
767 	data->folder = g_strdup (folder);
768 	data->name = g_strdup (name);
769 	save->priv->data = g_slist_append (save->priv->data, data);
770 
771 	switch (g_slist_length (save->priv->data)) {
772 	case 1:
773 
774 		/* First case: We have only one file. */
775 		title = g_strdup_printf (_("Save '%s'..."), name);
776 		gtk_window_set_title (GTK_WINDOW (save), title);
777 		g_free (title);
778 
779 		gtk_widget_hide ( GTK_WIDGET(save->priv->toggle_filename_camera));
780 
781 		gtk_widget_hide (save->priv->hbox_prefix);
782 		gtk_widget_set_sensitive (save->priv->spin_entry, FALSE);
783 		gtk_widget_set_sensitive (save->priv->prefix_entry, FALSE);
784 
785 		gtk_file_chooser_set_action(GTK_FILE_CHOOSER (save),
786 				GTK_FILE_CHOOSER_ACTION_SAVE);
787 
788 		gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (save), name);
789 
790 		break;
791 
792 	default:
793 
794 		/* Second case: We have multiple files to save. */
795 		gtk_window_set_title (GTK_WINDOW (save), _("Save photos..."));
796 
797 		gtk_widget_show (GTK_WIDGET (save->priv->toggle_filename_camera));
798 
799 		gtk_widget_show (save->priv->hbox_prefix);
800 		gtk_widget_set_sensitive (save->priv->spin_entry,
801 				!save->priv->toggle_filename_camera->active);
802 		gtk_widget_set_sensitive (save->priv->prefix_entry,
803 				!save->priv->toggle_filename_camera->active);
804 		gtk_file_chooser_set_action(GTK_FILE_CHOOSER (save),
805 				GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
806 
807 		break;
808 	}
809 }
810