1 /* gtkam-preview.c
2  *
3  * Copyright 2001,2002 Lutz Mueller <lutz@users.sf.net>
4  * Copyright 2002,2003 Patrick Mansfield <patmans@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-preview.h"
22 #include "i18n.h"
23 
24 #include <stdio.h>
25 #include <string.h>
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <fcntl.h>
29 
30 #include <gtk/gtktooltips.h>
31 #include <gtk/gtkvbox.h>
32 #include <gtk/gtklabel.h>
33 #include <gtk/gtkhbox.h>
34 #include <gtk/gtkcheckbutton.h>
35 #include <gtk/gtkspinbutton.h>
36 #include <gtk/gtkradiobutton.h>
37 #include <gtk/gtkbutton.h>
38 #include <gtk/gtkmain.h>
39 #include <gtk/gtksignal.h>
40 #include <gtk/gtkpixmap.h>
41 #include <gtk/gtkhscale.h>
42 #include <gtk/gtkimage.h>
43 #include <gtk/gtkstock.h>
44 
45 #include <gdk-pixbuf/gdk-pixbuf-loader.h>
46 
47 #include "gdk-pixbuf-hacks.h"
48 
49 #include "gtkam-config.h"
50 #include "gtkam-error.h"
51 #include "gtkam-status.h"
52 
53 struct _GtkamPreviewPrivate
54 {
55 	GtkWidget *spin;
56 	GtkWidget *image;
57 
58 	GtkamCamera *camera;
59 
60 	guint rotate;
61 
62 	GtkToggleButton *angle_0, *angle_90, *angle_180, *angle_270;
63 
64 	GtkCheckButton *check_download;
65 	GtkEntry *entry_download;
66 	GtkFileChooserButton *button_file;
67 
68 	guint32 timeout_id;
69 
70 	GtkTooltips *tooltips;
71 };
72 
73 #define PARENT_TYPE GTKAM_TYPE_DIALOG
74 static GtkamDialogClass *parent_class;
75 
76 enum {
77 	CAPTURED,
78 	LAST_SIGNAL
79 };
80 
81 static guint signals[LAST_SIGNAL] = {0};
82 
83 static void
gtkam_preview_destroy(GtkObject * object)84 gtkam_preview_destroy (GtkObject *object)
85 {
86 	GtkamPreview *preview = GTKAM_PREVIEW (object);
87 
88 	if (preview->priv->tooltips) {
89 		g_object_unref (G_OBJECT (preview->priv->tooltips));
90 		preview->priv->tooltips = NULL;
91 	}
92 
93 	if (preview->priv->timeout_id) {
94 		gtk_timeout_remove (preview->priv->timeout_id);
95 		preview->priv->timeout_id = 0;
96 	}
97 
98 	if (preview->priv->camera) {
99 		g_object_unref (G_OBJECT (preview->priv->camera));
100 		preview->priv->camera = NULL;
101 	}
102 
103 	GTK_OBJECT_CLASS (parent_class)->destroy (object);
104 }
105 
106 static void
gtkam_preview_finalize(GObject * object)107 gtkam_preview_finalize (GObject *object)
108 {
109 	GtkamPreview *preview = GTKAM_PREVIEW (object);
110 
111 	g_free (preview->priv);
112 
113 	G_OBJECT_CLASS (parent_class)->finalize (object);
114 }
115 
116 static void
gtkam_preview_class_init(gpointer g_class,gpointer class_data)117 gtkam_preview_class_init (gpointer g_class, gpointer class_data)
118 {
119 	GtkObjectClass *object_class;
120 	GObjectClass *gobject_class;
121 
122 	object_class = GTK_OBJECT_CLASS (g_class);
123 	object_class->destroy  = gtkam_preview_destroy;
124 
125 	gobject_class = G_OBJECT_CLASS (g_class);
126 	gobject_class->finalize = gtkam_preview_finalize;
127 
128 	signals[CAPTURED] = g_signal_new ("captured",
129 		G_TYPE_FROM_CLASS (g_class), G_SIGNAL_RUN_LAST,
130 		G_STRUCT_OFFSET (GtkamPreviewClass, captured), NULL, NULL,
131 		g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1,
132 		G_TYPE_POINTER);
133 
134 	parent_class = g_type_class_peek_parent (g_class);
135 }
136 
137 static void
gtkam_preview_init(GTypeInstance * instance,gpointer g_class)138 gtkam_preview_init (GTypeInstance *instance, gpointer g_class)
139 {
140 	GtkamPreview *preview = GTKAM_PREVIEW (instance);
141 
142 	preview->priv = g_new0 (GtkamPreviewPrivate, 1);
143 }
144 
145 GType
gtkam_preview_get_type(void)146 gtkam_preview_get_type (void)
147 {
148 	static GType type = 0;
149 
150 	if (!type) {
151 		GTypeInfo ti;
152 
153 		memset (&ti, 0, sizeof (GTypeInfo));
154 		ti.class_size    = sizeof (GtkamPreviewClass);
155 		ti.class_init    = gtkam_preview_class_init;
156 		ti.instance_size = sizeof (GtkamPreview);
157 		ti.instance_init = gtkam_preview_init;
158 
159 		type = g_type_register_static (PARENT_TYPE, "GtkamPreview",
160 					       &ti, 0);
161 	}
162 
163 	return (type);
164 }
165 
166 static gboolean
idle_destroy(gpointer data)167 idle_destroy (gpointer data)
168 {
169 	while (gtk_events_pending ())
170 		gtk_main_iteration ();
171 
172 	gtk_object_destroy (GTK_OBJECT (data));
173 
174 	return (FALSE);
175 }
176 
177 static void
on_preview_close_clicked(GtkButton * button,GtkamPreview * preview)178 on_preview_close_clicked (GtkButton *button, GtkamPreview *preview)
179 {
180 	gtk_widget_hide (GTK_WIDGET (preview));
181 
182 	gtk_idle_add (idle_destroy, preview);
183 }
184 
185 static void
download_captured_image(GtkWidget * parent,GtkamContext * context,Camera * camera,const char * path_folder,const char * path_name,const gchar * store_dir)186 download_captured_image(GtkWidget *parent, GtkamContext *context,
187 		Camera *camera, const char *path_folder, const char *path_name,
188 		const gchar *store_dir)
189 {
190 	int result;
191 	GTimeVal time;
192 	gchar *store_path, *suffix_pos, *time_s;
193 	int fd;
194 	CameraFile *camera_file;
195 	GtkWidget *dialog;
196 
197 	g_get_current_time(&time);
198 	time.tv_usec = 0;
199 	time_s = g_time_val_to_iso8601(&time);
200 	store_path = g_build_filename(store_dir, time_s, NULL);
201 	g_free(time_s);
202 
203 	suffix_pos = strrchr(path_name, '.');
204 	if (suffix_pos) {
205 		gchar *s = store_path;
206 		store_path = g_strconcat(s, suffix_pos, NULL);
207 		g_free(s);
208 	}
209 
210 	fd = open(store_path, O_CREAT | O_WRONLY, 0644);
211 	if (fd == -1) {
212 		dialog = gtkam_error_new (-1, context,
213 			    parent, _("Failed to open target file '%s'."), store_path);
214 		gtk_widget_show (dialog);
215 		g_free(store_path);
216 		return;
217 	}
218 	g_free(store_path);
219 
220 	result = gp_file_new_from_fd(&camera_file, fd);
221 	if (result != GP_OK) {
222 		g_warning("gphoto error, gp_file_new_from_fd");
223 		close(fd);
224 		return;
225 	}
226 
227 	result = gp_camera_file_get (camera,
228 		    path_folder, path_name, GP_FILE_TYPE_NORMAL, camera_file,
229 		    context->context);
230 	if (result != GP_OK) {
231 		result = gp_camera_file_delete(camera,
232 			    path_folder, path_name,
233 			    context->context);
234 		if (result != GP_OK) {
235 			g_warning("Failed to erase file %s/%s", path_folder, path_name);
236 		}
237 	}
238 
239 	gp_file_free(camera_file);
240 }
241 
242 static gboolean
timeout_func(gpointer user_data)243 timeout_func (gpointer user_data)
244 {
245 	int r;
246 	CameraFile *file;
247 	const char *data = NULL;
248 	unsigned long int size = 0;
249 	GdkPixbufLoader *loader;
250 	GdkPixbuf *pixbuf, *rotated;
251 	GtkamPreview *p = GTKAM_PREVIEW (user_data);
252 
253 	gp_file_new (&file);
254 	r = gp_camera_capture_preview (p->priv->camera->camera, file, NULL);
255 	if (p->priv->camera->multi)
256 		gp_camera_exit (p->priv->camera->camera, NULL);
257 	if (r < GP_OK) {
258 		if (r != GP_ERROR_CAMERA_BUSY)
259 			g_warning ("Could not capture: %s",
260 				   gp_result_as_string (r));
261 		gp_file_unref (file);
262 		return (FALSE);
263 	}
264 
265 	loader = gdk_pixbuf_loader_new ();
266 	gp_file_get_data_and_size (file, &data, &size);
267 	gdk_pixbuf_loader_write (loader, data, size, NULL);
268 	gdk_pixbuf_loader_close (loader, NULL);
269 	gp_file_unref (file);
270 	pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
271 	rotated = gdk_pixbuf_rotate (pixbuf, p->priv->rotate);
272 	g_object_unref (G_OBJECT (loader));
273 	gtk_image_set_from_pixbuf (GTK_IMAGE (p->priv->image), rotated);
274 	g_object_unref (G_OBJECT (rotated));
275 
276 	while (g_main_pending ())
277 		g_main_iteration (TRUE);
278 
279 	return (TRUE);
280 }
281 
282 static void
preview_enable(GtkamPreview * preview,gboolean enable)283 preview_enable(GtkamPreview *preview, gboolean enable)
284 {
285 	if (enable) {
286 		if (preview->priv->timeout_id) {
287 			return;
288 		}
289 		preview->priv->timeout_id = gtk_timeout_add (200, timeout_func,
290 				preview);
291 	} else {
292 		gtk_timeout_remove (preview->priv->timeout_id);
293 		preview->priv->timeout_id = 0;
294 	}
295 }
296 
297 static void
on_preview_capture_clicked(GtkButton * button,GtkamPreview * preview)298 on_preview_capture_clicked (GtkButton *button, GtkamPreview *preview)
299 {
300 	int result;
301 	CameraFilePath path;
302 	GtkWidget *dialog, *s;
303 	GtkamPreviewCapturedData data;
304 	gchar *filename = NULL;
305 
306 	s = gtkam_status_new (_("Capturing image..."));
307 	gtk_box_pack_start (GTK_BOX (GTK_DIALOG (preview)->vbox), s,
308 			    FALSE, FALSE, 0);
309 	gtk_widget_show_now (s);
310 
311 	if (gtk_toggle_button_get_active(
312 				GTK_TOGGLE_BUTTON (preview->priv->check_download))) {
313 		filename = gtk_file_chooser_get_filename (
314 				GTK_FILE_CHOOSER (preview->priv->button_file));
315 		if (!filename) {
316 			dialog = gtkam_error_new (-1, GTKAM_STATUS (s)->context,
317 				GTK_WIDGET (preview), _("Download directory not selected."));
318 			gtk_widget_show (dialog);
319 			gtk_object_destroy (GTK_OBJECT (s));
320 			return;
321 		}
322 	}
323 
324 	preview_enable(preview, 0);
325 	result = gp_camera_capture (preview->priv->camera->camera,
326 		GP_CAPTURE_IMAGE, &path, GTKAM_STATUS (s)->context->context);
327 	if (preview->priv->camera->multi)
328 		gp_camera_exit (preview->priv->camera->camera, NULL);
329 	switch (result) {
330 	case GP_OK:
331 		memset (&data, 0, sizeof (GtkamPreviewCapturedData));
332 		data.camera = preview->priv->camera;
333 		data.folder = path.folder;
334 		data.name = path.name;
335 		g_signal_emit (GTK_OBJECT (preview), signals[CAPTURED], 0,
336 			       &data);
337 		if (filename) {
338 			download_captured_image(GTK_WIDGET(preview), GTKAM_STATUS (s)->context,
339 				    preview->priv->camera->camera,
340 				    data.folder, data.name, filename);
341 		 }
342 		break;
343 	case GP_ERROR_CANCEL:
344 		break;
345 	default:
346 		dialog = gtkam_error_new (result, GTKAM_STATUS (s)->context,
347 			GTK_WIDGET (preview), _("Could not capture image."));
348 		gtk_widget_show (dialog);
349 		break;
350 	}
351 	g_free(filename);
352 	gtk_object_destroy (GTK_OBJECT (s));
353 	preview_enable(preview, 1);
354 }
355 
356 static void
on_radio_0_toggled(GtkToggleButton * toggle,GtkamPreview * preview)357 on_radio_0_toggled (GtkToggleButton *toggle, GtkamPreview *preview)
358 {
359 	g_return_if_fail (GTK_IS_TOGGLE_BUTTON (toggle));
360 	g_return_if_fail (GTKAM_IS_PREVIEW (preview));
361 
362 	if (toggle->active)
363 		preview->priv->rotate = 0;
364 }
365 
366 static void
on_radio_90_toggled(GtkToggleButton * toggle,GtkamPreview * preview)367 on_radio_90_toggled (GtkToggleButton *toggle, GtkamPreview *preview)
368 {
369 	g_return_if_fail (GTK_IS_TOGGLE_BUTTON (toggle));
370 	g_return_if_fail (GTKAM_IS_PREVIEW (preview));
371 
372 	if (toggle->active)
373 		preview->priv->rotate = 90;
374 }
375 
376 static void
on_radio_180_toggled(GtkToggleButton * toggle,GtkamPreview * preview)377 on_radio_180_toggled (GtkToggleButton *toggle, GtkamPreview *preview)
378 {
379 	g_return_if_fail (GTK_IS_TOGGLE_BUTTON (toggle));
380 	g_return_if_fail (GTKAM_IS_PREVIEW (preview));
381 
382 	if (toggle->active)
383 		preview->priv->rotate = 180;
384 }
385 
386 static void
on_radio_270_toggled(GtkToggleButton * toggle,GtkamPreview * preview)387 on_radio_270_toggled (GtkToggleButton *toggle, GtkamPreview *preview)
388 {
389 	g_return_if_fail (GTK_IS_TOGGLE_BUTTON (toggle));
390 	g_return_if_fail (GTKAM_IS_PREVIEW (preview));
391 
392 	if (toggle->active)
393 		preview->priv->rotate = 270;
394 }
395 
396 static void
on_configure_clicked(GtkButton * button,GtkamPreview * preview)397 on_configure_clicked (GtkButton *button, GtkamPreview *preview)
398 {
399 	GtkWidget *d;
400 
401 	d = gtkam_config_new (preview->priv->camera);
402 	if (!d)
403 		return;
404 	gtk_window_set_transient_for (GTK_WINDOW (d), GTK_WINDOW (preview));
405 	gtk_widget_show (d);
406 }
407 
408 static void
on_size_allocate(GtkWidget * widget,GtkAllocation * allocation,GtkamPreview * preview)409 on_size_allocate (GtkWidget *widget, GtkAllocation *allocation,
410 		  GtkamPreview *preview)
411 {
412 	GdkPixbuf *pixbuf, *scaled;
413 	gint w, h, target_w, target_h;
414 
415 	g_return_if_fail (GTKAM_IS_PREVIEW (preview));
416 
417 	pixbuf = gtk_image_get_pixbuf (GTK_IMAGE (preview->priv->image));
418 	if (!pixbuf)
419 		return;
420 
421 	w = gdk_pixbuf_get_width (pixbuf);
422 	h = gdk_pixbuf_get_height (pixbuf);
423 
424 	target_w = MIN (allocation->width, allocation->height * w / h);
425 	target_h = MIN (allocation->height, allocation->width * h / w);
426 
427 	if ((target_w == w) || (target_h == h))
428 		return;
429 
430 	scaled = gdk_pixbuf_scale_simple (pixbuf, target_w, target_h,
431 					  GDK_INTERP_HYPER);
432 	gtk_image_set_from_pixbuf (GTK_IMAGE (preview->priv->image), scaled);
433 	g_object_unref (G_OBJECT (scaled));
434 }
435 
436 static void
on_direct_download_toggled(GtkToggleButton * togglebutton,GtkamPreview * preview)437 on_direct_download_toggled (GtkToggleButton *togglebutton, GtkamPreview *preview)
438 {
439 	GtkFileChooser *dialog;
440 
441 	if (!gtk_toggle_button_get_active(
442 				GTK_TOGGLE_BUTTON (preview->priv->check_download))) {
443 		gp_setting_set ("gtkam-preview", "direct_download", "0");
444 		return;
445 	}
446 
447 	gp_setting_set ("gtkam-preview", "direct_download", "1");
448 }
449 
450 static void
on_button_file_selection_changed(GtkFileChooserButton * widget,GtkamPreview * preview)451 on_button_file_selection_changed (GtkFileChooserButton *widget, GtkamPreview *preview)
452 {
453     gchar *store_filename;
454 
455     store_filename = gtk_file_chooser_get_filename (
456             GTK_FILE_CHOOSER (preview->priv->button_file));
457     if (store_filename) {
458         gp_setting_set ("gtkam-preview", "download_folder", store_filename);
459         g_free(store_filename);
460     }
461 }
462 
463 GtkWidget *
gtkam_preview_new(GtkamCamera * camera)464 gtkam_preview_new (GtkamCamera *camera)
465 {
466 	CameraAbilities abilities;
467 	GtkamPreview *preview;
468 	GtkWidget *button, *check, *hbox, *vbox, *radio;
469 	GSList *group;
470 	gchar buf[1024];
471 
472 	g_return_val_if_fail (GTKAM_IS_CAMERA (camera), NULL);
473 
474 	preview = g_object_new (GTKAM_TYPE_PREVIEW, NULL);
475 	gtk_window_set_title (GTK_WINDOW (preview), _("Capture"));
476 	gtk_container_set_border_width (GTK_CONTAINER (preview), 5);
477 
478 	preview->priv->camera = camera;
479 	g_object_ref (G_OBJECT (camera));
480 	preview->priv->tooltips = gtk_tooltips_new ();
481 	g_object_ref (G_OBJECT (preview->priv->tooltips));
482 	gtk_object_sink (GTK_OBJECT (preview->priv->tooltips));
483 
484 	hbox = gtk_hbox_new (FALSE, 10);
485 	gtk_widget_show (hbox);
486 	gtk_box_pack_start (GTK_BOX (GTKAM_DIALOG (preview)->vbox), hbox,
487 			    TRUE, TRUE, 0);
488 
489 	/* Empty image (for preview) */
490 	preview->priv->image = gtk_image_new ();
491 	gtk_widget_show (preview->priv->image);
492 	gtk_box_pack_start (GTK_BOX (hbox), preview->priv->image,
493 			    TRUE, TRUE, 0);
494 	g_signal_connect (G_OBJECT (preview->priv->image), "size_allocate",
495 			  G_CALLBACK (on_size_allocate), preview);
496 
497 	/* Rotate */
498 	vbox = gtk_vbox_new (FALSE, 0);
499 	gtk_widget_show (vbox);
500 	gtk_box_pack_end (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);
501 	radio = gtk_radio_button_new_with_label (NULL, _("0 degrees"));
502 	gtk_widget_show (radio);
503 	gtk_box_pack_start (GTK_BOX (vbox), radio, FALSE, FALSE, 0);
504 	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (radio), TRUE);
505 	g_signal_connect (GTK_OBJECT (radio), "toggled",
506 			    GTK_SIGNAL_FUNC (on_radio_0_toggled), preview);
507 	preview->priv->angle_0 = GTK_TOGGLE_BUTTON (radio);
508 	gtk_tooltips_set_tip (preview->priv->tooltips, radio,
509 			      _("Don't rotate thumbnail"), NULL);
510 	group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio));
511 	radio = gtk_radio_button_new_with_label (group, _("-90 degrees"));
512 	gtk_widget_show (radio);
513 	gtk_box_pack_start (GTK_BOX (vbox), radio, FALSE, FALSE, 0);
514 	g_signal_connect (GTK_OBJECT (radio), "toggled",
515 			    GTK_SIGNAL_FUNC (on_radio_270_toggled), preview);
516 	preview->priv->angle_90 = GTK_TOGGLE_BUTTON (radio);
517 	gtk_tooltips_set_tip (preview->priv->tooltips, radio,
518 			      _("Rotate thumbnail by -90 degrees"), NULL);
519 	group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio));
520 	radio = gtk_radio_button_new_with_label (group, _("+90 degrees"));
521 	gtk_widget_show (radio);
522 	gtk_box_pack_start (GTK_BOX (vbox), radio, FALSE, FALSE, 0);
523 	g_signal_connect (GTK_OBJECT (radio), "toggled",
524 			    GTK_SIGNAL_FUNC (on_radio_90_toggled), preview);
525 	preview->priv->angle_180 = GTK_TOGGLE_BUTTON (radio);
526 	gtk_tooltips_set_tip (preview->priv->tooltips, radio,
527 			      _("Rotate thumbnail by 90 degrees"), NULL);
528 	group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio));
529 	radio = gtk_radio_button_new_with_label (group, _("180 degrees"));
530 	gtk_widget_show (radio);
531 	gtk_box_pack_start (GTK_BOX (vbox), radio, FALSE, FALSE, 0);
532 	g_signal_connect (GTK_OBJECT (radio), "toggled",
533 			    GTK_SIGNAL_FUNC (on_radio_180_toggled), preview);
534 	preview->priv->angle_270 = GTK_TOGGLE_BUTTON (radio);
535 	gtk_tooltips_set_tip (preview->priv->tooltips, radio,
536 			      _("Rotate thumbnail by 180 degrees"), NULL);
537 
538 	/* Immediate image download */
539 	hbox = gtk_hbox_new (FALSE, 10);
540 	gtk_widget_show (hbox);
541 	gtk_box_pack_start (GTK_BOX (GTKAM_DIALOG (preview)->vbox), hbox,
542 			    TRUE, TRUE, 0);
543 
544 	check = gtk_check_button_new_with_label (_("Download"));
545 	gtk_widget_show (check);
546 	gtk_box_pack_start (GTK_BOX (hbox), check, FALSE, FALSE, 0);
547 	g_signal_connect (GTK_OBJECT (check), "toggled",
548 			    GTK_SIGNAL_FUNC (on_direct_download_toggled), preview);
549 	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check), FALSE);
550 	gtk_tooltips_set_tip (preview->priv->tooltips, check, _(
551 			    _("Download captured images into specified directory.")), NULL);
552 	preview->priv->check_download = GTK_CHECK_BUTTON (check);
553 
554 	button = gtk_file_chooser_button_new(_("Download target directory"),
555 			    GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
556 	gtk_widget_show (button);
557 	gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
558 	gtk_file_chooser_set_local_only( GTK_FILE_CHOOSER (button), TRUE);
559 	preview->priv->button_file = GTK_FILE_CHOOSER_BUTTON (button);
560 	g_signal_connect (G_OBJECT (preview->priv->button_file), "selection-changed",
561             G_CALLBACK (on_button_file_selection_changed), preview);
562 
563 	if (gp_setting_get ("gtkam-preview", "download_folder", buf) == GP_OK) {
564 		gtk_file_chooser_set_filename (preview->priv->button_file, buf);
565 	}
566 	if (gp_setting_get ("gtkam-preview", "direct_download", buf) == GP_OK) {
567 		gtk_toggle_button_set_active (
568 		    GTK_TOGGLE_BUTTON (preview->priv->check_download),
569 		    atoi(buf));
570 	}
571 
572 	/* Buttons in action area */
573 	button = gtk_button_new_with_label (_("Capture"));
574 	gtk_widget_show (button);
575 	g_signal_connect (GTK_OBJECT (button), "clicked",
576 			    GTK_SIGNAL_FUNC (on_preview_capture_clicked),
577 			    preview);
578 	gtk_container_add (GTK_CONTAINER (GTK_DIALOG (preview)->action_area),
579 			   button);
580 	gtk_widget_grab_focus (button);
581 
582 	gp_camera_get_abilities (camera->camera, &abilities);
583 	if (abilities.operations & GP_OPERATION_CONFIG) {
584 		button = gtk_button_new_from_stock (GTK_STOCK_PREFERENCES);
585 		gtk_widget_show (button);
586 		g_signal_connect (GTK_OBJECT (button), "clicked",
587 			GTK_SIGNAL_FUNC (on_configure_clicked), preview);
588 		gtk_container_add (
589 			GTK_CONTAINER (GTK_DIALOG (preview)->action_area),
590 			button);
591 	}
592 
593 	button = gtk_button_new_from_stock (GTK_STOCK_CLOSE);
594 	gtk_widget_show (button);
595 	g_signal_connect (GTK_OBJECT (button), "clicked",
596 		GTK_SIGNAL_FUNC (on_preview_close_clicked), preview);
597 	gtk_container_add (GTK_CONTAINER (GTK_DIALOG (preview)->action_area),
598 			   button);
599 
600 	preview_enable(preview, 1);
601 
602 	return (GTK_WIDGET (preview));
603 }
604 
605 void
gtkam_preview_set_angle(GtkamPreview * preview,guint angle)606 gtkam_preview_set_angle (GtkamPreview *preview, guint angle)
607 {
608 	g_return_if_fail (GTKAM_IS_PREVIEW (preview));
609 
610 	switch (angle) {
611 	case 0:
612 		gtk_toggle_button_set_active (preview->priv->angle_0, TRUE);
613 		break;
614 	case 90:
615 		gtk_toggle_button_set_active (preview->priv->angle_90, TRUE);
616 		break;
617 	case 180:
618 		gtk_toggle_button_set_active (preview->priv->angle_180, TRUE);
619 		break;
620 	case 270:
621 		gtk_toggle_button_set_active (preview->priv->angle_270, TRUE);
622 		break;
623 	default:
624 		g_warning ("Rotation by %i not implemented!", angle);
625 	}
626 }
627 
628 guint
gtkam_preview_get_angle(GtkamPreview * preview)629 gtkam_preview_get_angle (GtkamPreview *preview)
630 {
631 	g_return_val_if_fail (GTKAM_IS_PREVIEW (preview), 0);
632 
633 	return (preview->priv->rotate);
634 }
635