1 /* gtkam-tree.c
2 *
3 * Copyright 2001,2002 Lutz Mueller <lutz@users.sf.net>
4 * Copyright 2004 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-tree.h"
22 #include "i18n.h"
23
24 #include <stdio.h>
25 #include <sys/types.h>
26 #include <sys/stat.h>
27 #include <string.h>
28 #include <stdlib.h>
29 #include <libgen.h>
30
31 #include <gtk/gtkvbox.h>
32 #include <gtk/gtkhbox.h>
33 #include <gtk/gtklabel.h>
34 #include <gtk/gtksignal.h>
35 #include <gtk/gtkmain.h>
36 #include <gtk/gtkfilesel.h>
37 #include <gtk/gtkbutton.h>
38 #include <gtk/gtktreestore.h>
39 #include <gtk/gtkpixmap.h>
40 #include <gtk/gtkitemfactory.h>
41 #include <gtk/gtkmenu.h>
42 #include <gtk/gtkcellrenderertext.h>
43 #include <gtk/gtktreeselection.h>
44 #include <gtk/gtkstock.h>
45 #include <gtk/gtktooltips.h>
46 #include <gtk/gtkmenuitem.h>
47
48 #include <gdk-pixbuf/gdk-pixbuf.h>
49
50 #include <gphoto2/gphoto2-setting.h>
51 #include <gphoto2/gphoto2-camera.h>
52
53 #include "util.h"
54
55 #include "gtkam-camera.h"
56 #include "gtkam-chooser.h"
57 #include "gtkam-close.h"
58 #include "gtkam-config.h"
59 #include "gtkam-error.h"
60 #include "gtkam-status.h"
61 #include "gtkam-mkdir.h"
62 #include "gtkam-preview.h"
63 #include "gtkam-cancel.h"
64
65 struct _GtkamTreePrivate
66 {
67 GtkTreeStore *store;
68
69 GtkItemFactory *factory;
70 GtkTooltips *tooltips;
71
72 GtkTreeIter iter;
73 };
74
75 #define PARENT_TYPE GTK_TYPE_TREE_VIEW
76 static GtkTreeViewClass *parent_class;
77
78 enum {
79 FOLDER_SELECTED,
80 FOLDER_UNSELECTED,
81 FILE_ADDED,
82 NEW_STATUS,
83 NEW_ERROR,
84 NEW_DIALOG,
85 LAST_SIGNAL
86 };
87
88 static guint signals[LAST_SIGNAL] = {0};
89
90 enum {
91 FOLDER_COLUMN = 0,
92 CAMERA_COLUMN,
93 NUM_COLUMNS
94 };
95
96 static void
gtkam_tree_destroy(GtkObject * object)97 gtkam_tree_destroy (GtkObject *object)
98 {
99 GtkamTree *tree = GTKAM_TREE (object);
100
101 if (tree->priv->store) {
102 g_object_unref (G_OBJECT (tree->priv->store));
103 tree->priv->store = NULL;
104 }
105
106 if (tree->priv->tooltips) {
107 g_object_unref (G_OBJECT (tree->priv->tooltips));
108 tree->priv->tooltips = NULL;
109 }
110
111 GTK_OBJECT_CLASS (parent_class)->destroy (object);
112 }
113
114 static void
gtkam_tree_finalize(GObject * object)115 gtkam_tree_finalize (GObject *object)
116 {
117 GtkamTree *tree = GTKAM_TREE (object);
118
119 g_free (tree->priv);
120
121 G_OBJECT_CLASS (parent_class)->finalize (object);
122 }
123
124 static void
gtkam_tree_class_init(gpointer g_class,gpointer class_data)125 gtkam_tree_class_init (gpointer g_class, gpointer class_data)
126 {
127 GtkObjectClass *object_class;
128 GObjectClass *gobject_class;
129
130 object_class = GTK_OBJECT_CLASS (g_class);
131 object_class->destroy = gtkam_tree_destroy;
132
133 gobject_class = G_OBJECT_CLASS (g_class);
134 gobject_class->finalize = gtkam_tree_finalize;
135
136 signals[FOLDER_SELECTED] = g_signal_new ("folder_selected",
137 G_TYPE_FROM_CLASS (g_class), G_SIGNAL_RUN_LAST,
138 G_STRUCT_OFFSET (GtkamTreeClass, folder_selected), NULL, NULL,
139 g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1,
140 G_TYPE_POINTER);
141 signals[FOLDER_UNSELECTED] = g_signal_new ("folder_unselected",
142 G_TYPE_FROM_CLASS (g_class), G_SIGNAL_RUN_LAST,
143 G_STRUCT_OFFSET (GtkamTreeClass, folder_unselected), NULL, NULL,
144 g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1,
145 G_TYPE_POINTER);
146 signals[FILE_ADDED] = g_signal_new ("file_added",
147 G_TYPE_FROM_CLASS (g_class), G_SIGNAL_RUN_LAST,
148 G_STRUCT_OFFSET (GtkamTreeClass, file_added), NULL, NULL,
149 g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1,
150 G_TYPE_POINTER);
151 signals[NEW_STATUS] = g_signal_new ("new_status",
152 G_TYPE_FROM_CLASS (g_class), G_SIGNAL_RUN_LAST,
153 G_STRUCT_OFFSET (GtkamTreeClass, new_status), NULL, NULL,
154 g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1,
155 G_TYPE_POINTER);
156 signals[NEW_ERROR] = g_signal_new ("new_error",
157 G_TYPE_FROM_CLASS (g_class), G_SIGNAL_RUN_LAST,
158 G_STRUCT_OFFSET (GtkamTreeClass, new_error), NULL, NULL,
159 g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1,
160 G_TYPE_POINTER);
161 signals[NEW_DIALOG] = g_signal_new ("new_dialog",
162 G_TYPE_FROM_CLASS (g_class), G_SIGNAL_RUN_LAST,
163 G_STRUCT_OFFSET (GtkamTreeClass, new_dialog), NULL, NULL,
164 g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1,
165 G_TYPE_POINTER);
166
167 parent_class = g_type_class_peek_parent (g_class);
168 }
169
170 static void
gtkam_tree_init(GTypeInstance * instance,gpointer g_class)171 gtkam_tree_init (GTypeInstance *instance, gpointer g_class)
172 {
173 GtkamTree *tree = GTKAM_TREE (instance);
174
175 tree->priv = g_new0 (GtkamTreePrivate, 1);
176
177 tree->priv->tooltips = gtk_tooltips_new ();
178 g_object_ref (G_OBJECT (tree->priv->tooltips));
179 gtk_object_sink (GTK_OBJECT (tree->priv->tooltips));
180 }
181
182 GType
gtkam_tree_get_type(void)183 gtkam_tree_get_type (void)
184 {
185 static GType type = 0;
186
187 if (!type) {
188 GTypeInfo ti;
189
190 memset (&ti, 0, sizeof (GTypeInfo));
191 ti.class_size = sizeof (GtkamTreeClass);
192 ti.class_init = gtkam_tree_class_init;
193 ti.instance_size = sizeof (GtkamTree);
194 ti.instance_init = gtkam_tree_init;
195
196 type = g_type_register_static (PARENT_TYPE, "GtkamTree",
197 &ti, 0);
198 }
199
200 return (type);
201 }
202
203 static GtkamCamera *
gtkam_tree_get_camera_from_iter(GtkamTree * tree,GtkTreeIter * iter)204 gtkam_tree_get_camera_from_iter (GtkamTree *tree, GtkTreeIter *iter)
205 {
206 GValue value = {0};
207 GtkamCamera *camera;
208
209 gtk_tree_model_get_value (GTK_TREE_MODEL (tree->priv->store), iter,
210 CAMERA_COLUMN, &value);
211 g_assert (G_VALUE_HOLDS (&value, GTKAM_TYPE_CAMERA));
212 camera = GTKAM_CAMERA (g_value_peek_pointer (&value));
213 g_value_unset (&value);
214
215 return (camera);
216 }
217
218 static gchar *
gtkam_tree_get_path_rec(GtkamTree * tree,GtkTreeIter * iter,const gchar * path)219 gtkam_tree_get_path_rec (GtkamTree *tree, GtkTreeIter *iter, const gchar *path)
220 {
221 GtkTreeIter parent, p;
222 gchar *new_path = NULL, *new_path_ret = NULL;
223 GValue value = {0};
224
225 if (gtk_tree_model_iter_parent (GTK_TREE_MODEL (tree->priv->store),
226 &parent, iter)) {
227 if (gtk_tree_model_iter_parent (
228 GTK_TREE_MODEL (tree->priv->store), &p, &parent)) {
229 gtk_tree_model_get_value (
230 GTK_TREE_MODEL (tree->priv->store),
231 &parent, FOLDER_COLUMN, &value);
232 new_path = g_strdup_printf ("%s/%s",
233 g_value_get_string (&value), path);
234 g_value_unset (&value);
235 new_path_ret = gtkam_tree_get_path_rec (tree, &parent,
236 new_path);
237 g_free (new_path);
238 return (new_path_ret);
239 } else
240 return (g_strdup_printf ("/%s", path));
241 } else
242 return (g_strdup ("/"));
243 }
244
245 static gchar *
gtkam_tree_get_path_from_iter(GtkamTree * tree,GtkTreeIter * iter)246 gtkam_tree_get_path_from_iter (GtkamTree *tree, GtkTreeIter *iter)
247 {
248 GtkTreeIter parent;
249 GValue value = {0};
250 gchar *path = NULL;
251
252 if (gtk_tree_model_iter_parent (GTK_TREE_MODEL (tree->priv->store),
253 &parent, iter)) {
254 gtk_tree_model_get_value (GTK_TREE_MODEL (tree->priv->store),
255 iter, FOLDER_COLUMN, &value);
256 path = gtkam_tree_get_path_rec (tree, iter,
257 g_value_get_string (&value));
258 g_value_unset (&value);
259 } else
260 path = g_strdup ("/");
261
262 return (path);
263 }
264
265 static void
gtkam_tree_update_iter(GtkamTree * tree,GtkTreeIter * iter)266 gtkam_tree_update_iter (GtkamTree *tree, GtkTreeIter *iter)
267 {
268 gint i, n;
269 GtkTreeIter child;
270 CameraList *list;
271 const char *name;
272 int result;
273 GtkamCamera *camera = NULL;
274 GtkWidget *s;
275 gchar *folder = NULL, *msg;
276 GtkamTreeErrorData e;
277
278 g_return_if_fail (GTKAM_IS_TREE (tree));
279
280 /* Look up the corresponding camera */
281 camera = gtkam_tree_get_camera_from_iter (tree, iter);
282 g_return_if_fail (camera != NULL);
283 g_return_if_fail (GTKAM_IS_CAMERA (camera));
284
285 while (gtk_tree_model_iter_n_children (
286 GTK_TREE_MODEL (tree->priv->store), iter)) {
287 gtk_tree_model_iter_nth_child (
288 GTK_TREE_MODEL (tree->priv->store), &child,
289 iter, 0);
290 gtk_tree_store_remove (tree->priv->store, &child);
291 }
292
293 /* Which folder? */
294 folder = gtkam_tree_get_path_from_iter (tree, iter);
295
296 s = gtkam_status_new (_("Listing folders in '%s'..."), folder);
297 g_signal_emit (G_OBJECT (tree), signals[NEW_STATUS], 0, s);
298 gp_list_new (&list);
299 result = gp_camera_folder_list_folders (camera->camera, folder, list,
300 GTKAM_STATUS (s)->context->context);
301 if (result >= 0) {
302 n = gp_list_count (list);
303 for (i = 0; i < n; i++) {
304 gp_list_get_name (list, i, &name);
305 gtk_tree_store_append (tree->priv->store, &child,
306 iter);
307 gtk_tree_store_set (tree->priv->store, &child,
308 FOLDER_COLUMN, name,
309 CAMERA_COLUMN, camera, -1);
310 }
311 } else if (result == GP_ERROR_NOT_SUPPORTED) {
312 /* Do nothing */
313 } else {
314 e.context = GTKAM_STATUS (s)->context;
315 e.result = result;
316 e.msg = msg = g_strdup_printf (
317 _("Could not list folders in '%s'."), folder);
318 g_signal_emit (G_OBJECT (tree), signals[NEW_ERROR], 0, &e);
319 g_free (msg);
320 }
321 g_free (folder);
322 gp_list_unref (list);
323 if (camera->multi)
324 gp_camera_exit (camera->camera, NULL);
325
326 gtk_object_destroy (GTK_OBJECT (s));
327 }
328
329 static void
on_row_expanded(GtkTreeView * tree_view,GtkTreeIter * iter,GtkTreePath * path,GtkamTree * tree)330 on_row_expanded (GtkTreeView *tree_view, GtkTreeIter *iter,
331 GtkTreePath *path, GtkamTree *tree)
332 {
333 gint i, n;
334 GtkTreeIter child;
335
336 n = gtk_tree_model_iter_n_children (
337 GTK_TREE_MODEL (tree->priv->store), iter);
338 for (i = 0; i < n; i++) {
339 gtk_tree_model_iter_nth_child (
340 GTK_TREE_MODEL (tree->priv->store), &child, iter, i);
341 if (!gtk_tree_model_iter_has_child (
342 GTK_TREE_MODEL (tree->priv->store), &child))
343 gtkam_tree_update_iter (tree, &child);
344 }
345 }
346
347 static gboolean
selection_func(GtkTreeSelection * selection,GtkTreeModel * model,GtkTreePath * path,gboolean path_currently_selected,gpointer data)348 selection_func (GtkTreeSelection *selection, GtkTreeModel *model,
349 GtkTreePath *path, gboolean path_currently_selected,
350 gpointer data)
351 {
352 GtkTreeIter iter;
353 gchar *folder;
354 GtkamTree *tree = GTKAM_TREE (data);
355 GtkamTreeFolderSelectedData sd;
356 GtkamTreeFolderUnselectedData ud;
357
358 gtk_tree_model_get_iter (model, &iter, path);
359 folder = gtkam_tree_get_path_from_iter (tree, &iter);
360 if (path_currently_selected) {
361 ud.camera = gtkam_tree_get_camera_from_iter (tree, &iter);
362 ud.folder = folder;
363 g_signal_emit (G_OBJECT (tree), signals[FOLDER_UNSELECTED],
364 0, &ud);
365 } else {
366 sd.camera = gtkam_tree_get_camera_from_iter (tree, &iter);
367 sd.folder = folder;
368 g_signal_emit (G_OBJECT (tree), signals[FOLDER_SELECTED],
369 0, &sd);
370 }
371 g_free (folder);
372
373 return (TRUE);
374 }
375
376 typedef struct _GtkamTreeUploadData GtkamTreeUploadData;
377 struct _GtkamTreeUploadData {
378 GtkWidget *fsel;
379 GtkamTree *tree;
380 GtkTreeIter *iter;
381 };
382
383 static void
on_upload_destroy(GtkObject * object,GtkamTreeUploadData * ud)384 on_upload_destroy (GtkObject *object, GtkamTreeUploadData *ud)
385 {
386 gtk_tree_iter_free (ud->iter);
387 g_free (ud);
388 }
389
390 static void
on_upload_cancel_clicked(GtkButton * button,GtkFileSelection * fsel)391 on_upload_cancel_clicked (GtkButton *button, GtkFileSelection *fsel)
392 {
393 gtk_object_destroy (GTK_OBJECT (fsel));
394 }
395
396 static void
on_upload_ok_clicked(GtkButton * button,GtkamTreeUploadData * ud)397 on_upload_ok_clicked (GtkButton *button, GtkamTreeUploadData *ud)
398 {
399 const gchar *path;
400 int r;
401 CameraFile *file;
402 GtkamTreeErrorData e;
403 GtkamTreeFileAddedData fud;
404 GtkWidget *s;
405 gchar *basename, *folder, *msg;
406 GtkamCamera *c;
407
408 path = gtk_file_selection_get_filename (GTK_FILE_SELECTION (ud->fsel));
409 gp_file_new (&file);
410 r = gp_file_open (file, path);
411 if (r < 0) {
412 e.context = NULL;
413 e.result = r;
414 e.msg = msg = g_strdup_printf (_("Could not open '%s'."), path);
415 g_signal_emit (G_OBJECT (ud->tree), signals[NEW_ERROR], 0, &e);
416 g_free (msg);
417 } else {
418 gtk_widget_hide (ud->fsel);
419 folder = gtkam_tree_get_path_from_iter (ud->tree, ud->iter);
420 c = gtkam_tree_get_camera_from_iter (ud->tree, ud->iter);
421 basename = g_path_get_basename (path);
422 s = gtkam_status_new (_("Uploading '%s' into "
423 "folder '%s'..."), basename, folder);
424 g_signal_emit (G_OBJECT (ud->tree), signals[NEW_STATUS], 0, s);
425 #ifdef HAVE_GP_PORT_INFO_GET_NAME
426 r = gp_camera_folder_put_file (c->camera, folder, basename, GP_FILE_TYPE_NORMAL, file,
427 GTKAM_STATUS (s)->context->context);
428 #else
429 r = gp_camera_folder_put_file (c->camera, folder, file, GTKAM_STATUS (s)->context->context);
430 #endif
431 if (c->multi)
432 gp_camera_exit (c->camera, NULL);
433 switch (r) {
434 case GP_OK:
435 fud.camera = c;
436 fud.folder = folder;
437 fud.name = basename;
438 g_signal_emit (G_OBJECT (ud->tree),
439 signals[FILE_ADDED], 0, &fud);
440 break;
441 case GP_ERROR_CANCEL:
442 break;
443 default:
444 e.context = GTKAM_STATUS (s)->context;
445 e.result = r;
446 e.msg = msg = g_strdup_printf (_("Could not upload "
447 "'%s' into '%s'."), path, folder);
448 g_signal_emit (G_OBJECT (ud->tree), signals[NEW_ERROR],
449 0, &e);
450 g_free (msg);
451 break;
452 }
453 g_free (basename);
454 g_free (folder);
455 gtk_object_destroy (GTK_OBJECT (s));
456 }
457 gp_file_unref (file);
458 gtk_object_destroy (GTK_OBJECT (ud->fsel));
459 }
460
461 static void
action_upload(gpointer callback_data,guint callback_action,GtkWidget * widget)462 action_upload (gpointer callback_data, guint callback_action,
463 GtkWidget *widget)
464 {
465 GtkWidget *fsel;
466 GtkamTree *tree = GTKAM_TREE (callback_data);
467 GtkamTreeUploadData *ud;
468 gchar *title, *folder;
469
470 folder = gtkam_tree_get_path_from_iter (tree, &tree->priv->iter);
471 title = g_strdup_printf (_("Upload into '%s'..."), folder);
472 g_free (folder);
473 fsel = gtk_file_selection_new (title);
474 g_free (title);
475 g_signal_emit (G_OBJECT (tree), signals[NEW_DIALOG], 0, fsel);
476 g_object_unref (G_OBJECT (fsel));
477 ud = g_new0 (GtkamTreeUploadData, 1);
478 ud->fsel = fsel;
479 ud->tree = tree;
480 ud->iter = gtk_tree_iter_copy (&tree->priv->iter);
481 g_signal_connect (G_OBJECT (fsel), "destroy",
482 G_CALLBACK (on_upload_destroy), ud);
483 g_signal_connect (G_OBJECT (GTK_FILE_SELECTION (fsel)->ok_button),
484 "clicked", G_CALLBACK (on_upload_ok_clicked), ud);
485 g_signal_connect (G_OBJECT (GTK_FILE_SELECTION (fsel)->cancel_button),
486 "clicked", G_CALLBACK (on_upload_cancel_clicked), fsel);
487 }
488
489 typedef struct _DirCreatedData DirCreatedData;
490 struct _DirCreatedData {
491 GtkamTree *tree;
492 GtkTreeIter *iter;
493 };
494
495 static void
on_dir_created(GtkamMkdir * mkdir,GtkamMkdirDirCreatedData * data,DirCreatedData * d)496 on_dir_created (GtkamMkdir *mkdir, GtkamMkdirDirCreatedData *data,
497 DirCreatedData *d)
498 {
499 gtkam_tree_update_iter (d->tree, d->iter);
500 }
501
502 static void
on_mkdir_destroy(GtkObject * mkdir,DirCreatedData * d)503 on_mkdir_destroy (GtkObject *mkdir, DirCreatedData *d)
504 {
505 gtk_tree_iter_free (d->iter);
506 g_free (d);
507 }
508
509 static void
action_mkdir(gpointer callback_data,guint callback_action,GtkWidget * widget)510 action_mkdir (gpointer callback_data, guint callback_action,
511 GtkWidget *widget)
512 {
513 GtkWidget *d;
514 GtkamTree *tree = GTKAM_TREE (callback_data);
515 GtkamCamera *camera;
516 DirCreatedData *data;
517 gchar *folder;
518
519 camera = gtkam_tree_get_camera_from_iter (tree, &tree->priv->iter);
520 folder = gtkam_tree_get_path_from_iter (tree, &tree->priv->iter);
521 d = gtkam_mkdir_new (camera, folder);
522 g_signal_emit (GTK_OBJECT (tree), signals[NEW_DIALOG], 0, d);
523 g_object_unref (G_OBJECT (d));
524 g_free (folder);
525 data = g_new0 (DirCreatedData, 1);
526 data->tree = tree;
527 data->iter = gtk_tree_iter_copy (&tree->priv->iter);
528 g_signal_connect (G_OBJECT (d), "dir_created",
529 G_CALLBACK (on_dir_created), data);
530 g_signal_connect (G_OBJECT (d), "destroy",
531 G_CALLBACK (on_mkdir_destroy), data);
532 }
533
534 static void
action_rmdir(gpointer callback_data,guint callback_action,GtkWidget * widget)535 action_rmdir (gpointer callback_data, guint callback_action,
536 GtkWidget *widget)
537 {
538 GtkWidget *s;
539 GtkamTree *tree = GTKAM_TREE (callback_data);
540 gchar *basename, *folder, *path, *msg;
541 int r;
542 GtkamCamera *camera;
543 GtkamTreeErrorData e;
544
545 folder = gtkam_tree_get_path_from_iter (tree, &tree->priv->iter);
546 camera = gtkam_tree_get_camera_from_iter (tree, &tree->priv->iter);
547 s = gtkam_status_new (_("Removing directory '%s'..."), folder);
548 g_signal_emit (G_OBJECT (tree), signals[NEW_STATUS], 0, s);
549 path = g_strdup (folder);
550 while (path[strlen (path) - 1] != '/')
551 path[strlen (path) - 1] = '\0';
552 basename = g_path_get_basename (folder);
553 r = gp_camera_folder_remove_dir (camera->camera, path,
554 basename, GTKAM_STATUS (s)->context->context);
555 g_free (path);
556 g_free (basename);
557 switch (r) {
558 case GP_OK:
559 gtk_tree_store_remove (tree->priv->store, &tree->priv->iter);
560 break;
561 case GP_ERROR_CANCEL:
562 break;
563 default:
564 e.context = GTKAM_STATUS (s)->context;
565 e.result = r;
566 e.msg = msg = g_strdup_printf (_("Could not remove directory "
567 "'%s'."), folder);
568 g_signal_emit (G_OBJECT (tree), signals[NEW_ERROR], 0, &e);
569 g_free (msg);
570 break;
571 }
572 g_free (folder);
573 gtk_object_destroy (GTK_OBJECT (s));
574 }
575
576 typedef struct _GtkamTreeDownloadData GtkamTreeDownloadData;
577 struct _GtkamTreeDownloadData {
578 GtkWidget *fsel;
579 GtkamTree *tree;
580 GtkTreeIter *iter;
581 };
582
583 static void
on_download_destroy(GtkObject * object,GtkamTreeDownloadData * dd)584 on_download_destroy (GtkObject *object, GtkamTreeDownloadData *dd)
585 {
586 gtk_tree_iter_free (dd->iter);
587 g_free (dd);
588 }
589
590 static void
on_download_cancel_clicked(GtkButton * button,GtkFileSelection * fsel)591 on_download_cancel_clicked (GtkButton *button, GtkFileSelection *fsel)
592 {
593 gtk_object_destroy (GTK_OBJECT (fsel));
594 }
595
596 static gchar *
tree_concat_dir_and_file(const gchar * dirname,const gchar * filename)597 tree_concat_dir_and_file (const gchar *dirname, const gchar *filename)
598 {
599 gchar *full_path;
600
601 if (!strcmp (dirname, "/"))
602 full_path = g_strdup_printf ("/%s", filename);
603 else if (dirname[strlen (dirname) - 1] == '/')
604 full_path = g_strdup_printf ("%s%s", dirname, filename);
605 else
606 full_path = g_strdup_printf ("%s/%s", dirname, filename);
607 return (full_path);
608 }
609
610 static int
tree_save_file(CameraFile * file,const char * dest_path,const char * name,GtkWindow * save)611 tree_save_file (CameraFile *file, const char *dest_path, const char *name,
612 GtkWindow *save)
613 {
614 gchar *full_path, *msg;
615 GtkWidget *dialog;
616 int result;
617
618 /* Use filename provided by the CameraFile */
619 full_path = tree_concat_dir_and_file (dest_path, name);
620
621 /* FIXME Check which is user, and prompt the user */
622 if (file_exists (full_path)) {
623 msg = g_strdup_printf (_("The file '%s' already exists."),
624 full_path);
625 dialog = gtkam_error_new (GP_ERROR_FILE_EXISTS, NULL,
626 GTK_WIDGET (save), msg);
627 gtk_widget_show (dialog);
628 g_free (msg);
629 g_free (full_path);
630 return -1;
631 }
632
633 /* FIXME Check for sufficient disk space for this file, or
634 calculate total disk space required for all files before
635 save process starts */
636
637 result = gp_file_save (file, full_path);
638 if (result < 0) {
639 dialog = gtkam_error_new (result, NULL, GTK_WIDGET (save),
640 _("Could not save file to '%s'."), full_path);
641 gtk_widget_show (dialog);
642 }
643
644 g_free (full_path);
645
646 return result;
647 }
648
649 static int
tree_get_file(GtkamCamera * camera,const gchar * dest_path,const gchar * folder,const gchar * name,GtkamContext * context,GtkWindow * save)650 tree_get_file (GtkamCamera *camera,
651 const gchar *dest_path, const gchar *folder, const gchar *name,
652 GtkamContext *context, GtkWindow *save)
653 {
654 int result;
655 GtkWidget *dialog;
656 CameraFile *file;
657
658 gp_file_new (&file);
659 result = gp_camera_file_get (camera->camera, folder, name,
660 GP_FILE_TYPE_NORMAL, file,
661 context->context);
662 if (camera->multi)
663 gp_camera_exit (camera->camera, NULL);
664 switch (result) {
665 case GP_OK:
666 result = GP_OK;
667 tree_save_file (file, dest_path, name, save);
668 break;
669 case GP_ERROR_CANCEL:
670 break;
671 default:
672 dialog = gtkam_error_new (result, context, GTK_WIDGET (save),
673 _("Could not get '%s' "
674 "from folder '%s'."), name, folder);
675 gtk_widget_show (dialog);
676 }
677 gp_file_unref (file);
678
679 return result;
680 }
681
682 static int
tree_save_dir(GtkamCamera * camera,GtkamTree * tree,const gchar * path,const gchar * folder,GtkWindow * save)683 tree_save_dir(GtkamCamera *camera, GtkamTree *tree,
684 const gchar *path, const gchar *folder, GtkWindow *save)
685 {
686 GtkWidget *s, *dialog;
687 const gchar *name;
688 gchar *new_path;
689 CameraList *flist, *slist;
690 gint i, count, id;
691 int result;
692 id = 0;
693
694 s = gtkam_status_new (_("Listing files in folder '%s'..."), folder);
695 g_signal_emit (G_OBJECT (tree), signals[NEW_STATUS], 0, s);
696 gp_list_new (&flist);
697 result = gp_camera_folder_list_files (camera->camera, folder, flist,
698 GTKAM_STATUS (s)->context->context);
699 switch (result) {
700 case GP_OK:
701 break;
702 case GP_ERROR_CANCEL:
703 if (camera->multi)
704 gp_camera_exit (camera->camera, NULL);
705 gtk_object_destroy (GTK_OBJECT (s));
706 return -1;
707 default:
708 if (camera->multi)
709 gp_camera_exit (camera->camera, NULL);
710 dialog = gtkam_error_new (result, GTKAM_STATUS (s)->context,
711 GTK_WIDGET (save), _("Could not get file list "
712 "for folder '%s'"), folder);
713 gtk_widget_show (dialog);
714 gtk_object_destroy (GTK_OBJECT (s));
715 return -1;
716 }
717 gtk_object_destroy (GTK_OBJECT (s));
718
719 if (strcmp (folder, "/")) {
720 new_path = g_strdup_printf ("%s/%s", path,
721 basename ((char *) folder));
722 if (mkdir (new_path, 00755) < 0) {
723 dialog = gtkam_error_new (result,
724 GTKAM_STATUS (s)->context,
725 GTK_WIDGET (save),
726 _("Could not create directory '%s'"),
727 new_path);
728 gtk_widget_show (dialog);
729 g_free(new_path);
730 gtk_object_destroy (GTK_OBJECT (s));
731 return -1;
732 }
733 } else
734 new_path = g_strdup (path);
735
736 count = gp_list_count (flist);
737 if (count == 1)
738 s = gtkam_cancel_new (_("Downloading file from '%s'"), folder);
739 else
740 s = gtkam_cancel_new (_("Downloading %i files from '%s'"),
741 count, folder);
742 gtk_window_set_transient_for (GTK_WINDOW (s), save);
743 g_signal_emit (G_OBJECT (tree), signals[NEW_DIALOG], 0, s);
744 gtk_widget_show (s);
745
746 if (count > 1)
747 id = gp_context_progress_start (
748 GTKAM_CANCEL (s)->context->context, count,
749 _("Downloading %i files..."), count);
750
751 /* Loop through files */
752 for (i = 0; i < count; i++) {
753 gp_list_get_name (flist, i, &name);
754
755 result = tree_get_file (camera, new_path, folder, name,
756 GTKAM_CANCEL (s)->context, save);
757
758 if (result < 0) {
759 if (count > 1)
760 gp_context_progress_stop (
761 GTKAM_CANCEL (s)->context->context, id);
762 dialog = gtkam_error_new (result,
763 GTKAM_CANCEL (s)->context,
764 GTK_WIDGET(save), _("Problem getting "
765 "'%s' from folder '%s'."),
766 name, folder);
767 gtk_widget_show (dialog);
768
769 g_free(new_path);
770 gtk_object_destroy (GTK_OBJECT (s));
771 return -1;
772 }
773
774 if (count > 1)
775 gp_context_progress_update (
776 GTKAM_CANCEL (s)->context->context, id, i + 1);
777 gp_context_idle (GTKAM_CANCEL (s)->context->context);
778 if (gp_context_cancel (GTKAM_CANCEL (s)->context->context) ==
779 GP_CONTEXT_FEEDBACK_CANCEL)
780 break;
781 }
782 gp_list_unref (flist);
783
784 if (count > 1)
785 gp_context_progress_stop (
786 GTKAM_CANCEL (s)->context->context, id);
787 gtk_object_destroy (GTK_OBJECT (s));
788
789 /* Recurse into subfolders */
790 s = gtkam_status_new (_("Listing subfolders in folder '%s'..."),
791 folder);
792 g_signal_emit (G_OBJECT (tree), signals[NEW_STATUS], 0, s);
793 gp_list_new (&slist);
794 result = gp_camera_folder_list_folders (camera->camera, folder, slist,
795 GTKAM_STATUS (s)->context->context);
796 switch (result) {
797 case GP_OK:
798 break;
799 case GP_ERROR_CANCEL:
800 if (camera->multi)
801 gp_camera_exit (camera->camera, NULL);
802 gtk_object_destroy (GTK_OBJECT (s));
803 g_free(new_path);
804 return -1;
805 default:
806 if (camera->multi)
807 gp_camera_exit (camera->camera, NULL);
808 dialog = gtkam_error_new (result, GTKAM_STATUS (s)->context,
809 GTK_WIDGET (save), _("Could not get subfolders list "
810 "for folder '%s'"), folder);
811 gtk_widget_show (dialog);
812 gtk_object_destroy (GTK_OBJECT (s));
813 g_free(new_path);
814 return -1;
815 }
816 gtk_object_destroy (GTK_OBJECT (s));
817
818 count = gp_list_count (slist);
819
820 for (i = 0; i < count; i++) {
821 gp_list_get_name (slist, i, &name);
822 name = tree_concat_dir_and_file (folder, name);
823
824 result = tree_save_dir (camera, tree, new_path, name, save);
825
826 g_free((gchar *) name);
827 if (result < 0)
828 break;
829 }
830 gp_list_unref (slist);
831
832 g_free(new_path);
833 return result;
834 }
835
836 static void
on_download_ok_clicked(GtkButton * button,GtkamTreeDownloadData * dd)837 on_download_ok_clicked (GtkButton *button, GtkamTreeDownloadData *dd)
838 {
839 const gchar *path, *final_path;
840 gchar *folder;
841 GtkamCamera *camera;
842
843 gtk_widget_hide (dd->fsel);
844
845 path = gtk_file_selection_get_filename (GTK_FILE_SELECTION (dd->fsel));
846 /* Get the directory path */
847 if (!g_file_test (path, G_FILE_TEST_EXISTS) ||
848 g_file_test (path, G_FILE_TEST_IS_REGULAR))
849 final_path = g_strdup (dirname ((char *) path));
850 else
851 final_path = g_strdup (path);
852
853 folder = gtkam_tree_get_path_from_iter (dd->tree, dd->iter);
854 camera = gtkam_tree_get_camera_from_iter (dd->tree, dd->iter);
855
856 tree_save_dir(camera, dd->tree, final_path, folder,
857 GTK_WINDOW(dd->fsel));
858 g_free((gchar *) final_path);
859 gtk_object_destroy (GTK_OBJECT (dd->fsel));
860 }
861
862 static void
action_download(gpointer callback_data,guint callback_action,GtkWidget * widget)863 action_download (gpointer callback_data, guint callback_action,
864 GtkWidget *widget)
865 {
866 GtkWidget *fsel;
867 GtkamTree *tree = GTKAM_TREE (callback_data);
868 GtkamTreeDownloadData *dd;
869 gchar *title, *folder;
870
871 folder = gtkam_tree_get_path_from_iter (tree, &tree->priv->iter);
872 title = g_strdup_printf (_("Download '%s' subtree to..."), folder);
873 g_free (folder);
874 fsel = gtk_file_selection_new (title);
875 g_free (title);
876 g_signal_emit (G_OBJECT (tree), signals[NEW_DIALOG], 0, fsel);
877 g_object_unref (G_OBJECT (fsel));
878
879 dd = g_new0 (GtkamTreeDownloadData, 1);
880 dd->fsel = fsel;
881 dd->tree = tree;
882 dd->iter = gtk_tree_iter_copy (&tree->priv->iter);
883 g_signal_connect (G_OBJECT (fsel), "destroy",
884 G_CALLBACK (on_download_destroy), dd);
885 g_signal_connect (G_OBJECT (GTK_FILE_SELECTION (fsel)->ok_button),
886 "clicked", G_CALLBACK (on_download_ok_clicked), dd);
887 g_signal_connect (G_OBJECT (GTK_FILE_SELECTION (fsel)->cancel_button),
888 "clicked", G_CALLBACK (on_download_cancel_clicked), fsel);
889 }
890
891 typedef enum _CameraTextType CameraTextType;
892 enum _CameraTextType {
893 CAMERA_TEXT_SUMMARY,
894 CAMERA_TEXT_MANUAL,
895 CAMERA_TEXT_ABOUT
896 };
897
898 static void
action_text(GtkamTree * tree,CameraTextType type)899 action_text (GtkamTree *tree, CameraTextType type)
900 {
901 GtkamCamera *camera;
902 GtkWidget *s, *d;
903 int r;
904 CameraText text;
905
906 camera = gtkam_tree_get_camera_from_iter (tree, &tree->priv->iter);
907 switch (type) {
908 case CAMERA_TEXT_SUMMARY:
909 s = gtkam_status_new (
910 _("Getting information about the camera..."));
911 break;
912 case CAMERA_TEXT_ABOUT:
913 s = gtkam_status_new (
914 _("Getting information about the driver..."));
915 break;
916 case CAMERA_TEXT_MANUAL:
917 default:
918 s = gtkam_status_new (_("Getting manual..."));
919 break;
920 }
921 g_signal_emit (G_OBJECT (tree), signals[NEW_STATUS], 0, s);
922 switch (type) {
923 case CAMERA_TEXT_SUMMARY:
924 r = gp_camera_get_summary (camera->camera, &text,
925 GTKAM_STATUS (s)->context->context);
926 break;
927 case CAMERA_TEXT_ABOUT:
928 r = gp_camera_get_about (camera->camera, &text,
929 GTKAM_STATUS (s)->context->context);
930 break;
931 case CAMERA_TEXT_MANUAL:
932 default:
933 r = gp_camera_get_manual (camera->camera, &text,
934 GTKAM_STATUS (s)->context->context);
935 break;
936 }
937 if (camera->multi)
938 gp_camera_exit (camera->camera, NULL);
939 switch (r) {
940 case GP_OK:
941 d = gtkam_close_new (text.text);
942 g_signal_emit (G_OBJECT (tree), signals[NEW_DIALOG], 0, d);
943 g_object_unref (G_OBJECT (d));
944 break;
945 case GP_ERROR_CANCEL:
946 break;
947 default:
948 d = gtkam_error_new (r, GTKAM_STATUS (s)->context, NULL,
949 _("Could not retrieve information."));
950 g_signal_emit (G_OBJECT (tree), signals[NEW_DIALOG], 0, d);
951 g_object_unref (G_OBJECT (d));
952 }
953 gtk_object_destroy (GTK_OBJECT (s));
954 }
955
956 static void
action_summary(gpointer callback_data,guint callback_action,GtkWidget * widget)957 action_summary (gpointer callback_data, guint callback_action,
958 GtkWidget *widget)
959 {
960 GtkamTree *tree = GTKAM_TREE (callback_data);
961
962 action_text (tree, CAMERA_TEXT_SUMMARY);
963 }
964
965 static void
action_preferences(gpointer callback_data,guint callback_action,GtkWidget * widget)966 action_preferences (gpointer callback_data, guint callback_action,
967 GtkWidget *widget)
968 {
969 GtkWidget *d;
970 GtkamTree *tree = GTKAM_TREE (callback_data);
971 GtkamCamera *camera;
972
973 camera = gtkam_tree_get_camera_from_iter (tree, &tree->priv->iter);
974 d = gtkam_config_new (camera);
975 if (!d)
976 return;
977 g_signal_emit (G_OBJECT (tree), signals[NEW_DIALOG], 0, d);
978 g_object_unref (G_OBJECT (d));
979 }
980
981 static void
action_about(gpointer callback_data,guint callback_action,GtkWidget * widget)982 action_about (gpointer callback_data, guint callback_action,
983 GtkWidget *widget)
984 {
985 GtkamTree *tree = GTKAM_TREE (callback_data);
986
987 action_text (tree, CAMERA_TEXT_ABOUT);
988 }
989
990 typedef struct _CameraSelectedData CameraSelectedData;
991 struct _CameraSelectedData {
992 GtkamTree *tree;
993 GtkTreeIter *iter;
994 };
995
996 static void
on_camera_selected(GtkamChooser * chooser,GtkamCamera * camera,CameraSelectedData * data)997 on_camera_selected (GtkamChooser *chooser, GtkamCamera *camera,
998 CameraSelectedData *data)
999 {
1000 CameraAbilities a;
1001 GtkTreeSelection *s;
1002 GtkamTreeFolderUnselectedData fud;
1003
1004 s = gtk_tree_view_get_selection (GTK_TREE_VIEW (data->tree));
1005 if (gtk_tree_selection_iter_is_selected (s, data->iter)) {
1006 fud.camera = camera;
1007 fud.folder = "/";
1008 g_signal_emit (G_OBJECT (data->tree),
1009 signals[FOLDER_UNSELECTED], 0, &fud);
1010 }
1011
1012 gp_camera_get_abilities (camera->camera, &a);
1013 gtk_tree_store_set (data->tree->priv->store, data->iter,
1014 FOLDER_COLUMN, a.model,
1015 CAMERA_COLUMN, camera, -1);
1016 gtkam_tree_update_iter (data->tree, data->iter);
1017 gtkam_tree_save (data->tree);
1018 }
1019
1020 static void
camera_selected_data_destroy(gpointer data)1021 camera_selected_data_destroy (gpointer data)
1022 {
1023 CameraSelectedData *d = data;
1024
1025 gtk_tree_iter_free (d->iter);
1026 g_free (d);
1027 }
1028
1029 static void
action_remove_camera(gpointer callback_data,guint callback_action,GtkWidget * widget)1030 action_remove_camera (gpointer callback_data, guint callback_action,
1031 GtkWidget *widget)
1032 {
1033 GtkamTree *tree = GTKAM_TREE (callback_data);
1034
1035 gtk_tree_store_remove (tree->priv->store, &tree->priv->iter);
1036 gtkam_tree_save (tree);
1037 }
1038
1039 static void
action_select_camera(gpointer callback_data,guint callback_action,GtkWidget * widget)1040 action_select_camera (gpointer callback_data, guint callback_action,
1041 GtkWidget *widget)
1042 {
1043 GtkWidget *d;
1044 GtkamTree *tree = GTKAM_TREE (callback_data);
1045 CameraSelectedData *data;
1046
1047 d = gtkam_chooser_new ();
1048 g_signal_emit (G_OBJECT (tree), signals[NEW_DIALOG], 0, d);
1049 g_object_unref (G_OBJECT (d));
1050 gtkam_chooser_set_camera (GTKAM_CHOOSER (d),
1051 gtkam_tree_get_camera_from_iter (tree, &tree->priv->iter));
1052 gtk_window_set_title (GTK_WINDOW (d), _("Select Camera"));
1053 data = g_new0 (CameraSelectedData, 1);
1054 data->tree = tree;
1055 data->iter = gtk_tree_iter_copy (&tree->priv->iter);
1056 g_signal_connect (G_OBJECT (d), "camera_selected",
1057 G_CALLBACK (on_camera_selected), data);
1058 g_object_set_data_full (G_OBJECT (d), "data", data,
1059 camera_selected_data_destroy);
1060 }
1061
1062 static void
on_captured(GtkamPreview * preview,GtkamPreviewCapturedData * data,GtkamTree * tree)1063 on_captured (GtkamPreview *preview, GtkamPreviewCapturedData *data,
1064 GtkamTree *tree)
1065 {
1066 GtkamTreeFileAddedData fad;
1067
1068 fad.folder = data->folder;
1069 fad.name = data->name;
1070 fad.camera = data->camera;
1071 g_signal_emit (G_OBJECT (tree), signals[FILE_ADDED], 0, &fad);
1072 }
1073
1074 static void
action_capture(gpointer callback_data,guint callback_action,GtkWidget * widget)1075 action_capture (gpointer callback_data, guint callback_action,
1076 GtkWidget *widget)
1077 {
1078 GtkamTree *tree = GTKAM_TREE (callback_data);
1079 GtkamCamera *camera;
1080 CameraAbilities a;
1081 GtkWidget *s, *d;
1082 int r;
1083 GtkamTreeErrorData e;
1084 GtkamTreeFileAddedData fad;
1085 gchar *msg;
1086 CameraFilePath path;
1087
1088 camera = gtkam_tree_get_camera_from_iter (tree, &tree->priv->iter);
1089
1090 /* Let's first check if the camera supports previews */
1091 gp_camera_get_abilities (camera->camera, &a);
1092 if (TRUE /*a.operations & GP_OPERATION_CAPTURE_PREVIEW*/) {
1093 d = gtkam_preview_new (camera);
1094 g_signal_emit (G_OBJECT (tree), signals[NEW_DIALOG], 0, d);
1095 g_object_unref (G_OBJECT (d));
1096 g_signal_connect (G_OBJECT (d), "captured",
1097 G_CALLBACK (on_captured), tree);
1098 return;
1099 }
1100
1101 /* The camera doesn't support previews. Capture an image. */
1102 s = gtkam_status_new (_("Capturing image..."));
1103 g_signal_emit (G_OBJECT (tree), signals[NEW_STATUS], 0, s);
1104 r = gp_camera_capture (camera->camera, GP_CAPTURE_IMAGE, &path,
1105 GTKAM_STATUS (s)->context->context);
1106 if (camera->multi)
1107 gp_camera_exit (camera->camera, NULL);
1108 switch (r) {
1109 case GP_OK:
1110 fad.camera = camera;
1111 fad.folder = path.folder;
1112 fad.name = path.name;
1113 g_signal_emit (G_OBJECT (tree), signals[FILE_ADDED], 0, &fad);
1114 break;
1115 case GP_ERROR_CANCEL:
1116 break;
1117 default:
1118 e.context = GTKAM_STATUS (s)->context;
1119 e.result = r;
1120 e.msg = msg = g_strdup (_("Could not capture."));
1121 g_signal_emit (G_OBJECT (tree), signals[NEW_ERROR], 0, &e);
1122 g_free (msg);
1123 break;
1124 }
1125 gtk_object_destroy (GTK_OBJECT (s));
1126 }
1127
1128 static void
action_manual(gpointer callback_data,guint callback_action,GtkWidget * widget)1129 action_manual (gpointer callback_data, guint callback_action,
1130 GtkWidget *widget)
1131 {
1132 GtkamTree *tree = GTKAM_TREE (callback_data);
1133
1134 action_text (tree, CAMERA_TEXT_MANUAL);
1135 }
1136
1137 static void
on_new_camera_selected(GtkamChooser * chooser,GtkamCamera * camera,GtkamTree * tree)1138 on_new_camera_selected (GtkamChooser *chooser, GtkamCamera *camera,
1139 GtkamTree *tree)
1140 {
1141 gtkam_tree_add_camera (tree, camera);
1142 }
1143
1144 static void
on_add_camera_activate(GtkMenuItem * item,GtkamTree * tree)1145 on_add_camera_activate (GtkMenuItem *item, GtkamTree *tree)
1146 {
1147 GtkWidget *d, *w;
1148
1149 w = gtk_widget_get_ancestor (GTK_WIDGET (tree), GTK_TYPE_WINDOW);
1150 d = gtkam_chooser_new ();
1151 gtk_window_set_transient_for (GTK_WINDOW (d), GTK_WINDOW (w));
1152 gtk_widget_show (d);
1153 g_signal_connect (G_OBJECT (d), "camera_selected",
1154 G_CALLBACK (on_new_camera_selected), tree);
1155 }
1156
1157 static GtkItemFactoryEntry mi[] =
1158 {
1159 {N_("/Upload file..."), NULL, action_upload, 0, NULL},
1160 {N_("/Make directory..."), NULL, action_mkdir, 0, NULL},
1161 {N_("/Delete directory"), NULL, action_rmdir, 0, NULL},
1162 {N_("/Save directory tree..."), NULL, action_download, 0, NULL},
1163 {"/sep1", NULL, NULL, 0, "<Separator>"},
1164 {N_("/Capture image..."), NULL, action_capture, 0, NULL},
1165 {N_("/View camera preferences"), NULL, action_preferences, 0,
1166 "<StockItem>", GTK_STOCK_PREFERENCES},
1167 {N_("/View camera summary"), NULL, action_summary, 0, NULL},
1168 {N_("/View camera manual"), NULL, action_manual, 0, NULL},
1169 {N_("/View driver details"), NULL, action_about, 0, NULL},
1170 {"/sep2", NULL, NULL, 0, "<Separator>"},
1171 {N_("/Select camera..."), NULL, action_select_camera, 0, NULL},
1172 {N_("/Remove camera"), NULL, action_remove_camera, 0, NULL},
1173 };
1174
1175 #ifdef ENABLE_NLS
1176
1177 static gchar *
translate_func(const gchar * path,gpointer data)1178 translate_func (const gchar *path, gpointer data)
1179 {
1180 return (_(path));
1181 }
1182
1183 #endif
1184
1185 static gint
on_button_press_event(GtkWidget * widget,GdkEventButton * event,GtkamTree * tree)1186 on_button_press_event (GtkWidget *widget, GdkEventButton *event,
1187 GtkamTree *tree)
1188 {
1189 GtkTreePath *path = NULL;
1190 GtkamCamera *camera;
1191 GtkWidget *w, *m, *i;
1192 CameraAbilities a;
1193
1194 switch (event->button) {
1195 case 3:
1196
1197 /* Right-click on a tree item? */
1198 if (!gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (tree),
1199 event->x, event->y, &path, NULL, NULL, NULL)) {
1200 m = gtk_menu_new ();
1201 i = gtk_menu_item_new_with_mnemonic (
1202 _("_Add camera..."));
1203 gtk_widget_show (i);
1204 gtk_container_add (GTK_CONTAINER (m), i);
1205 g_signal_connect (G_OBJECT (i), "activate",
1206 G_CALLBACK (on_add_camera_activate), tree);
1207 gtk_menu_popup (GTK_MENU (m), NULL, NULL, NULL, NULL,
1208 event->button, event->time);
1209 return (TRUE);
1210 }
1211
1212 gtk_tree_model_get_iter (GTK_TREE_MODEL (tree->priv->store),
1213 &tree->priv->iter, path);
1214 camera = gtkam_tree_get_camera_from_iter (tree,
1215 &tree->priv->iter);
1216 gp_camera_get_abilities (camera->camera, &a);
1217 gtk_tree_path_free (path);
1218
1219 /* What operations does the camera support? */
1220 w = gtk_item_factory_get_widget (tree->priv->factory,
1221 "/Make directory...");
1222 gtk_widget_set_sensitive (w,
1223 a.folder_operations & GP_FOLDER_OPERATION_MAKE_DIR);
1224 w = gtk_item_factory_get_widget (tree->priv->factory,
1225 "/Delete directory");
1226 gtk_widget_set_sensitive (w,
1227 a.folder_operations & GP_FOLDER_OPERATION_REMOVE_DIR);
1228 w = gtk_item_factory_get_widget (tree->priv->factory,
1229 "/Upload file...");
1230 gtk_widget_set_sensitive (w,
1231 a.folder_operations & GP_FOLDER_OPERATION_PUT_FILE);
1232 w = gtk_item_factory_get_widget (tree->priv->factory,
1233 "/View camera preferences");
1234 gtk_widget_set_sensitive (w,
1235 a.operations & GP_OPERATION_CONFIG);
1236 w = gtk_item_factory_get_widget (tree->priv->factory,
1237 "/Capture image...");
1238 gtk_widget_set_sensitive (w,
1239 /*a.operations & GP_OPERATION_CAPTURE_IMAGE */ TRUE);
1240
1241 gtk_item_factory_popup (tree->priv->factory, event->x_root,
1242 event->y_root, event->button, event->time);
1243
1244 return (TRUE);
1245 default:
1246 return (FALSE);
1247 }
1248 }
1249
1250 static void
on_row_deleted(GtkTreeModel * model,GtkTreePath * path,GtkamTree * tree)1251 on_row_deleted (GtkTreeModel *model, GtkTreePath *path,
1252 GtkamTree *tree)
1253 {
1254 GtkTreeIter iter;
1255 gchar *folder;
1256 GtkamTreeFolderUnselectedData fdd;
1257
1258 if (!gtk_tree_model_get_iter (model, &iter, path))
1259 return;
1260
1261 fdd.camera = gtkam_tree_get_camera_from_iter (tree, &iter);
1262 fdd.folder = folder = gtkam_tree_get_path_from_iter (tree, &iter);
1263 g_signal_emit (G_OBJECT (tree), signals[FOLDER_UNSELECTED], 0, &fdd);
1264 g_free (folder);
1265 }
1266
1267 static void
on_drag_data_received(GtkWidget * widget,GdkDragContext * context,gint x,gint y,GtkSelectionData * selection_data,guint info,guint time,GtkamTree * tree)1268 on_drag_data_received (GtkWidget *widget, GdkDragContext *context,
1269 gint x, gint y, GtkSelectionData *selection_data,
1270 guint info, guint time, GtkamTree *tree)
1271 {
1272 g_warning ("Fixme: on_drag_data_received");
1273 }
1274
1275 #if 0
1276 static GtkTargetEntry targets[] = {
1277 {"text/uri-list", 0, 0}
1278 };
1279 #endif
1280
1281 GtkWidget *
gtkam_tree_new(void)1282 gtkam_tree_new (void)
1283 {
1284 GtkamTree *tree;
1285 GtkCellRenderer *renderer;
1286 GtkTreeSelection *selection;
1287 GtkAccelGroup *ag;
1288
1289 tree = g_object_new (GTKAM_TYPE_TREE, NULL);
1290 gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (tree), FALSE);
1291 #if 0
1292 gtk_tree_view_enable_model_drag_dest (GTK_TREE_VIEW (tree),
1293 targets, G_N_ELEMENTS (targets),
1294 GDK_ACTION_COPY);
1295 #endif
1296 g_signal_connect (G_OBJECT (tree), "drag_data_received",
1297 G_CALLBACK (on_drag_data_received), tree);
1298 g_signal_connect (G_OBJECT (tree), "button_press_event",
1299 G_CALLBACK (on_button_press_event), tree);
1300
1301 gtk_tooltips_set_tip (tree->priv->tooltips, GTK_WIDGET (tree),
1302 (_("Please right-click to access additional menus")), NULL);
1303
1304 ag = gtk_accel_group_new ();
1305 tree->priv->factory = gtk_item_factory_new (GTK_TYPE_MENU,
1306 "<popup>", ag);
1307 #ifdef ENABLE_NLS
1308 gtk_item_factory_set_translate_func (GTK_ITEM_FACTORY (tree->priv->factory),
1309 translate_func, NULL, NULL);
1310 #endif
1311 gtk_item_factory_create_items (tree->priv->factory,
1312 G_N_ELEMENTS (mi), mi, tree);
1313 g_object_ref (G_OBJECT (tree->priv->factory));
1314 gtk_object_sink (GTK_OBJECT (tree->priv->factory));
1315
1316 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree));
1317 gtk_tree_selection_set_mode (selection, GTK_SELECTION_MULTIPLE);
1318 gtk_tree_selection_set_select_function (selection, selection_func,
1319 tree, NULL);
1320
1321 tree->priv->store = gtk_tree_store_new (NUM_COLUMNS, G_TYPE_STRING,
1322 GTKAM_TYPE_CAMERA);
1323 g_signal_connect (G_OBJECT (tree->priv->store), "row_deleted",
1324 G_CALLBACK (on_row_deleted), tree);
1325 gtk_tree_view_set_model (GTK_TREE_VIEW (tree),
1326 GTK_TREE_MODEL (tree->priv->store));
1327
1328 /* Column for folder names. */
1329 renderer = gtk_cell_renderer_text_new ();
1330 gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (tree),
1331 -1, _("Folder"), renderer, "text",
1332 FOLDER_COLUMN, NULL);
1333 g_signal_connect (G_OBJECT (tree), "row_expanded",
1334 G_CALLBACK (on_row_expanded), tree);
1335
1336 return (GTK_WIDGET (tree));
1337 }
1338
1339 void
gtkam_tree_add_camera(GtkamTree * tree,GtkamCamera * camera)1340 gtkam_tree_add_camera (GtkamTree *tree, GtkamCamera *camera)
1341 {
1342 CameraAbilities a;
1343 GtkTreeIter iter;
1344
1345 g_return_if_fail (GTKAM_IS_TREE (tree));
1346 g_return_if_fail (GTKAM_IS_CAMERA (camera));
1347
1348 gp_camera_get_abilities (camera->camera, &a);
1349 gtk_tree_store_append (tree->priv->store, &iter, NULL);
1350 gtk_tree_store_set (tree->priv->store, &iter,
1351 FOLDER_COLUMN, a.model,
1352 CAMERA_COLUMN, camera, -1);
1353 gtkam_tree_update_iter (tree, &iter);
1354 gtkam_tree_save (tree);
1355 }
1356
1357 #ifdef HAVE_GP_CAMERA_SET_TIMEOUT_FUNCS
1358
1359 typedef struct _TimeoutData TimeoutData;
1360 struct _TimeoutData {
1361 Camera *camera;
1362 CameraTimeoutFunc func;
1363 };
1364
1365 static gboolean
timeout_func(gpointer data)1366 timeout_func (gpointer data)
1367 {
1368 TimeoutData *td = data;
1369
1370 td->func (td->camera, NULL);
1371
1372 /* Repeat forever */
1373 return (TRUE);
1374 }
1375
1376 static void
timeout_destroy_notify(gpointer data)1377 timeout_destroy_notify (gpointer data)
1378 {
1379 TimeoutData *td = data;
1380
1381 g_free (td);
1382 }
1383
1384 static unsigned int
start_timeout_func(Camera * camera,unsigned int timeout,CameraTimeoutFunc func,void * data)1385 start_timeout_func (Camera *camera, unsigned int timeout,
1386 CameraTimeoutFunc func, void *data)
1387 {
1388 TimeoutData *td;
1389
1390 td = g_new0 (TimeoutData, 1);
1391 td->camera = camera;
1392 td->func = func;
1393
1394 return (gtk_timeout_add_full (timeout * 1000, timeout_func, NULL,
1395 td, timeout_destroy_notify));
1396 }
1397
1398 static void
stop_timeout_func(Camera * camera,unsigned int id,void * data)1399 stop_timeout_func (Camera *camera, unsigned int id, void *data)
1400 {
1401 gtk_timeout_remove (id);
1402 }
1403
1404 #endif
1405
1406 void
gtkam_tree_load(GtkamTree * tree)1407 gtkam_tree_load (GtkamTree *tree)
1408 {
1409 GtkWidget *s;
1410 char port[1024], speed[1024], model[1024], multi[1024];
1411 Camera *camera;
1412 CameraAbilitiesList *al;
1413 GPPortInfoList *il;
1414 GPPortInfo info;
1415 CameraAbilities a;
1416 int n, p, result;
1417 gchar *ms;
1418 guint i;
1419 GtkTreeIter iter;
1420 GtkamCamera *c;
1421
1422 g_return_if_fail (GTKAM_IS_TREE (tree));
1423
1424 s = gtkam_status_new (_("Loading cameras..."));
1425 g_signal_emit (G_OBJECT (tree), signals[NEW_STATUS], 0, s);
1426
1427 gp_abilities_list_new (&al);
1428 gp_abilities_list_load (al, GTKAM_STATUS (s)->context->context);
1429 gp_port_info_list_new (&il);
1430 gp_port_info_list_load (il);
1431
1432 gtk_object_destroy (GTK_OBJECT (s));
1433
1434 /* Load settings */
1435 for (i = 1; ; i++) {
1436 ms = g_strdup_printf ("model-%i", i);
1437 result = gp_setting_get ("gtkam", ms, model);
1438 g_free (ms);
1439 if (result < 0)
1440 break;
1441 if (!strcmp (model, ""))
1442 break;
1443
1444 ms = g_strdup_printf ("port-%i", i);
1445 result = gp_setting_get ("gtkam", ms, port);
1446 g_free (ms);
1447 if (result < 0)
1448 break;
1449
1450 ms = g_strdup_printf ("multi-%i", i);
1451 result = gp_setting_get ("gtkam", ms, multi);
1452 g_free (ms);
1453 if (result < 0)
1454 break;
1455
1456 ms = g_strdup_printf ("speed-%i", i);
1457 result = gp_setting_get ("gtkam", ms, speed);
1458 g_free (ms);
1459 if (result < 0)
1460 break;
1461
1462 gp_camera_new (&camera);
1463 #ifdef HAVE_GP_CAMERA_SET_TIMEOUT_FUNCS
1464 gp_camera_set_timeout_funcs (camera, start_timeout_func,
1465 stop_timeout_func, NULL);
1466 #endif
1467
1468 n = gp_abilities_list_lookup_model (al, model);
1469 gp_abilities_list_get_abilities (al, n, &a);
1470
1471 if (strcmp (port, "") && strcmp (port, "None") &&
1472 strcmp (model, "Directory Browse")) {
1473 p = gp_port_info_list_lookup_path (il, port);
1474 if (p < 0) {
1475 g_warning ("Could not find '%s' in port "
1476 "info list (%s)!", port,
1477 gp_result_as_string (p));
1478 gp_camera_unref (camera);
1479 continue;
1480 }
1481 gp_port_info_list_get_info (il, p, &info);
1482 gp_camera_set_port_info (camera, info);
1483 }
1484
1485 gp_camera_set_abilities (camera, a);
1486 if (atoi (speed))
1487 gp_camera_set_port_speed (camera, atoi (speed));
1488
1489 /* Add this camera to our tree. */
1490 gtk_tree_store_append (tree->priv->store, &iter, NULL);
1491 c = gtkam_camera_new (camera, atoi (multi));
1492 gtk_tree_store_set (tree->priv->store, &iter,
1493 FOLDER_COLUMN, model,
1494 CAMERA_COLUMN, c, -1);
1495 g_object_unref (G_OBJECT (c));
1496 gtkam_tree_update_iter (tree, &iter);
1497 }
1498
1499 gp_abilities_list_free (al);
1500 gp_port_info_list_free (il);
1501 }
1502
1503 void
gtkam_tree_save(GtkamTree * tree)1504 gtkam_tree_save (GtkamTree *tree)
1505 {
1506 GtkTreeIter child;
1507 guint i, n;
1508 GtkamCamera *camera;
1509 GPPortInfo info;
1510 CameraAbilities a;
1511 int speed, result;
1512 gchar *ms, *mm;
1513 char model[1024];
1514
1515 /* Clear the configuration file */
1516 for (i = 1; ; i++) {
1517 ms = g_strdup_printf ("model-%i", i);
1518 result = gp_setting_get ("gtkam", ms, model);
1519 g_free (ms);
1520 if (result < 0)
1521 break;
1522
1523 memset (model, 0, sizeof (model));
1524 ms = g_strdup_printf ("model-%i", i);
1525 gp_setting_set ("gtkam", ms, model);
1526 g_free (ms);
1527 }
1528
1529 /* Iterate over all cameras. */
1530 n = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (tree->priv->store),
1531 NULL);
1532 for (i = 0; i < n; i++) {
1533 #ifdef HAVE_GP_PORT_INFO_GET_NAME
1534 char *xpath;
1535 #endif
1536 gtk_tree_model_iter_nth_child (
1537 GTK_TREE_MODEL (tree->priv->store),
1538 &child, NULL, i);
1539 camera = gtkam_tree_get_camera_from_iter (tree, &child);
1540
1541 gp_camera_get_abilities (camera->camera, &a);
1542 gp_camera_get_port_info (camera->camera, &info);
1543 speed = gp_camera_get_port_speed (camera->camera);
1544
1545 ms = g_strdup_printf ("model-%i", i + 1);
1546 gp_setting_set ("gtkam", ms, a.model);
1547 g_free (ms);
1548
1549 ms = g_strdup_printf ("port-%i", i + 1);
1550 #ifdef HAVE_GP_PORT_INFO_GET_NAME
1551 gp_port_info_get_path (info, &xpath);
1552 gp_setting_set ("gtkam", ms, xpath);
1553 #else
1554 gp_setting_set ("gtkam", ms, info.path);
1555 #endif
1556 g_free (ms);
1557
1558 ms = g_strdup_printf ("multi-%i", i + 1);
1559 mm = g_strdup_printf ("%i", camera->multi ? 1 : 0);
1560 gp_setting_set ("gtkam", ms, mm);
1561 g_free (mm);
1562 g_free (ms);
1563
1564 ms = g_strdup_printf ("speed-%i", i + 1);
1565 mm = g_strdup_printf ("%i", speed);
1566 gp_setting_set ("gtkam", ms, mm);
1567 g_free (mm);
1568 g_free (ms);
1569 }
1570 }
1571