aboutsummaryrefslogtreecommitdiffstats
path: root/widgets
diff options
context:
space:
mode:
Diffstat (limited to 'widgets')
-rw-r--r--widgets/misc/Makefile.am2
-rw-r--r--widgets/misc/e-picture-gallery.c419
-rw-r--r--widgets/misc/e-picture-gallery.h67
3 files changed, 488 insertions, 0 deletions
diff --git a/widgets/misc/Makefile.am b/widgets/misc/Makefile.am
index 4375c0641e..7e9ce9ca2b 100644
--- a/widgets/misc/Makefile.am
+++ b/widgets/misc/Makefile.am
@@ -44,6 +44,7 @@ widgetsinclude_HEADERS = \
e-menu-tool-button.h \
e-online-button.h \
e-paned.h \
+ e-picture-gallery.h \
e-popup-action.h \
e-popup-menu.h \
e-preferences-window.h \
@@ -122,6 +123,7 @@ libemiscwidgets_la_SOURCES = \
e-menu-tool-button.c \
e-online-button.c \
e-paned.c \
+ e-picture-gallery.c \
e-popup-action.c \
e-popup-menu.c \
e-preferences-window.c \
diff --git a/widgets/misc/e-picture-gallery.c b/widgets/misc/e-picture-gallery.c
new file mode 100644
index 0000000000..163a160ff8
--- /dev/null
+++ b/widgets/misc/e-picture-gallery.c
@@ -0,0 +1,419 @@
+/*
+ * e-picture-gallery.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#include "e-util/e-icon-factory.h"
+
+#include "e-picture-gallery.h"
+
+#define E_PICTURE_GALLERY_GET_PRIVATE(obj) \
+ (G_TYPE_INSTANCE_GET_PRIVATE \
+ ((obj), E_TYPE_PICTURE_GALLERY, EPictureGalleryPrivate))
+
+struct _EPictureGalleryPrivate {
+ gboolean initialized;
+ gchar *path;
+ GFileMonitor *monitor;
+};
+
+enum {
+ PROP_0,
+ PROP_PATH
+};
+
+enum {
+ COL_PIXBUF = 0,
+ COL_URI,
+ COL_FILENAME_TEXT
+};
+
+G_DEFINE_TYPE (EPictureGallery, e_picture_gallery, GTK_TYPE_ICON_VIEW)
+
+static gboolean
+update_file_iter (GtkListStore *list_store, GtkTreeIter *iter, GFile *file, gboolean force_thumbnail_update)
+{
+ GFileInfo *file_info;
+ gchar *uri;
+ gboolean res = FALSE;
+
+ g_return_val_if_fail (list_store != NULL, FALSE);
+ g_return_val_if_fail (iter != NULL, FALSE);
+ g_return_val_if_fail (file != NULL, FALSE);
+
+ uri = g_file_get_uri (file);
+
+ file_info = g_file_query_info (file,
+ G_FILE_ATTRIBUTE_THUMBNAIL_PATH ","
+ G_FILE_ATTRIBUTE_THUMBNAILING_FAILED ","
+ G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME ","
+ G_FILE_ATTRIBUTE_STANDARD_SIZE,
+ G_FILE_QUERY_INFO_NONE,
+ NULL,
+ NULL);
+
+ if (file_info != NULL) {
+ const gchar *existing_thumb = g_file_info_get_attribute_byte_string (file_info, G_FILE_ATTRIBUTE_THUMBNAIL_PATH);
+ gchar *new_thumb = NULL;
+
+ if (!existing_thumb || force_thumbnail_update) {
+ gchar *filename;
+
+ filename = g_file_get_path (file);
+ if (filename) {
+ new_thumb = e_icon_factory_create_thumbnail (filename);
+ if (new_thumb)
+ existing_thumb = new_thumb;
+ g_free (filename);
+ }
+ }
+
+ if (existing_thumb && !g_file_info_get_attribute_boolean (file_info, G_FILE_ATTRIBUTE_THUMBNAILING_FAILED)) {
+ GdkPixbuf* pixbuf;
+
+ pixbuf = gdk_pixbuf_new_from_file (existing_thumb, NULL);
+
+ if (pixbuf) {
+ const gchar *filename;
+ gchar *filename_text = NULL;
+ guint64 filesize;
+
+ filename = g_file_info_get_attribute_string (file_info, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME);
+ if (filename) {
+ filesize = g_file_info_get_attribute_uint64 (file_info, G_FILE_ATTRIBUTE_STANDARD_SIZE);
+ if (filesize) {
+ gchar *tmp = g_format_size_for_display ((goffset) filesize);
+ filename_text = g_strdup_printf ("%s (%s)", filename, tmp);
+ g_free (tmp);
+ }
+
+ res = TRUE;
+ gtk_list_store_set (list_store, iter,
+ COL_PIXBUF, pixbuf,
+ COL_URI, uri,
+ COL_FILENAME_TEXT, filename_text ? filename_text : filename,
+ -1);
+ }
+
+ g_object_unref (pixbuf);
+ g_free (filename_text);
+ }
+ }
+
+ g_free (new_thumb);
+ }
+
+ g_free (uri);
+
+ return res;
+}
+
+static void
+add_file (GtkListStore *list_store, GFile *file)
+{
+ GtkTreeIter iter;
+
+ g_return_if_fail (list_store != NULL);
+ g_return_if_fail (file != NULL);
+
+ gtk_list_store_append (list_store, &iter);
+ if (!update_file_iter (list_store, &iter, file, FALSE))
+ gtk_list_store_remove (list_store, &iter);
+}
+
+static gboolean
+find_file_uri (GtkListStore *list_store, const gchar *uri, GtkTreeIter *iter)
+{
+ GtkTreeModel *model;
+
+ g_return_val_if_fail (list_store != NULL, FALSE);
+ g_return_val_if_fail (uri != NULL, FALSE);
+ g_return_val_if_fail (iter != NULL, FALSE);
+
+ model = GTK_TREE_MODEL (list_store);
+ g_return_val_if_fail (model != NULL, FALSE);
+
+ if (!gtk_tree_model_get_iter_first (model, iter))
+ return FALSE;
+
+ do {
+ gchar *iter_uri = NULL;
+
+ gtk_tree_model_get (model, iter,
+ COL_URI, &iter_uri,
+ -1);
+
+ if (iter_uri && g_ascii_strcasecmp (uri, iter_uri) == 0) {
+ g_free (iter_uri);
+ return TRUE;
+ }
+
+ g_free (iter_uri);
+ } while (gtk_tree_model_iter_next (model, iter));
+
+ return FALSE;
+}
+
+static void
+picture_gallery_dir_changed_cb (GFileMonitor *monitor, GFile *file, GFile *other_file, GFileMonitorEvent event_type, EPictureGallery *gallery)
+{
+ gchar *uri;
+ GtkListStore *list_store;
+ GtkTreeIter iter;
+
+ g_return_if_fail (gallery != NULL);
+ g_return_if_fail (gallery->priv != NULL);
+ g_return_if_fail (file != NULL);
+
+ list_store = GTK_LIST_STORE (gtk_icon_view_get_model (GTK_ICON_VIEW (gallery)));
+ g_return_if_fail (list_store != NULL);
+
+ uri = g_file_get_uri (file);
+ if (!uri)
+ return;
+
+ switch (event_type) {
+ case G_FILE_MONITOR_EVENT_CREATED:
+ if (find_file_uri (list_store, uri, &iter)) {
+ if (!update_file_iter (list_store, &iter, file, TRUE))
+ gtk_list_store_remove (list_store, &iter);
+ } else {
+ add_file (list_store, file);
+ }
+ break;
+ case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT:
+ if (find_file_uri (list_store, uri, &iter)) {
+ if (!update_file_iter (list_store, &iter, file, TRUE))
+ gtk_list_store_remove (list_store, &iter);
+ }
+ break;
+ case G_FILE_MONITOR_EVENT_DELETED:
+ if (find_file_uri (list_store, uri, &iter))
+ gtk_list_store_remove (list_store, &iter);
+ break;
+ default:
+ break;
+ }
+
+ g_free (uri);
+}
+
+static gboolean
+picture_gallery_start_loading_cb (EPictureGallery *gallery)
+{
+ GtkIconView *icon_view;
+ GtkListStore *list_store;
+ GDir *dir;
+ const gchar *dirname;
+
+ icon_view = GTK_ICON_VIEW (gallery);
+ list_store = GTK_LIST_STORE (gtk_icon_view_get_model (icon_view));
+ g_return_val_if_fail (list_store != NULL, FALSE);
+
+ dirname = e_picture_gallery_get_path (gallery);
+ if (!dirname)
+ return FALSE;
+
+ dir = g_dir_open (dirname, 0, NULL);
+ if (dir) {
+ GFile *file;
+ const gchar *basename;
+
+ while ((basename = g_dir_read_name (dir)) != NULL) {
+ gchar *filename;
+
+ filename = g_build_filename (dirname, basename, NULL);
+ file = g_file_new_for_path (filename);
+
+ add_file (list_store, file);
+
+ g_free (filename);
+ g_object_unref (file);
+ }
+
+ g_dir_close (dir);
+
+ file = g_file_new_for_path (dirname);
+ gallery->priv->monitor = g_file_monitor_directory (file, G_FILE_MONITOR_NONE, NULL, NULL);
+ g_object_unref (file);
+
+ if (gallery->priv->monitor)
+ g_signal_connect (gallery->priv->monitor, "changed", G_CALLBACK (picture_gallery_dir_changed_cb), gallery);
+ }
+
+ g_object_unref (icon_view);
+
+ return FALSE;
+}
+
+const gchar *
+e_picture_gallery_get_path (EPictureGallery *gallery)
+{
+ g_return_val_if_fail (gallery != NULL, NULL);
+ g_return_val_if_fail (E_IS_PICTURE_GALLERY (gallery), NULL);
+ g_return_val_if_fail (gallery->priv != NULL, NULL);
+
+ return gallery->priv->path;
+}
+
+static void
+picture_gallery_set_path (EPictureGallery *gallery, const gchar *path)
+{
+ g_return_if_fail (gallery != NULL);
+ g_return_if_fail (E_IS_PICTURE_GALLERY (gallery));
+ g_return_if_fail (gallery->priv != NULL);
+
+ g_free (gallery->priv->path);
+
+ if (!path || !*path || !g_file_test (path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))
+ gallery->priv->path = g_strdup (g_get_user_special_dir (G_USER_DIRECTORY_PICTURES));
+ else
+ gallery->priv->path = g_strdup (path);
+}
+
+static void
+picture_gallery_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_PATH:
+ g_value_set_string (value, e_picture_gallery_get_path (E_PICTURE_GALLERY (object)));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+picture_gallery_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
+{
+ switch (property_id) {
+ case PROP_PATH:
+ picture_gallery_set_path (E_PICTURE_GALLERY (object), g_value_get_string (value));
+ return;
+ }
+
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+}
+
+static void
+visible_cb (EPictureGallery *gallery)
+{
+ g_return_if_fail (gallery != NULL);
+ g_return_if_fail (gallery->priv != NULL);
+
+ if (!gallery->priv->initialized && gtk_widget_get_visible (GTK_WIDGET (gallery))) {
+ gallery->priv->initialized = TRUE;
+
+ g_idle_add ((GSourceFunc) picture_gallery_start_loading_cb, gallery);
+ }
+}
+
+static void
+picture_gallery_constructed (GObject *object)
+{
+ if (G_OBJECT_CLASS (e_picture_gallery_parent_class)->constructed)
+ G_OBJECT_CLASS (e_picture_gallery_parent_class)->constructed (object);
+
+ g_signal_connect (object, "notify::visible", G_CALLBACK (visible_cb), NULL);
+}
+
+static void
+picture_gallery_dispose (GObject *object)
+{
+ EPictureGallery *gallery;
+
+ gallery = E_PICTURE_GALLERY (object);
+
+ g_return_if_fail (gallery != NULL);
+ g_return_if_fail (gallery->priv != NULL);
+
+ if (gallery->priv->monitor) {
+ g_object_unref (gallery->priv->monitor);
+ gallery->priv->monitor = NULL;
+ }
+
+ if (G_OBJECT_CLASS (e_picture_gallery_parent_class)->dispose)
+ G_OBJECT_CLASS (e_picture_gallery_parent_class)->dispose (object);
+}
+
+static void
+e_picture_gallery_class_init (EPictureGalleryClass *class)
+{
+ GObjectClass *object_class;
+
+ g_type_class_add_private (class, sizeof (EPictureGalleryPrivate));
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->get_property = picture_gallery_get_property;
+ object_class->set_property = picture_gallery_set_property;
+ object_class->constructed = picture_gallery_constructed;
+ object_class->dispose = picture_gallery_dispose;
+
+ g_object_class_install_property (
+ object_class,
+ PROP_PATH,
+ g_param_spec_string (
+ "path",
+ "Gallery path",
+ NULL,
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+}
+
+static void
+e_picture_gallery_init (EPictureGallery *gallery)
+{
+ GtkIconView *icon_view;
+ GtkListStore *list_store;
+ GtkTargetEntry *targets;
+ GtkTargetList *list;
+ gint n_targets;
+
+ gallery->priv = E_PICTURE_GALLERY_GET_PRIVATE (gallery);
+ gallery->priv->initialized = FALSE;
+ gallery->priv->monitor = NULL;
+ picture_gallery_set_path (gallery, NULL);
+
+ icon_view = GTK_ICON_VIEW (gallery);
+
+ list_store = gtk_list_store_new (3, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING);
+ gtk_icon_view_set_model (icon_view, GTK_TREE_MODEL (list_store));
+ g_object_unref (list_store);
+
+ gtk_icon_view_set_pixbuf_column (icon_view, COL_PIXBUF);
+ gtk_icon_view_set_text_column (icon_view, COL_FILENAME_TEXT);
+ gtk_icon_view_set_tooltip_column (icon_view, -1);
+
+ list = gtk_target_list_new (NULL, 0);
+ gtk_target_list_add_uri_targets (list, 0);
+ targets = gtk_target_table_new_from_list (list, &n_targets);
+
+ gtk_icon_view_enable_model_drag_source (
+ icon_view, GDK_BUTTON1_MASK,
+ targets, n_targets, GDK_ACTION_COPY);
+
+ gtk_target_table_free (targets, n_targets);
+ gtk_target_list_unref (list);
+}
+
+GtkWidget *
+e_picture_gallery_new (const gchar *path)
+{
+ return g_object_new (E_TYPE_PICTURE_GALLERY, "path", path, NULL);
+}
diff --git a/widgets/misc/e-picture-gallery.h b/widgets/misc/e-picture-gallery.h
new file mode 100644
index 0000000000..6da23294c4
--- /dev/null
+++ b/widgets/misc/e-picture-gallery.h
@@ -0,0 +1,67 @@
+/*
+ * e-picture-gallery.h
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with the program; if not, see <http://www.gnu.org/licenses/>
+ *
+ *
+ * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
+ *
+ */
+
+#ifndef E_PICTURE_GALLERY_H
+#define E_PICTURE_GALLERY_H
+
+#include <gtk/gtk.h>
+
+/* Standard GObject macros */
+#define E_TYPE_PICTURE_GALLERY \
+ (e_picture_gallery_get_type ())
+#define E_PICTURE_GALLERY(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST \
+ ((obj), E_TYPE_PICTURE_GALLERY, EPictureGallery))
+#define E_PICTURE_GALLERY_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_CAST \
+ ((cls), E_TYPE_PICTURE_GALLERY, EPictureGalleryClass))
+#define E_IS_PICTURE_GALLERY(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE \
+ ((obj), E_TYPE_PICTURE_GALLERY))
+#define E_IS_PICTURE_GALLERY_CLASS(cls) \
+ (G_TYPE_CHECK_CLASS_TYPE \
+ ((cls), E_TYPE_PICTURE_GALLERY))
+#define E_PICTURE_GALLERY_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS \
+ ((obj), E_TYPE_PICTURE_GALLERY, EPictureGalleryClass))
+
+G_BEGIN_DECLS
+
+typedef struct _EPictureGallery EPictureGallery;
+typedef struct _EPictureGalleryClass EPictureGalleryClass;
+typedef struct _EPictureGalleryPrivate EPictureGalleryPrivate;
+
+struct _EPictureGallery {
+ GtkIconView parent;
+ EPictureGalleryPrivate *priv;
+};
+
+struct _EPictureGalleryClass {
+ GtkIconViewClass parent_class;
+};
+
+GType e_picture_gallery_get_type (void);
+GtkWidget * e_picture_gallery_new (const gchar *path);
+const gchar * e_picture_gallery_get_path (EPictureGallery *gallery);
+
+G_END_DECLS
+
+#endif /* E_PICTURE_GALLERY_H */