Avoid using deprecated GtkAlignment in main window
[cheese.git] / src / thumbview / cheese-thumb-view.c
blobb5ce06b38a50ac47a520623242576444e36602d0
1 /*
2 * Copyright © 2007,2008 daniel g. siegel <dgsiegel@gnome.org>
3 * Copyright © 2007,2008 Jaap Haitsma <jaap@haitsma.org>
4 * Copyright © 2008 Filippo Argiolas <filippo.argiolas@gmail.com>
6 * Licensed under the GNU General Public License Version 2
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #ifdef HAVE_CONFIG_H
23 #include "cheese-config.h"
24 #endif
26 #include <glib.h>
27 #include <gtk/gtk.h>
28 #include <libgnome-desktop/gnome-desktop-thumbnail.h>
29 #include <string.h>
31 #include "cheese-fileutil.h"
32 #include "cheese-thumbnail.h"
34 #include "cheese-thumb-view.h"
36 const guint THUMB_VIEW_MINIMUM_WIDTH = 140;
37 const guint THUMB_VIEW_MINIMUM_HEIGHT = 100;
39 const gchar CHEESE_OLD_VIDEO_NAME_SUFFIX[] = ".ogv";
41 typedef struct
43 GtkListStore *store;
44 CheeseFileUtil *fileutil;
45 GFileMonitor *photo_file_monitor;
46 GFileMonitor *video_file_monitor;
47 GnomeDesktopThumbnailFactory *factory;
48 gboolean multiplex_thumbnail_generator;
49 gboolean vertical;
50 guint n_items;
51 guint idle_id;
52 GQueue *thumbnails;
53 } CheeseThumbViewPrivate;
55 G_DEFINE_TYPE_WITH_PRIVATE (CheeseThumbView, cheese_thumb_view, GTK_TYPE_ICON_VIEW);
57 enum
59 THUMBNAIL_PIXBUF_COLUMN,
60 THUMBNAIL_URL_COLUMN,
61 THUMBNAIL_BASENAME_URL_COLUMN
64 /* Drag 'n Drop */
65 enum
67 TARGET_PLAIN,
68 TARGET_PLAIN_UTF8,
69 TARGET_URILIST,
72 static GtkTargetEntry target_table[] = {
73 {"text/uri-list", 0, TARGET_URILIST},
76 typedef struct
78 CheeseThumbView *thumb_view;
79 GFile *file;
80 GtkTreeIter iter;
81 } CheeseThumbViewIdleData;
84 static void cheese_thumb_view_constructed (GObject *object);
85 GtkWidget * cheese_thumb_view_new (void);
87 static gboolean
88 cheese_thumb_view_idle_append_item (gpointer data)
90 CheeseThumbViewIdleData *item = g_queue_peek_head (data);
91 CheeseThumbView *thumb_view;
92 CheeseThumbViewPrivate *priv;
94 /* Disconnect the idle handler when the queue is empty. */
95 if (item == NULL) return FALSE;
97 thumb_view = item->thumb_view;
98 priv = cheese_thumb_view_get_instance_private (thumb_view);
101 GnomeDesktopThumbnailFactory *factory = priv->factory;
102 GFile *file = item->file;
103 GtkTreeIter iter = item->iter;
104 GdkPixbuf *pixbuf = NULL;
105 GFileInfo *info;
106 char *thumb_loc;
107 GTimeVal mtime;
108 char *mime_type;
109 char *uri;
110 char *filename;
112 info = g_file_query_info (file, "standard::content-type,time::modified", 0, NULL, NULL);
114 if (!info)
116 g_warning ("Invalid filename\n");
117 return TRUE;
119 g_file_info_get_modification_time (info, &mtime);
120 mime_type = g_strdup (g_file_info_get_content_type (info));
122 uri = g_file_get_uri (file);
123 filename = g_file_get_path (file);
125 thumb_loc = gnome_desktop_thumbnail_factory_lookup (factory, uri, mtime.tv_sec);
127 if (!thumb_loc)
129 pixbuf = gnome_desktop_thumbnail_factory_generate_thumbnail (factory, uri, mime_type);
130 if (!pixbuf)
132 g_warning ("could not generate thumbnail for %s (%s)\n", filename, mime_type);
134 else
136 gnome_desktop_thumbnail_factory_save_thumbnail (factory, pixbuf, uri, mtime.tv_sec);
139 else
141 pixbuf = gdk_pixbuf_new_from_file (thumb_loc, NULL);
142 if (!pixbuf)
144 g_warning ("could not load thumbnail %s (%s)\n", filename, mime_type);
147 g_object_unref (info);
148 g_free (thumb_loc);
149 g_free (uri);
151 if (!pixbuf)
153 gchar *escape = NULL;
154 GError *error = NULL;
155 escape = g_strrstr (mime_type, "/");
156 if (escape != NULL) *escape = '-';
157 pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
158 mime_type,
160 GTK_ICON_LOOKUP_GENERIC_FALLBACK,
161 &error);
162 if (error)
164 g_warning ("%s", error->message);
165 return TRUE;
168 else
170 cheese_thumbnail_add_frame (&pixbuf);
173 gtk_list_store_set (priv->store, &iter,
174 THUMBNAIL_PIXBUF_COLUMN, pixbuf, -1);
176 g_free (mime_type);
177 g_free (filename);
178 g_object_unref (pixbuf);
179 g_object_unref (file);
180 g_slice_free (CheeseThumbViewIdleData, item);
181 g_queue_pop_head (data);
183 return TRUE;
186 static void
187 cheese_thumb_view_append_item (CheeseThumbView *thumb_view, GFile *file)
189 CheeseThumbViewPrivate *priv = cheese_thumb_view_get_instance_private (thumb_view);
191 GtkTreeIter iter;
192 GtkIconTheme *icon_theme;
193 GdkPixbuf *pixbuf = NULL;
194 GtkTreePath *path;
195 char *filename, *basename;
196 GError *error = NULL;
197 gboolean skip = FALSE;
198 GFileInfo *info;
199 goffset size;
201 CheeseThumbViewIdleData *data;
203 info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_SIZE, 0, NULL,
204 NULL);
205 if (!info)
207 /* This is normal since photos first get created with a tmpname, ie:
208 * "2013-06-13-113155.jpg.DQRGYW" and then moved to their final name,
209 * we will get another append_item call for the final name. */
210 return;
212 size = g_file_info_get_size (info);
213 g_object_unref (info);
215 /* Ignore 0-sized files, bug 677735. */
216 if (size == 0)
217 return;
219 filename = g_file_get_path (file);
221 if (!(g_str_has_suffix (filename, CHEESE_PHOTO_NAME_SUFFIX))
222 && !(g_str_has_suffix (filename, CHEESE_VIDEO_NAME_SUFFIX))
223 && !(g_str_has_suffix (filename, CHEESE_OLD_VIDEO_NAME_SUFFIX)))
225 g_free (filename);
226 return;
229 if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (priv->store), &iter))
231 gchar *col_filename;
233 /* check if the selected item is the first, else go through the store */
234 gtk_tree_model_get (GTK_TREE_MODEL (priv->store), &iter, THUMBNAIL_URL_COLUMN, &col_filename, -1);
235 /* FIXME: col_filename is in GLib filename encoding, not ASCII. */
236 if (g_ascii_strcasecmp (col_filename, filename))
238 while (gtk_tree_model_iter_next (GTK_TREE_MODEL (priv->store), &iter))
240 g_free (col_filename);
242 gtk_tree_model_get (GTK_TREE_MODEL (priv->store), &iter, THUMBNAIL_URL_COLUMN, &col_filename, -1);
243 /* FIXME: col_filename is in GLib filename encoding, not ASCII. */
244 if (!g_ascii_strcasecmp (col_filename, filename))
246 skip = TRUE;
247 break;
251 else
253 skip = TRUE;
255 g_free (col_filename);
256 g_free (filename);
258 if (skip) return;
260 else
262 g_free (filename);
265 if (priv->multiplex_thumbnail_generator)
267 gchar *f;
269 f = g_strdup_printf ("/org/gnome/Cheese/pixmaps/cheese-%i.svg",
270 g_random_int_range (1, 4));
271 pixbuf = gdk_pixbuf_new_from_resource (f, NULL);
272 g_free (f);
274 else
276 icon_theme = gtk_icon_theme_get_default ();
277 pixbuf = gtk_icon_theme_load_icon (icon_theme,
278 "image-loading",
280 GTK_ICON_LOOKUP_GENERIC_FALLBACK,
281 &error);
284 if (!pixbuf)
286 g_warning ("Couldn't load icon: %s", error->message);
287 g_error_free (error);
288 error = NULL;
291 filename = g_file_get_path (file);
292 basename = g_path_get_basename (filename);
294 gtk_list_store_append (priv->store, &iter);
295 gtk_list_store_set (priv->store, &iter,
296 THUMBNAIL_PIXBUF_COLUMN, pixbuf,
297 THUMBNAIL_URL_COLUMN, filename,
298 THUMBNAIL_BASENAME_URL_COLUMN, basename, -1);
299 g_free (filename);
300 g_free (basename);
301 path = gtk_tree_model_get_path (GTK_TREE_MODEL (priv->store), &iter);
302 gtk_icon_view_scroll_to_path (GTK_ICON_VIEW (thumb_view), path,
303 TRUE, 1.0, 0.5);
304 gtk_tree_path_free (path);
306 if (pixbuf) g_object_unref (pixbuf);
308 if (!priv->multiplex_thumbnail_generator)
310 data = g_slice_new0 (CheeseThumbViewIdleData);
311 data->thumb_view = g_object_ref (thumb_view);
312 data->file = g_object_ref (file);
313 data->iter = iter;
315 g_queue_push_tail (priv->thumbnails, data);
316 if (!priv->idle_id) g_idle_add (cheese_thumb_view_idle_append_item, priv->thumbnails);
320 void
321 cheese_thumb_view_remove_item (CheeseThumbView *thumb_view, GFile *file)
323 CheeseThumbViewPrivate *priv = cheese_thumb_view_get_instance_private (thumb_view);
325 gchar *filename;
326 GtkTreeIter iter;
327 gboolean found = FALSE;
329 filename = g_file_get_path (file);
331 if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (priv->store), &iter))
333 gchar *col_filename;
335 gtk_tree_model_get (GTK_TREE_MODEL (priv->store), &iter,
336 THUMBNAIL_URL_COLUMN, &col_filename, -1);
338 /* FIXME: col_filename is in GLib filename encoding, not ASCII. */
339 if (g_ascii_strcasecmp (col_filename, filename))
341 while (gtk_tree_model_iter_next (GTK_TREE_MODEL (priv->store),
342 &iter))
344 g_free (col_filename);
346 gtk_tree_model_get (GTK_TREE_MODEL (priv->store), &iter,
347 THUMBNAIL_URL_COLUMN, &col_filename, -1);
349 /* FIXME: col_filename is in GLib filename encoding, not ASCII. */
350 if (!g_ascii_strcasecmp (col_filename, filename))
352 found = TRUE;
353 break;
357 else
359 found = TRUE;
362 g_free (col_filename);
363 g_free (filename);
365 else
367 /* A single item was in the thumbview but it's been already removed. */
368 g_free (filename);
369 return;
372 if (!found) return;
374 gboolean valid = gtk_list_store_remove (priv->store, &iter);
375 if (!valid)
377 int len = gtk_tree_model_iter_n_children (GTK_TREE_MODEL (priv->store), NULL);
378 if (len <= 0)
379 return;
381 valid = gtk_tree_model_iter_nth_child (GTK_TREE_MODEL (priv->store), &iter, NULL, len - 1);
383 GtkTreePath *tree_path = gtk_tree_model_get_path (GTK_TREE_MODEL (priv->store), &iter);
384 gtk_icon_view_select_path (GTK_ICON_VIEW (thumb_view), tree_path);
385 gtk_tree_path_free (tree_path);
388 static void
389 cheese_thumb_view_monitor_cb (GFileMonitor *file_monitor,
390 GFile *file,
391 GFile *other_file,
392 GFileMonitorEvent event_type,
393 CheeseThumbView *thumb_view)
395 switch (event_type)
397 case G_FILE_MONITOR_EVENT_DELETED:
398 cheese_thumb_view_remove_item (thumb_view, file);
399 break;
401 case G_FILE_MONITOR_EVENT_MOVED:
402 cheese_thumb_view_remove_item (thumb_view, file);
403 cheese_thumb_view_append_item (thumb_view, other_file);
404 break;
406 case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT:
407 cheese_thumb_view_append_item (thumb_view, file);
408 break;
410 case G_FILE_MONITOR_EVENT_CREATED:
412 CheeseThumbViewPrivate *priv;
413 const char *path_photos;
414 char *filename;
415 GDir *dir_photos;
416 const char *name;
417 char *photo_name;
418 GFile *photo_file;
420 priv = cheese_thumb_view_get_instance_private (thumb_view);
421 path_photos = cheese_fileutil_get_photo_path (priv->fileutil);
422 filename = g_file_get_path (file);
423 if (!strcmp(path_photos, filename))
425 dir_photos = g_dir_open (path_photos, 0, NULL);
426 while ((name = g_dir_read_name (dir_photos)))
428 if (!(g_str_has_suffix (name, CHEESE_PHOTO_NAME_SUFFIX)))
429 continue;
430 photo_name = g_build_filename (path_photos, name, NULL);
431 photo_file = g_file_new_for_path (photo_name);
432 cheese_thumb_view_append_item (thumb_view, photo_file);
433 g_free (photo_name);
434 g_object_unref (photo_file);
436 g_dir_close (dir_photos);
439 g_free (filename);
440 break;
443 default:
444 break;
448 static void
449 cheese_thumb_view_on_drag_data_get_cb (GtkIconView *thumb_view,
450 GdkDragContext *drag_context,
451 GtkSelectionData *data,
452 guint info,
453 guint time,
454 gpointer user_data)
456 GList *list, *l;
457 GtkTreeIter iter;
458 GtkTreeModel *model;
459 char *str;
460 char *uris = NULL;
461 char *tmp_str;
463 list = gtk_icon_view_get_selected_items (thumb_view);
464 model = gtk_icon_view_get_model (thumb_view);
466 for (l = list; l != NULL; l = l->next)
468 gtk_tree_model_get_iter (model, &iter, l->data);
469 gtk_tree_model_get (model, &iter, 1, &str, -1);
470 gtk_tree_path_free (l->data);
472 /* we always store local paths in the model, but DnD
473 * needs URIs, so we must add file:// to the path.
476 /* build the "text/uri-list" string */
477 if (uris)
479 tmp_str = g_strconcat (uris, "file://", str, "\r\n", NULL);
480 g_free (uris);
482 else
484 tmp_str = g_strconcat ("file://", str, "\r\n", NULL);
486 uris = tmp_str;
488 g_free (str);
490 gtk_selection_data_set (data, gtk_selection_data_get_target (data),
491 8, (guchar *) uris, strlen (uris));
492 g_free (uris);
493 g_list_free (list);
496 static char *
497 cheese_thumb_view_get_url_from_path (CheeseThumbView *thumb_view, GtkTreePath *path)
499 GtkTreeModel *model;
500 GtkTreeIter iter;
501 char *file;
503 model = gtk_icon_view_get_model (GTK_ICON_VIEW (thumb_view));
504 gtk_tree_model_get_iter (model, &iter, path);
506 gtk_tree_model_get (model, &iter, THUMBNAIL_URL_COLUMN, &file, -1);
508 return file;
511 char *
512 cheese_thumb_view_get_selected_image (CheeseThumbView *thumb_view)
514 GList *list;
515 char *filename = NULL;
517 list = gtk_icon_view_get_selected_items (GTK_ICON_VIEW (thumb_view));
518 if (list)
520 filename = cheese_thumb_view_get_url_from_path (thumb_view, (GtkTreePath *) list->data);
521 g_list_foreach (list, (GFunc) gtk_tree_path_free, NULL);
522 g_list_free (list);
525 return filename;
528 GList *
529 cheese_thumb_view_get_selected_images_list (CheeseThumbView *thumb_view)
531 GList *l, *item;
532 GList *list = NULL;
533 GFile *file;
535 GtkTreePath *path;
537 l = gtk_icon_view_get_selected_items (GTK_ICON_VIEW (thumb_view));
539 for (item = l; item != NULL; item = item->next)
541 path = (GtkTreePath *) item->data;
542 file = g_file_new_for_path (cheese_thumb_view_get_url_from_path (thumb_view, path));
543 list = g_list_prepend (list, file);
544 gtk_tree_path_free (path);
547 g_list_free (l);
548 list = g_list_reverse (list);
550 return list;
553 static void
554 cheese_thumb_view_get_n_selected_helper (GtkIconView *thumbview,
555 GtkTreePath *path,
556 gpointer data)
558 /* data is of type (guint *) */
559 (*(guint *) data)++;
562 guint
563 cheese_thumb_view_get_n_selected (CheeseThumbView *thumbview)
565 guint count = 0;
567 gtk_icon_view_selected_foreach (GTK_ICON_VIEW (thumbview),
568 cheese_thumb_view_get_n_selected_helper,
569 (&count));
570 return count;
573 static void
574 cheese_thumb_view_fill (CheeseThumbView *thumb_view)
576 CheeseThumbViewPrivate *priv = cheese_thumb_view_get_instance_private (thumb_view);
578 GDir *dir_videos, *dir_photos;
579 const char *path_videos, *path_photos;
580 const char *name;
581 char *filename;
582 GFile *file;
584 gtk_list_store_clear (priv->store);
586 path_videos = cheese_fileutil_get_video_path (priv->fileutil);
587 path_photos = cheese_fileutil_get_photo_path (priv->fileutil);
589 dir_videos = g_dir_open (path_videos, 0, NULL);
590 dir_photos = g_dir_open (path_photos, 0, NULL);
592 if (!dir_videos && !dir_photos)
593 return;
595 priv->multiplex_thumbnail_generator = FALSE;
596 char *multiplex_file = g_build_filename (path_photos, "cheese, cheese, cheese! all i want is cheese", NULL);
597 if (g_file_test (multiplex_file, G_FILE_TEST_EXISTS))
598 priv->multiplex_thumbnail_generator = !priv->multiplex_thumbnail_generator;
599 g_free (multiplex_file);
601 if (dir_videos)
603 /* read videos from the vid directory */
604 while ((name = g_dir_read_name (dir_videos)))
606 if (!(g_str_has_suffix (name, CHEESE_VIDEO_NAME_SUFFIX))
607 && !(g_str_has_suffix (name, CHEESE_OLD_VIDEO_NAME_SUFFIX)))
608 continue;
610 filename = g_build_filename (path_videos, name, NULL);
611 file = g_file_new_for_path (filename);
612 cheese_thumb_view_append_item (thumb_view, file);
613 g_free (filename);
614 g_object_unref (file);
616 g_dir_close (dir_videos);
617 cheese_thumb_view_start_monitoring_video_path (thumb_view, path_videos);
620 if (dir_photos)
622 /* read photos from the photo directory */
623 while ((name = g_dir_read_name (dir_photos)))
625 if (!(g_str_has_suffix (name, CHEESE_PHOTO_NAME_SUFFIX)))
626 continue;
628 filename = g_build_filename (path_photos, name, NULL);
629 file = g_file_new_for_path (filename);
630 cheese_thumb_view_append_item (thumb_view, file);
631 g_free (filename);
632 g_object_unref (file);
634 g_dir_close (dir_photos);
635 cheese_thumb_view_start_monitoring_photo_path (thumb_view, path_photos);
639 static void
640 cheese_thumb_view_finalize (GObject *object)
642 CheeseThumbView *thumb_view = CHEESE_THUMB_VIEW (object);
643 CheeseThumbViewPrivate *priv = cheese_thumb_view_get_instance_private (thumb_view);
645 g_object_unref (priv->store);
646 g_object_unref (priv->fileutil);
647 g_object_unref (priv->factory);
648 g_file_monitor_cancel (priv->photo_file_monitor);
649 g_file_monitor_cancel (priv->video_file_monitor);
650 g_queue_free (priv->thumbnails);
652 G_OBJECT_CLASS (cheese_thumb_view_parent_class)->finalize (object);
655 static void
656 cheese_thumb_view_class_init (CheeseThumbViewClass *klass)
658 GObjectClass *object_class = G_OBJECT_CLASS (klass);
660 object_class->constructed = cheese_thumb_view_constructed;
661 object_class->finalize = cheese_thumb_view_finalize;
664 static void
665 cheese_thumb_view_row_inserted_cb (GtkTreeModel *tree_model,
666 GtkTreePath *path,
667 GtkTreeIter *iter,
668 CheeseThumbView *thumb_view)
670 CheeseThumbViewPrivate *priv = cheese_thumb_view_get_instance_private (thumb_view);
672 priv->n_items++;
673 if (!priv->vertical)
674 gtk_icon_view_set_columns (GTK_ICON_VIEW (thumb_view), priv->n_items);
675 else
676 gtk_widget_set_size_request (GTK_WIDGET (thumb_view), -1, -1);
679 static void
680 cheese_thumb_view_row_deleted_cb (GtkTreeModel *tree_model,
681 GtkTreePath *path,
682 CheeseThumbView *thumb_view)
684 CheeseThumbViewPrivate *priv = cheese_thumb_view_get_instance_private (thumb_view);
686 priv->n_items--;
687 if (priv->n_items == 0)
688 gtk_widget_set_size_request (GTK_WIDGET (thumb_view),
689 THUMB_VIEW_MINIMUM_WIDTH,
690 THUMB_VIEW_MINIMUM_HEIGHT);
691 else if (!priv->vertical)
692 gtk_icon_view_set_columns (GTK_ICON_VIEW (thumb_view), priv->n_items);
695 static void
696 cheese_thumb_view_init (CheeseThumbView *thumb_view)
698 CheeseThumbViewPrivate *priv = cheese_thumb_view_get_instance_private (thumb_view);
700 priv->video_file_monitor = NULL;
701 priv->photo_file_monitor = NULL;
703 cheese_thumbnail_init ();
705 priv->store = gtk_list_store_new (3, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING);
706 priv->n_items = 0;
707 priv->idle_id = 0;
708 priv->thumbnails = g_queue_new ();
710 priv->fileutil = cheese_fileutil_new ();
711 priv->factory = gnome_desktop_thumbnail_factory_new (GNOME_DESKTOP_THUMBNAIL_SIZE_NORMAL);
714 g_signal_connect (G_OBJECT (priv->store),
715 "row-inserted",
716 G_CALLBACK (cheese_thumb_view_row_inserted_cb),
717 thumb_view);
718 g_signal_connect (G_OBJECT (priv->store),
719 "row-deleted",
720 G_CALLBACK (cheese_thumb_view_row_deleted_cb),
721 thumb_view);
723 g_signal_connect (G_OBJECT (thumb_view), "drag-data-get",
724 G_CALLBACK (cheese_thumb_view_on_drag_data_get_cb), NULL);
726 /* We do the rest of the initialization in our constructed() implementation,
727 * because GtkIconView may not be ready for us to do more now.
728 * See https://bugzilla.gnome.org/show_bug.cgi?id=643286#c6
732 static void
733 cheese_thumb_view_constructed (GObject *object)
735 CheeseThumbView *thumb_view = CHEESE_THUMB_VIEW (object);
736 CheeseThumbViewPrivate *priv = cheese_thumb_view_get_instance_private (thumb_view);
738 G_OBJECT_CLASS (cheese_thumb_view_parent_class)->constructed (object);
740 gtk_icon_view_set_model (GTK_ICON_VIEW (thumb_view), GTK_TREE_MODEL (priv->store));
742 gtk_widget_set_size_request (GTK_WIDGET (thumb_view),
743 THUMB_VIEW_MINIMUM_WIDTH,
744 THUMB_VIEW_MINIMUM_HEIGHT);
746 gtk_icon_view_set_margin (GTK_ICON_VIEW (thumb_view), 0);
747 gtk_icon_view_set_row_spacing (GTK_ICON_VIEW (thumb_view), 0);
748 gtk_icon_view_set_column_spacing (GTK_ICON_VIEW (thumb_view), 0);
750 gtk_icon_view_set_pixbuf_column (GTK_ICON_VIEW (thumb_view), 0);
752 gtk_icon_view_set_columns (GTK_ICON_VIEW (thumb_view), -1);
754 gtk_icon_view_enable_model_drag_source (GTK_ICON_VIEW (thumb_view), GDK_BUTTON1_MASK,
755 target_table, G_N_ELEMENTS (target_table),
756 GDK_ACTION_COPY);
757 gtk_icon_view_set_selection_mode (GTK_ICON_VIEW (thumb_view), GTK_SELECTION_MULTIPLE);
759 gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (priv->store),
760 THUMBNAIL_BASENAME_URL_COLUMN, GTK_SORT_ASCENDING);
762 cheese_thumb_view_fill (thumb_view);
763 cheese_thumb_view_set_vertical (thumb_view, FALSE);
766 GtkWidget *
767 cheese_thumb_view_new ()
769 CheeseThumbView *thumb_view;
771 thumb_view = g_object_new (CHEESE_TYPE_THUMB_VIEW, NULL);
772 return GTK_WIDGET (thumb_view);
775 void
776 cheese_thumb_view_set_vertical (CheeseThumbView *thumb_view, gboolean vertical)
778 CheeseThumbViewPrivate *priv = cheese_thumb_view_get_instance_private (thumb_view);
780 priv->vertical = vertical;
781 if (!priv->vertical && priv->n_items)
782 gtk_icon_view_set_columns(GTK_ICON_VIEW (thumb_view), priv->n_items);
783 else
784 gtk_icon_view_set_columns(GTK_ICON_VIEW (thumb_view), 1);
786 gtk_widget_set_hexpand (GTK_WIDGET (thumb_view), !vertical);
787 gtk_widget_set_vexpand (GTK_WIDGET (thumb_view), vertical);
790 void
791 cheese_thumb_view_start_monitoring_photo_path (CheeseThumbView *thumb_view, const char *path_photos)
793 CheeseThumbViewPrivate *priv = cheese_thumb_view_get_instance_private (thumb_view);
795 if (priv->photo_file_monitor != NULL)
796 return;
798 GFile *file;
800 /* connect signal to photo path */
801 file = g_file_new_for_path (path_photos);
802 priv->photo_file_monitor = g_file_monitor_directory (file, G_FILE_MONITOR_SEND_MOVED, NULL, NULL);
803 g_signal_connect (priv->photo_file_monitor, "changed", G_CALLBACK (cheese_thumb_view_monitor_cb), thumb_view);
805 g_object_unref (file);
809 void
810 cheese_thumb_view_start_monitoring_video_path (CheeseThumbView *thumb_view, const char *path_videos)
812 CheeseThumbViewPrivate *priv = cheese_thumb_view_get_instance_private (thumb_view);
814 if (priv->video_file_monitor != NULL)
815 return;
817 GFile *file;
819 /* connect signal to video path */
820 file = g_file_new_for_path (path_videos);
821 priv->video_file_monitor = g_file_monitor_directory (file, G_FILE_MONITOR_SEND_MOVED, NULL, NULL);
822 g_signal_connect (priv->video_file_monitor, "changed", G_CALLBACK (cheese_thumb_view_monitor_cb), thumb_view);
824 g_object_unref (file);