summaryrefslogtreecommitdiff
path: root/src-ng/tasks/nautilus-thumbnail-task.c
diff options
context:
space:
mode:
Diffstat (limited to 'src-ng/tasks/nautilus-thumbnail-task.c')
-rw-r--r--src-ng/tasks/nautilus-thumbnail-task.c287
1 files changed, 287 insertions, 0 deletions
diff --git a/src-ng/tasks/nautilus-thumbnail-task.c b/src-ng/tasks/nautilus-thumbnail-task.c
new file mode 100644
index 000000000..a5aaa613b
--- /dev/null
+++ b/src-ng/tasks/nautilus-thumbnail-task.c
@@ -0,0 +1,287 @@
+/* Copyright (C) 2017 Ernestas Kulik <ernestask@gnome.org>
+ *
+ * This file is part of Nautilus.
+ *
+ * Nautilus is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Nautilus 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Nautilus. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include "nautilus-thumbnail-task.h"
+
+#include "nautilus-marshallers.h"
+#include "nautilus-task-private.h"
+
+#include <gdk-pixbuf/gdk-pixbuf.h>
+
+#ifndef GNOME_DESKTOP_USE_UNSTABLE_API
+#define GNOME_DESKTOP_USE_UNSTABLE_API
+#endif
+
+#include <libgnome-desktop/gnome-desktop-thumbnail.h>
+
+struct _NautilusThumbnailTask
+{
+ NautilusTask parent_instance;
+
+ GFile *location;
+ gboolean use_external_thumbnailer;
+};
+
+G_DEFINE_TYPE (NautilusThumbnailTask, nautilus_thumbnail_task, NAUTILUS_TYPE_TASK)
+
+enum
+{
+ FINISHED,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+static void
+finalize (GObject *object)
+{
+ NautilusThumbnailTask *self;
+
+ self = NAUTILUS_THUMBNAIL_TASK (object);
+
+ g_object_unref (self->location);
+
+ G_OBJECT_CLASS (nautilus_thumbnail_task_parent_class)->finalize (object);
+}
+
+static gpointer
+create_thumbnail_factory (gpointer data)
+{
+ (void) data;
+
+ return gnome_desktop_thumbnail_factory_new (GNOME_DESKTOP_THUMBNAIL_SIZE_LARGE);
+}
+
+static GnomeDesktopThumbnailFactory *
+get_thumbnail_factory (void)
+{
+ static GOnce once = G_ONCE_INIT;
+
+ g_once (&once, create_thumbnail_factory, NULL);
+
+ return once.retval;
+}
+
+static GdkPixbuf *
+thumbnail_gnome_desktop (GFile *location)
+{
+ GnomeDesktopThumbnailFactory *thumbnail_factory;
+ g_autofree gchar *uri = NULL;
+ g_autoptr (GFileInfo) file_info = NULL;
+ const gchar *content_type;
+ guint64 mtime;
+ GdkPixbuf *pixbuf;
+
+ thumbnail_factory = get_thumbnail_factory ();
+ uri = g_file_get_uri (location);
+ file_info = g_file_query_info (location,
+ G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE ","
+ G_FILE_ATTRIBUTE_TIME_MODIFIED,
+ G_FILE_QUERY_INFO_NONE,
+ NULL, NULL);
+ content_type = g_file_info_get_content_type (file_info);
+ mtime = g_file_info_get_attribute_uint64 (file_info,
+ G_FILE_ATTRIBUTE_TIME_MODIFIED);
+
+ if (!gnome_desktop_thumbnail_factory_can_thumbnail (thumbnail_factory,
+ uri, content_type,
+ mtime))
+ {
+ return NULL;
+ }
+
+ pixbuf = gnome_desktop_thumbnail_factory_generate_thumbnail (thumbnail_factory,
+ uri,
+ content_type);
+
+ if (pixbuf != NULL)
+ {
+ gnome_desktop_thumbnail_factory_save_thumbnail (thumbnail_factory,
+ pixbuf, uri, mtime);
+ }
+ else
+ {
+ gnome_desktop_thumbnail_factory_create_failed_thumbnail (thumbnail_factory,
+ uri, mtime);
+ }
+
+ return pixbuf;
+}
+
+static GdkPixbuf *
+thumbnail_from_cache (GFile *location)
+{
+ g_autoptr (GFileInfo) file_info = NULL;
+ gboolean thumbnail_is_valid;
+ const char *thumbnail_path;
+
+ file_info = g_file_query_info (location,
+ G_FILE_ATTRIBUTE_THUMBNAIL_PATH ","
+ G_FILE_ATTRIBUTE_THUMBNAIL_IS_VALID,
+ G_FILE_QUERY_INFO_NONE,
+ NULL, NULL);
+
+ thumbnail_is_valid = g_file_info_get_attribute_boolean (file_info,
+ G_FILE_ATTRIBUTE_THUMBNAIL_IS_VALID);
+
+ if (!thumbnail_is_valid)
+ {
+ return NULL;
+ }
+
+ thumbnail_path = g_file_info_get_attribute_byte_string (file_info,
+ G_FILE_ATTRIBUTE_THUMBNAIL_PATH);
+
+ return gdk_pixbuf_new_from_file (thumbnail_path, NULL);
+}
+
+static gpointer
+create_gdk_pixbuf_mime_types_table (gpointer data)
+{
+ GHashTable *hash_table;
+ g_autoptr (GSList) gdk_pixbuf_formats = NULL;
+
+ (void) data;
+
+ hash_table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+ gdk_pixbuf_formats = gdk_pixbuf_get_formats ();
+
+ for (GSList *i = gdk_pixbuf_formats; i != NULL; i = i->next)
+ {
+ g_autofree GStrv mime_types = NULL;
+
+ mime_types = gdk_pixbuf_format_get_mime_types (i->data);
+
+ for (gsize j = 0; mime_types[j] != NULL; j++)
+ {
+ g_hash_table_insert (hash_table,
+ mime_types[j], GUINT_TO_POINTER (1));
+ }
+ }
+
+ return hash_table;
+}
+
+static GHashTable *
+get_gdk_pixbuf_mime_types (void)
+{
+ static GOnce once = G_ONCE_INIT;
+
+ g_once (&once, create_gdk_pixbuf_mime_types_table, NULL);
+
+ return once.retval;
+}
+
+static GdkPixbuf *
+thumbnail_gdk_pixbuf (GFile *location)
+{
+ GHashTable *gdk_pixbuf_mime_types;
+ g_autoptr (GFileInfo) file_info = NULL;
+ const gchar *content_type;
+
+ gdk_pixbuf_mime_types = get_gdk_pixbuf_mime_types ();
+ file_info = g_file_query_info (location,
+ G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE ","
+ G_FILE_ATTRIBUTE_TIME_MODIFIED,
+ G_FILE_QUERY_INFO_NONE,
+ NULL, NULL);
+ content_type = g_file_info_get_content_type (file_info);
+
+ if (g_hash_table_lookup (gdk_pixbuf_mime_types, content_type) == NULL)
+ {
+ return NULL;
+ }
+
+ return NULL;
+}
+
+static void
+execute (NautilusTask *task)
+{
+ NautilusThumbnailTask *self;
+ g_autoptr (GdkPixbuf) pixbuf = NULL;
+
+ self = NAUTILUS_THUMBNAIL_TASK (task);
+
+ if (self->use_external_thumbnailer)
+ {
+ pixbuf = thumbnail_from_cache (self->location);
+
+ if (pixbuf == NULL)
+ {
+ pixbuf = thumbnail_gnome_desktop (self->location);
+ }
+ }
+ else
+ {
+ pixbuf = thumbnail_gdk_pixbuf (self->location);
+ }
+
+ if (pixbuf == NULL)
+ {
+ pixbuf = gdk_pixbuf_new_from_resource ("/org/gnome/Nautilus/text-x-preview.png",
+ NULL);
+ }
+
+ nautilus_task_emit_signal_in_main_context (task, signals[FINISHED], 0,
+ self->location, pixbuf);
+}
+
+static void
+nautilus_thumbnail_task_class_init (NautilusThumbnailTaskClass *klass)
+{
+ GObjectClass *object_class;
+ NautilusTaskClass *task_class;
+
+ object_class = G_OBJECT_CLASS (klass);
+ task_class = NAUTILUS_TASK_CLASS (klass);
+
+ object_class->finalize = finalize;
+
+ task_class->execute = execute;
+
+ signals[FINISHED] = g_signal_new ("finished",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL,
+ nautilus_cclosure_marshal_VOID__OBJECT_OBJECT,
+ G_TYPE_NONE,
+ 2,
+ G_TYPE_FILE, GDK_TYPE_PIXBUF);
+}
+
+static void
+nautilus_thumbnail_task_init (NautilusThumbnailTask *self)
+{
+}
+
+NautilusTask *
+nautilus_thumbnail_task_new (GFile *location,
+ gboolean use_external_thumbnailer)
+{
+ NautilusThumbnailTask *instance;
+
+ g_return_val_if_fail (G_IS_FILE (location), NULL);
+
+ instance = g_object_new (NAUTILUS_TYPE_THUMBNAIL_TASK, NULL);
+
+ instance->location = g_object_ref (location);
+ instance->use_external_thumbnailer = use_external_thumbnailer;
+
+ return NAUTILUS_TASK (instance);
+}