Commit 5917666a authored by Ernestas Kulik's avatar Ernestas Kulik 🦑

Add thumbnail task

Things to consider:
    scaling/sizing,
    NautilusIconInfo?
parent 4637f974
Pipeline #1907 failed with stage
in 28 seconds
......@@ -2,11 +2,13 @@
#include <stdlib.h>
#include <glib.h>
#include <gtk/gtk.h>
#include "nautilus-directory.h"
#include "nautilus-file.h"
#include "nautilus-task-manager.h"
#include "tasks/nautilus-rename-task.h"
#include "tasks/nautilus-thumbnail-task.h"
static void
got_info (NautilusFile *file,
......@@ -145,6 +147,60 @@ _rename (const gchar *target,
g_main_loop_run (loop);
}
static void
on_thumbnail_finished (NautilusThumbnailTask *task,
GFile *location,
GdkPixbuf *thumbnail,
gpointer user_data)
{
GtkWidget *image;
image = gtk_image_new_from_pixbuf (thumbnail);
gtk_widget_set_halign (image, GTK_ALIGN_CENTER);
gtk_widget_set_valign (image, GTK_ALIGN_CENTER);
gtk_widget_set_visible (image, TRUE);
gtk_container_add (GTK_CONTAINER (user_data), image);
g_object_unref (thumbnail);
}
static gboolean
on_window_deleted (GtkWidget *widget,
GdkEvent *event,
gpointer user_data)
{
gtk_main_quit ();
return GDK_EVENT_PROPAGATE;
}
static void
display_thumbnail (const gchar *path)
{
GtkWidget *window;
g_autoptr (GFile) location = NULL;
g_autoptr (NautilusTask) task = NULL;
g_autoptr (NautilusTaskManager) task_manager = NULL;
gtk_init (NULL, NULL);
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
location = g_file_new_for_path (path);
task = nautilus_thumbnail_task_new (location, TRUE);
task_manager = nautilus_task_manager_dup_singleton ();
gtk_widget_show_all (window);
g_signal_connect_after (window, "delete-event", on_window_deleted, NULL);
g_signal_connect (task, "finished", on_thumbnail_finished, window);
nautilus_task_manager_queue_task (task_manager, task);
gtk_main ();
}
int
main (int argc,
char **argv)
......@@ -153,6 +209,7 @@ main (int argc,
gchar **files = NULL;
gboolean check = FALSE;
gchar *new_name = NULL;
gboolean thumbnail = FALSE;
const GOptionEntry option_entries[] =
{
{
......@@ -167,6 +224,10 @@ main (int argc,
"rename", 'n', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, &new_name,
"Rename FILE to NAME", "NAME"
},
{
"thumbnail", 't', G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, &thumbnail,
"Display thumbnail for FILE", NULL
},
{ NULL }
};
GError *error = NULL;
......@@ -204,5 +265,10 @@ main (int argc,
_rename (files[0], new_name);
}
if (thumbnail)
{
display_thumbnail (files[0]);
}
return EXIT_SUCCESS;
}
nautilus_ng_sources = ['nautilus-task.c',
resources = gnome.compile_resources ('nautilus-ng-resources',
join_paths ('res', 'org.gnome.Nautilus.gresource.xml'),
source_dir: 'res')
nautilus_ng_sources = [resources,
'nautilus-task.c',
'nautilus-task.h',
'nautilus-task-private.h',
'nautilus-task-manager.c',
......@@ -21,9 +26,11 @@ nautilus_ng_sources = ['nautilus-task.c',
'nautilus-signal-utilities.h',
'nautilus-file-table.c',
'nautilus-file-table.h',
'tasks/nautilus-thumbnail-task.c',
'tasks/nautilus-thumbnail-task.h',
'main.c']
nautilus_ng_dependencies = [gio, glib]
nautilus_ng_dependencies = [gio, glib, gnome_desktop, gtk]
nautilus_marshallers = gnome.genmarshal ('nautilus-marshallers',
sources: 'nautilus-marshallers.list',
......
......@@ -23,6 +23,7 @@
#include "nautilus-file-table.h"
#include "nautilus-task-manager.h"
#include "tasks/nautilus-attribute-task.h"
#include "tasks/nautilus-thumbnail-task.h"
enum
{
......@@ -305,6 +306,34 @@ nautilus_file_query_info (NautilusFile *file,
nautilus_task_manager_queue_task (manager, task);
}
typedef struct
{
NautilusFile *file;
NautilusFileInfoCallback callback;
gpointer callback_data;
} GetThumbnailDetails;
void
nautilus_file_get_thumbnail (NautilusFile *file,
NautilusThumbnailCallback callback,
gpointer user_data)
{
g_autoptr (GFile) location = NULL;
g_autoptr (NautilusTask) task = NULL;
GetThumbnailDetails *details;
g_autoptr (NautilusTaskManager) manager = NULL;
g_return_if_fail (NAUTILUS_IS_FILE (file));
location = nautilus_file_get_location (file);
task = nautilus_thumbnail_task_new (location, TRUE);
details = g_new0 (GetThumbnailDetails, 1);
manager = nautilus_task_manager_dup_singleton ();
nautilus_task_manager_queue_task (manager, task);
}
NautilusFile *
nautilus_file_get_existing (GFile *location)
{
......
......@@ -21,6 +21,7 @@
#include <glib-object.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <gio/gio.h>
#define NAUTILUS_TYPE_FILE (nautilus_file_get_type ())
......@@ -31,6 +32,9 @@ typedef void (*NautilusFileInfoCallback) (NautilusFile *file,
GFileInfo *info,
GError *error,
gpointer user_data);
typedef void (*NautilusThumbnailCallback) (NautilusFile *file,
GdkPixbuf *pixbuf,
gpointer user_data);
typedef enum
{
......@@ -46,10 +50,13 @@ struct _NautilusFileClass
GFile *new_location);
};
void nautilus_file_query_info (NautilusFile *file,
GCancellable *cancellable,
NautilusFileInfoCallback callback,
gpointer user_data);
void nautilus_file_query_info (NautilusFile *file,
GCancellable *cancellable,
NautilusFileInfoCallback callback,
gpointer user_data);
void nautilus_file_get_thumbnail (NautilusFile *file,
NautilusThumbnailCallback callback,
gpointer user_data);
NautilusFile *nautilus_file_get_existing (GFile *location);
GFile *nautilus_file_get_location (NautilusFile *file);
......
VOID:OBJECT,OBJECT,BOXED
VOID:OBJECT,BOXED,BOXED
VOID:OBJECT,OBJECT
<?xml version='1.0' encoding='UTF-8'?>
<gresources>
<gresource prefix='/org/gnome/Nautilus'>
<file>text-x-preview.png</file>
</gresource>
</gresources>
/* 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);
}
/* 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/>.
*/
#ifndef NAUTILUS_THUMBNAIL_TASK_H_INCLUDED
#define NAUTILUS_THUMBNAIL_TASK_H_INCLUDED
#include "nautilus-task.h"
#include <gio/gio.h>
#define NAUTILUS_TYPE_THUMBNAIL_TASK (nautilus_thumbnail_task_get_type ())
G_DECLARE_FINAL_TYPE (NautilusThumbnailTask, nautilus_thumbnail_task,
NAUTILUS, THUMBNAIL_TASK, NautilusTask)
NautilusTask *nautilus_thumbnail_task_new (GFile *location,
gboolean use_external_thumbnailer);
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment