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