From da669e43a15442a6ee641aa5b8197837856a168b Mon Sep 17 00:00:00 2001 From: Ernestas Kulik Date: Tue, 15 Aug 2017 21:38:44 +0300 Subject: Iris-ify tasks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For ∞x more flexibility. --- meson.build | 2 +- src-ng/main.c | 274 -------------------- src-ng/meson.build | 54 ++-- src-ng/nautilus-context-scheduler.c | 166 ++++++++++++ src-ng/nautilus-context-scheduler.h | 37 +++ src-ng/nautilus-directory.c | 49 +--- src-ng/nautilus-file.c | 58 ++--- src-ng/nautilus-file.h | 1 + src-ng/nautilus-main.c | 269 +++++++++++++++++++ src-ng/nautilus-scheduler-private.h | 49 ++++ src-ng/nautilus-scheduler.c | 158 ++++++++++++ src-ng/nautilus-scheduler.h | 62 +++++ src-ng/nautilus-task-manager.c | 117 --------- src-ng/nautilus-task-manager.h | 37 --- src-ng/nautilus-task-private.h | 29 --- src-ng/nautilus-task.c | 327 ++++++++++++++++++------ src-ng/nautilus-task.h | 131 +++++++++- src-ng/nautilus-tasks.c | 235 +++++++++++++++++ src-ng/nautilus-tasks.h | 35 +++ src-ng/tasks/nautilus-attribute-task.c | 126 --------- src-ng/tasks/nautilus-attribute-task.h | 37 --- src-ng/tasks/nautilus-enumerate-children-task.c | 142 ---------- src-ng/tasks/nautilus-enumerate-children-task.h | 38 --- src-ng/tasks/nautilus-rename-task.c | 150 ----------- src-ng/tasks/nautilus-rename-task.h | 35 --- src-ng/tasks/nautilus-thumbnail-task.c | 287 --------------------- src-ng/tasks/nautilus-thumbnail-task.h | 34 --- 27 files changed, 1430 insertions(+), 1509 deletions(-) delete mode 100644 src-ng/main.c create mode 100644 src-ng/nautilus-context-scheduler.c create mode 100644 src-ng/nautilus-context-scheduler.h create mode 100644 src-ng/nautilus-main.c create mode 100644 src-ng/nautilus-scheduler-private.h create mode 100644 src-ng/nautilus-scheduler.c create mode 100644 src-ng/nautilus-scheduler.h delete mode 100644 src-ng/nautilus-task-manager.c delete mode 100644 src-ng/nautilus-task-manager.h delete mode 100644 src-ng/nautilus-task-private.h create mode 100644 src-ng/nautilus-tasks.c create mode 100644 src-ng/nautilus-tasks.h delete mode 100644 src-ng/tasks/nautilus-attribute-task.c delete mode 100644 src-ng/tasks/nautilus-attribute-task.h delete mode 100644 src-ng/tasks/nautilus-enumerate-children-task.c delete mode 100644 src-ng/tasks/nautilus-enumerate-children-task.h delete mode 100644 src-ng/tasks/nautilus-rename-task.c delete mode 100644 src-ng/tasks/nautilus-rename-task.h delete mode 100644 src-ng/tasks/nautilus-thumbnail-task.c delete mode 100644 src-ng/tasks/nautilus-thumbnail-task.h diff --git a/meson.build b/meson.build index 92e4b4946..5530f9473 100644 --- a/meson.build +++ b/meson.build @@ -20,7 +20,7 @@ searchproviderdir = join_paths (datadir, 'gnome-shell', 'search-providers') servicedir = join_paths (datadir, 'dbus-1', 'services') sysconfdir = get_option ('sysconfdir') -glib_ver = '>=2.51.2' +glib_ver = '>=2.53.5' gnome_desktop_ver = '>=3.0.0' pango_ver = '1.28.3' gtk_ver = '>=3.22.6' diff --git a/src-ng/main.c b/src-ng/main.c deleted file mode 100644 index fa36b5922..000000000 --- a/src-ng/main.c +++ /dev/null @@ -1,274 +0,0 @@ -#include -#include - -#include -#include - -#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, - GFileInfo *info, - GError *error, - gpointer user_data) -{ - g_print ("Got info for %p\n" - "\tDisplay name: %s\n" - "\tFile is directory: %s\n\n", - (gpointer) file, - g_file_info_get_display_name (info), - NAUTILUS_IS_DIRECTORY (file)? "yes" : "no"); - - g_object_unref (info); - - if (user_data != NULL) - { - g_main_loop_quit ((GMainLoop *) user_data); - } -} - -static void -got_children (NautilusDirectory *directory, - GList *children, - GError *error, - gpointer user_data) -{ - g_print ("Got children for %p\n", (gpointer) directory); - - if (children == NULL) - { - g_list_free (children); - - g_main_loop_quit ((GMainLoop *) user_data); - - return; - } - - for (GList *i = children; i != NULL; i = i->next) - { - if (G_UNLIKELY (i->next == NULL)) - { - nautilus_file_query_info (NAUTILUS_FILE (i->data), - NULL, got_info, user_data); - } - else - { - nautilus_file_query_info (NAUTILUS_FILE (i->data), - NULL, got_info, NULL); - } - } - - g_list_free (children); -} - -static void -perform_self_test_checks (const gchar *path) -{ - g_autoptr (GFile) location = NULL; - g_autoptr (NautilusFile) file = NULL; - g_autoptr (NautilusFile) duplicate_file = NULL; - GMainLoop *loop; - - location = g_file_new_for_path (path); - - g_print ("Creating NautilusFile\n"); - file = nautilus_file_new (location); - g_print ("\tGot %p\n\n", (gpointer) file); - - g_print ("Creating another NautilusFile for the same location\n"); - duplicate_file = nautilus_file_new (location); - g_print ("\tGot %p, which is %s\n\n", - (gpointer) duplicate_file, - file == duplicate_file? "the same" : "not the same"); - - loop = g_main_loop_new (NULL, TRUE); - - if (NAUTILUS_IS_DIRECTORY (file)) - { - nautilus_file_query_info (file, NULL, got_info, NULL); - } - else - { - nautilus_file_query_info (file, NULL, got_info, loop); - } - - if (NAUTILUS_IS_DIRECTORY (file)) - { - nautilus_directory_enumerate_children (NAUTILUS_DIRECTORY (file), - NULL, - got_children, - loop); - } - - g_main_loop_run (loop); -} - -static void -on_children_changed (NautilusDirectory *directory, - gpointer user_data) -{ - g_main_loop_quit ((GMainLoop *) user_data); -} - -static void -_rename (const gchar *target, - const gchar *name) -{ - g_autoptr (GFile) location = NULL; - g_autoptr (NautilusFile) file = NULL; - g_autoptr (NautilusFile) parent = NULL; - g_autoptr (NautilusTaskManager) manager = NULL; - g_autoptr (NautilusTask) task = NULL; - GMainLoop *loop; - - location = g_file_new_for_path (target); - g_message ("Constructed GFile %p for path %s", - (gpointer) location, target); - file = nautilus_file_new (location); - parent = nautilus_file_get_parent (file); - g_message ("Constructed NautilusFile %p for location %p", - (gpointer) file, (gpointer) location); - manager = nautilus_task_manager_dup_singleton (); - task = nautilus_rename_task_new (); - loop = g_main_loop_new (NULL, TRUE); - - g_signal_connect (parent, "children-changed", - G_CALLBACK (on_children_changed), loop); - - nautilus_rename_task_add_target (NAUTILUS_RENAME_TASK (task), - location, name); - - nautilus_task_manager_queue_task (manager, task); - - 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", G_CALLBACK (on_window_deleted), NULL); - g_signal_connect (task, "finished", G_CALLBACK (on_thumbnail_finished), window); - - nautilus_task_manager_queue_task (task_manager, task); - - gtk_main (); -} - -int -main (int argc, - char **argv) -{ - g_autoptr (GOptionContext) option_context = NULL; - gchar **files = NULL; - gboolean check = FALSE; - gchar *new_name = NULL; - gboolean thumbnail = FALSE; - const GOptionEntry option_entries[] = - { - { - G_OPTION_REMAINING, 0, G_OPTION_FLAG_NONE, - G_OPTION_ARG_FILENAME_ARRAY, &files, NULL, NULL - }, - { - "check", 'c', G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, &check, - "Perform self-test checks with FILE as input", NULL - }, - { - "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; - g_autoptr (NautilusTaskManager) manager = NULL; - - setlocale (LC_ALL, ""); - - option_context = g_option_context_new ("[FILE]"); - - g_option_context_add_main_entries (option_context, option_entries, NULL); - - if (!g_option_context_parse (option_context, &argc, &argv, &error)) - { - g_print ("%s\n", error->message); - - return EXIT_FAILURE; - } - - if (files == NULL) - { - g_print ("No input file specified\n"); - - return EXIT_FAILURE; - } - - manager = nautilus_task_manager_dup_singleton (); - - if (check) - { - perform_self_test_checks (files[0]); - } - - if (new_name != NULL && new_name[0] != '\0') - { - _rename (files[0], new_name); - } - - if (thumbnail) - { - display_thumbnail (files[0]); - } - - return EXIT_SUCCESS; -} diff --git a/src-ng/meson.build b/src-ng/meson.build index 493af051f..bfc1cf39c 100644 --- a/src-ng/meson.build +++ b/src-ng/meson.build @@ -2,33 +2,33 @@ 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', - 'nautilus-task-manager.h', - 'nautilus-file.c', - 'nautilus-file.h', - 'tasks/nautilus-attribute-task.c', - 'tasks/nautilus-attribute-task.h', - 'nautilus-directory.c', - 'nautilus-directory.h', - 'tasks/nautilus-enumerate-children-task.c', - 'tasks/nautilus-enumerate-children-task.h', - 'nautilus-cache.c', - 'nautilus-cache.h', - 'tasks/nautilus-rename-task.c', - 'tasks/nautilus-rename-task.h', - 'nautilus-file-changes.c', - 'nautilus-file-changes.h', - 'nautilus-signal-utilities.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_sources = [ + resources, + 'nautilus-task.c', + 'nautilus-task.h', + 'nautilus-file.c', + 'nautilus-file.h', + 'nautilus-directory.c', + 'nautilus-directory.h', + 'nautilus-cache.c', + 'nautilus-cache.h', + 'nautilus-file-changes.c', + 'nautilus-file-changes.h', + 'nautilus-signal-utilities.c', + 'nautilus-signal-utilities.h', + 'nautilus-file-table.c', + 'nautilus-file-table.h', + 'nautilus-attribute.c', + 'nautilus-attribute.h', + 'nautilus-tasks.c', + 'nautilus-tasks.h', + 'nautilus-scheduler.c', + 'nautilus-scheduler.h', + 'nautilus-context-scheduler.c', + 'nautilus-context-scheduler.h', + 'nautilus-scheduler-private.h', + 'nautilus-main.c' +] nautilus_ng_dependencies = [gio, glib, gnome_desktop, gtk] diff --git a/src-ng/nautilus-context-scheduler.c b/src-ng/nautilus-context-scheduler.c new file mode 100644 index 000000000..5f7723a9b --- /dev/null +++ b/src-ng/nautilus-context-scheduler.c @@ -0,0 +1,166 @@ +/* Copyright (C) 2017 Ernestas Kulik + * + * 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 . + */ + +#include "nautilus-context-scheduler.h" + +#include "nautilus-scheduler-private.h" + +struct _NautilusContextScheduler +{ + NautilusScheduler parent_instance; + + GMainContext *context; + guint source_id; + + GQueue *queue; +}; + +G_DEFINE_TYPE (NautilusContextScheduler, nautilus_context_scheduler, + NAUTILUS_TYPE_SCHEDULER) + +typedef struct +{ + GSource parent_instance; + + NautilusContextScheduler *scheduler; +} NautilusSource; + +G_LOCK_DEFINE_STATIC (table_mutex); +static GHashTable *scheduler_table = NULL; + +static void +queue (NautilusScheduler *scheduler, + NautilusCallback func, + gpointer func_data) +{ + NautilusContextScheduler *context_scheduler; + NautilusThreadWork *work; + + context_scheduler = NAUTILUS_CONTEXT_SCHEDULER (scheduler); + work = nautilus_thread_work_new (func, func_data); + + g_queue_push_tail (context_scheduler->queue, work); +} + +static void +nautilus_context_scheduler_class_init (NautilusContextSchedulerClass *klass) +{ + NautilusSchedulerClass *scheduler_class; + + scheduler_class = NAUTILUS_SCHEDULER_CLASS (klass); + + scheduler_class->queue = queue; +} + +static gboolean +source_prepare (GSource *source, + gint *timeout) +{ + NautilusSource *nautilus_source; + + nautilus_source = (NautilusSource *) source; + + *timeout = -1; + + return !g_queue_is_empty (nautilus_source->scheduler->queue); +} + +static gboolean +source_check (GSource *source) +{ + NautilusSource *nautilus_source; + + nautilus_source = (NautilusSource *) source; + + return !g_queue_is_empty (nautilus_source->scheduler->queue); +} + +static gboolean +source_dispatch (GSource *source, + GSourceFunc callback, + gpointer user_data) +{ + return callback (user_data); +} + +static GSourceFuncs source_funcs = +{ + source_prepare, + source_check, + source_dispatch, + NULL +}; + +static gboolean +source_callback (gpointer data) +{ + NautilusContextScheduler *scheduler; + NautilusThreadWork *work; + + scheduler = data; + + while ((work = g_queue_pop_head (scheduler->queue)) != NULL) + { + nautilus_thread_work_run (work); + } + + return G_SOURCE_CONTINUE; +} + +static void +nautilus_context_scheduler_init (NautilusContextScheduler *self) +{ + g_autoptr (GSource) source = NULL; + + source = g_source_new (&source_funcs, sizeof (NautilusSource)); + + g_source_set_priority (source, G_PRIORITY_DEFAULT_IDLE); + g_source_set_callback (source, source_callback, self, NULL); + + self->source_id = g_source_attach (source, self->context); +} + +NautilusScheduler * +nautilus_context_scheduler_get_for_context (GMainContext *context) +{ + NautilusContextScheduler *scheduler; + + g_return_val_if_fail (context != NULL, NULL); + + G_LOCK (table_mutex); + + if (scheduler_table == NULL) + { + scheduler_table = g_hash_table_new_full (g_direct_hash, g_direct_equal, + NULL, g_object_unref); + } + + scheduler = g_hash_table_lookup (scheduler_table, context); + if (scheduler == NULL) + { + scheduler = g_object_new (NAUTILUS_TYPE_CONTEXT_SCHEDULER, NULL); + + scheduler->context = context; + + g_hash_table_insert (scheduler_table, context, scheduler); + } + + G_UNLOCK (table_mutex); + + return NAUTILUS_SCHEDULER (scheduler); +} diff --git a/src-ng/nautilus-context-scheduler.h b/src-ng/nautilus-context-scheduler.h new file mode 100644 index 000000000..18a753f12 --- /dev/null +++ b/src-ng/nautilus-context-scheduler.h @@ -0,0 +1,37 @@ +/* Copyright (C) 2017 Ernestas Kulik + * + * 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 . + */ + +#ifndef NAUTILUS_CONTEXT_SCHEDULER_H_INCLUDED +#define NAUTILUS_CONTEXT_SCHEDULER_H_INCLUDED + +#include "nautilus-scheduler.h" + +#define NAUTILUS_TYPE_CONTEXT_SCHEDULER (nautilus_context_scheduler_get_type ()) + +G_DECLARE_FINAL_TYPE (NautilusContextScheduler, nautilus_context_scheduler, + NAUTILUS, CONTEXT_SCHEDULER, NautilusScheduler) + +/** + * nautilus_context_scheduler_get_for_context: + * @context: a valid main context + * + * Returns: (transfer none): the scheduler for @context + */ +NautilusScheduler *nautilus_context_scheduler_get_for_context (GMainContext *context); + +#endif diff --git a/src-ng/nautilus-directory.c b/src-ng/nautilus-directory.c index c125a3968..a4c8c1313 100644 --- a/src-ng/nautilus-directory.c +++ b/src-ng/nautilus-directory.c @@ -19,8 +19,8 @@ #include "nautilus-directory.h" #include "nautilus-cache.h" -#include "nautilus-task-manager.h" -#include "tasks/nautilus-enumerate-children-task.h" +#include "nautilus-task.h" +#include "nautilus-tasks.h" enum { @@ -101,7 +101,7 @@ typedef struct gpointer callback_data; } EnumerateChildrenDetails; -static void +/*static void create_file_list (gpointer key, gpointer value, gpointer user_data) @@ -113,9 +113,9 @@ create_file_list (gpointer key, *list = g_list_prepend (*list, nautilus_file_new_with_info (G_FILE (key), G_FILE_INFO (value))); -} +}*/ -static void +/*static void on_enumerate_children_finished (NautilusEnumerateChildrenTask *task, GFile *file, GHashTable *files, @@ -133,9 +133,9 @@ on_enumerate_children_finished (NautilusEnumerateChildrenTask *task, priv->cache_items[CHILDREN]); if (cache_state == NAUTILUS_CACHE_INVALID) - { + {*/ /* TODO: restart */ - return; + /*return; } g_hash_table_foreach (files, create_file_list, &children); @@ -147,7 +147,7 @@ on_enumerate_children_finished (NautilusEnumerateChildrenTask *task, details->callback_data); g_free (details); -} +}*/ void nautilus_directory_enumerate_children (NautilusDirectory *directory, @@ -159,8 +159,6 @@ nautilus_directory_enumerate_children (NautilusDirectory *direct NautilusCacheState cache_state; g_autoptr (GFile) location = NULL; g_autoptr (NautilusTask) task = NULL; - EnumerateChildrenDetails *details; - g_autoptr (NautilusTaskManager) task_manager = NULL; g_return_if_fail (NAUTILUS_IS_DIRECTORY (directory)); @@ -184,33 +182,10 @@ nautilus_directory_enumerate_children (NautilusDirectory *direct priv->cache_items[CHILDREN]); location = nautilus_file_get_location (NAUTILUS_FILE (directory)); - task = nautilus_enumerate_children_task_new (location, - "standard::*," - "access::*," - "mountable::*," - "time::*," - "unix::*," - "owner::*," - "selinux::*," - "thumbnail::*," - "id::filesystem," - "trash::orig-path," - "trash::deletion-date," - "metadata::*," - "recent::*", - G_FILE_QUERY_INFO_NONE, - cancellable); - details = g_new0 (EnumerateChildrenDetails, 1); - task_manager = nautilus_task_manager_dup_singleton (); - - details->directory = directory; - details->callback = callback; - details->callback_data = user_data; - - g_signal_connect (task, "finished", - G_CALLBACK (on_enumerate_children_finished), details); - - nautilus_task_manager_queue_task (task_manager, task); + task = nautilus_task_new_with_func (nautilus_enumerate_children_task_func, location, + cancellable); + + nautilus_task_run (task); } NautilusFile * diff --git a/src-ng/nautilus-file.c b/src-ng/nautilus-file.c index 9701be12b..b5438806e 100644 --- a/src-ng/nautilus-file.c +++ b/src-ng/nautilus-file.c @@ -21,9 +21,8 @@ #include "nautilus-cache.h" #include "nautilus-directory.h" #include "nautilus-file-table.h" -#include "nautilus-task-manager.h" -#include "tasks/nautilus-attribute-task.h" -#include "tasks/nautilus-thumbnail-task.h" +#include "nautilus-task.h" +#include "nautilus-tasks.h" enum { @@ -203,7 +202,7 @@ typedef struct gpointer callback_data; } QueryInfoDetails; -static void +/*static void on_query_info_finished (NautilusAttributeTask *task, GFile *file, GFileInfo *info, @@ -220,9 +219,9 @@ on_query_info_finished (NautilusAttributeTask *task, priv->cache_items[INFO]); if (cache_state == NAUTILUS_CACHE_INVALID) - { + {*/ /* TODO: restart */ - return; + /*return; } nautilus_cache_item_set_value (priv->cache, priv->cache_items[INFO], @@ -232,7 +231,7 @@ on_query_info_finished (NautilusAttributeTask *task, details->callback_data); g_free (details); -} +}*/ void nautilus_file_query_info (NautilusFile *file, @@ -242,9 +241,9 @@ nautilus_file_query_info (NautilusFile *file, { NautilusFilePrivate *priv; NautilusCacheState cache_state; + GFile *location; g_autoptr (NautilusTask) task = NULL; QueryInfoDetails *details; - g_autoptr (NautilusTaskManager) manager = NULL; g_return_if_fail (NAUTILUS_IS_FILE (file)); @@ -277,61 +276,34 @@ nautilus_file_query_info (NautilusFile *file, nautilus_cache_item_set_pending (priv->cache, priv->cache_items[INFO]); - task = nautilus_attribute_task_new (priv->location, - "standard::*," - "access::*," - "mountable::*," - "time::*," - "unix::*," - "owner::*," - "selinux::*," - "thumbnail::*," - "id::filesystem," - "trash::orig-path," - "trash::deletion-date," - "metadata::*," - "recent::*", - G_FILE_QUERY_INFO_NONE, - cancellable); + location = nautilus_file_get_location (file); + task = nautilus_task_new_with_func (nautilus_query_info_func, location, cancellable); + details = g_new0 (QueryInfoDetails, 1); - manager = nautilus_task_manager_dup_singleton (); details->file = file; details->callback = callback; details->callback_data = user_data; - g_signal_connect (task, "finished", - G_CALLBACK (on_query_info_finished), details); - - nautilus_task_manager_queue_task (manager, task); + nautilus_task_run (task); } -typedef struct -{ - NautilusFile *file; - - NautilusFileInfoCallback callback; - gpointer callback_data; -} GetThumbnailDetails; - void nautilus_file_get_thumbnail (NautilusFile *file, + GCancellable *cancellable, 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 (); + task = nautilus_task_new_with_func (nautilus_thumbnail_task_func, + g_object_ref (location), cancellable); - nautilus_task_manager_queue_task (manager, task); + nautilus_task_run (task); } NautilusFile * diff --git a/src-ng/nautilus-file.h b/src-ng/nautilus-file.h index 8d26aea1c..8d9407b32 100644 --- a/src-ng/nautilus-file.h +++ b/src-ng/nautilus-file.h @@ -55,6 +55,7 @@ void nautilus_file_query_info (NautilusFile *file, NautilusFileInfoCallback callback, gpointer user_data); void nautilus_file_get_thumbnail (NautilusFile *file, + GCancellable *cancellable, NautilusThumbnailCallback callback, gpointer user_data); diff --git a/src-ng/nautilus-main.c b/src-ng/nautilus-main.c new file mode 100644 index 000000000..57f5e8040 --- /dev/null +++ b/src-ng/nautilus-main.c @@ -0,0 +1,269 @@ +#include +#include + +#include +#include + +#include "nautilus-directory.h" +#include "nautilus-file.h" +#include "nautilus-task.h" +#include "nautilus-tasks.h" + +static void +got_info (NautilusFile *file, + GFileInfo *info, + GError *error, + gpointer user_data) +{ + g_print ("Got info for %p\n" + "\tDisplay name: %s\n" + "\tFile is directory: %s\n\n", + (gpointer) file, + g_file_info_get_display_name (info), + NAUTILUS_IS_DIRECTORY (file)? "yes" : "no"); + + g_object_unref (info); + + if (user_data != NULL) + { + g_main_loop_quit ((GMainLoop *) user_data); + } +} + +static void +got_children (NautilusDirectory *directory, + GList *children, + GError *error, + gpointer user_data) +{ + g_print ("Got children for %p\n", (gpointer) directory); + + if (children == NULL) + { + g_list_free (children); + + g_main_loop_quit ((GMainLoop *) user_data); + + return; + } + + for (GList *i = children; i != NULL; i = i->next) + { + if (G_UNLIKELY (i->next == NULL)) + { + nautilus_file_query_info (NAUTILUS_FILE (i->data), + NULL, got_info, user_data); + } + else + { + nautilus_file_query_info (NAUTILUS_FILE (i->data), + NULL, got_info, NULL); + } + } + + g_list_free (children); +} + +static void +perform_self_test_checks (const gchar *path) +{ + g_autoptr (GFile) location = NULL; + g_autoptr (NautilusFile) file = NULL; + g_autoptr (NautilusFile) duplicate_file = NULL; + GMainLoop *loop; + + location = g_file_new_for_path (path); + + g_print ("Creating NautilusFile\n"); + file = nautilus_file_new (location); + g_print ("\tGot %p\n\n", (gpointer) file); + + g_print ("Creating another NautilusFile for the same location\n"); + duplicate_file = nautilus_file_new (location); + g_print ("\tGot %p, which is %s\n\n", + (gpointer) duplicate_file, + file == duplicate_file? "the same" : "not the same"); + + loop = g_main_loop_new (NULL, TRUE); + + if (NAUTILUS_IS_DIRECTORY (file)) + { + nautilus_file_query_info (file, NULL, got_info, NULL); + } + else + { + nautilus_file_query_info (file, NULL, got_info, loop); + } + + if (NAUTILUS_IS_DIRECTORY (file)) + { + nautilus_directory_enumerate_children (NAUTILUS_DIRECTORY (file), + NULL, + got_children, + loop); + } + + g_main_loop_run (loop); +} + +static void +on_children_changed (NautilusDirectory *directory, + gpointer user_data) +{ + g_main_loop_quit ((GMainLoop *) user_data); +} + +static void +_rename (const gchar *target, + const gchar *name) +{ + g_autoptr (GFile) location = NULL; + g_autoptr (NautilusFile) file = NULL; + g_autoptr (NautilusFile) parent = NULL; + g_autoptr (GHashTable) targets = NULL; + g_autoptr (NautilusTask) task = NULL; + GMainLoop *loop; + + location = g_file_new_for_path (target); + g_message ("Constructed GFile %p for path %s", + (gpointer) location, target); + file = nautilus_file_new (location); + parent = nautilus_file_get_parent (file); + g_message ("Constructed NautilusFile %p for location %p", + (gpointer) file, (gpointer) location); + targets = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, NULL); + task = nautilus_task_new_with_func (nautilus_rename_task_func, targets, NULL); + loop = g_main_loop_new (NULL, TRUE); + + (void) g_hash_table_insert (targets, location, name); + + g_signal_connect (parent, "children-changed", + G_CALLBACK (on_children_changed), loop); + + nautilus_task_run (task); + + 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", G_CALLBACK (on_window_deleted), NULL); + g_signal_connect (task, "finished", G_CALLBACK (on_thumbnail_finished), window); + + nautilus_task_manager_queue_task (task_manager, task); + + gtk_main ();*/ +} + +int +main (int argc, + char **argv) +{ + g_autoptr (GOptionContext) option_context = NULL; + gchar **files = NULL; + gboolean check = FALSE; + gchar *new_name = NULL; + gboolean thumbnail = FALSE; + const GOptionEntry option_entries[] = + { + { + G_OPTION_REMAINING, 0, G_OPTION_FLAG_NONE, + G_OPTION_ARG_FILENAME_ARRAY, &files, NULL, NULL + }, + { + "check", 'c', G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, &check, + "Perform self-test checks with FILE as input", NULL + }, + { + "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; + + setlocale (LC_ALL, ""); + + option_context = g_option_context_new ("[FILE]"); + + g_option_context_add_main_entries (option_context, option_entries, NULL); + + if (!g_option_context_parse (option_context, &argc, &argv, &error)) + { + g_print ("%s\n", error->message); + + return EXIT_FAILURE; + } + + if (files == NULL) + { + g_print ("No input file specified\n"); + + return EXIT_FAILURE; + } + + if (check) + { + perform_self_test_checks (files[0]); + } + + if (new_name != NULL && new_name[0] != '\0') + { + _rename (files[0], new_name); + } + + if (thumbnail) + { + display_thumbnail (files[0]); + } + + return EXIT_SUCCESS; +} diff --git a/src-ng/nautilus-scheduler-private.h b/src-ng/nautilus-scheduler-private.h new file mode 100644 index 000000000..737c2a5be --- /dev/null +++ b/src-ng/nautilus-scheduler-private.h @@ -0,0 +1,49 @@ +/* Copyright (C) 2017 Ernestas Kulik + * + * 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 . + */ + +#ifndef NAUTILUS_SCHEDULER_PRIVATE_H_INCLUDED +#define NAUTILUS_SCHEDULER_PRIVATE_H_INCLUDED + +#include "nautilus-scheduler.h" + +typedef struct NautilusThreadWork NautilusThreadWork; + +/** + * nautilus_thread_work_run: + * @work: an initialized #NautilusThreadWork + */ +void nautilus_thread_work_run (NautilusThreadWork *work); + +/** + * nautilus_thread_work_free: + * @work: an initialized #NautilusThreadWork + */ +void nautilus_thread_work_free (NautilusThreadWork *work); +/** + * nautilus_thread_work_new: + * @callback: the function to call + * @data: data to pass to @callback + * + * Returns: (transfer full): a new #NautilusThreadWork instance + */ +NautilusThreadWork *nautilus_thread_work_new (NautilusCallback callback, + gpointer data); + +G_DEFINE_AUTOPTR_CLEANUP_FUNC (NautilusThreadWork, nautilus_thread_work_free) + +#endif diff --git a/src-ng/nautilus-scheduler.c b/src-ng/nautilus-scheduler.c new file mode 100644 index 000000000..6695efc78 --- /dev/null +++ b/src-ng/nautilus-scheduler.c @@ -0,0 +1,158 @@ +/* Copyright (C) 2017 Ernestas Kulik + * + * 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 . + */ + +#include "nautilus-scheduler-private.h" + +typedef struct +{ + GThreadPool *thread_pool; +} NautilusSchedulerPrivate; + +G_DEFINE_TYPE_WITH_PRIVATE (NautilusScheduler, nautilus_scheduler, G_TYPE_OBJECT) + +struct NautilusThreadWork +{ + NautilusCallback func; + gpointer func_data; +}; + +static void +finalize (GObject *object) +{ + NautilusScheduler *scheduler; + NautilusSchedulerPrivate *priv; + + scheduler = NAUTILUS_SCHEDULER (object); + priv = nautilus_scheduler_get_instance_private (scheduler); + + g_thread_pool_free (priv->thread_pool, TRUE, TRUE); + + G_OBJECT_CLASS (nautilus_scheduler_parent_class)->finalize (object); +} + +static void +queue (NautilusScheduler *scheduler, + NautilusCallback func, + gpointer func_data) +{ + NautilusSchedulerPrivate *priv; + NautilusThreadWork *work; + + priv = nautilus_scheduler_get_instance_private (scheduler); + work = nautilus_thread_work_new (func, func_data); + + (void) g_thread_pool_push (priv->thread_pool, work, NULL); +} + +static void +nautilus_scheduler_class_init (NautilusSchedulerClass *klass) +{ + GObjectClass *object_class; + + object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = finalize; + + klass->queue = queue; +} + +static void +nautilus_scheduler_init (NautilusScheduler *self) +{ +} + +void +nautilus_scheduler_queue (NautilusScheduler *scheduler, + NautilusCallback func, + gpointer func_data) +{ + g_return_if_fail (NAUTILUS_IS_SCHEDULER (scheduler)); + g_return_if_fail (func != NULL); + + NAUTILUS_SCHEDULER_GET_CLASS (scheduler)->queue (scheduler, func, func_data); +} + +static void +thread_pool_func (gpointer data, + gpointer user_data) +{ + g_autoptr (NautilusThreadWork) work = NULL; + + work = data; + + nautilus_thread_work_run (work); +} + +static NautilusScheduler * +nautilus_scheduler_new (gint max_threads) +{ + NautilusScheduler *scheduler; + NautilusSchedulerPrivate *priv; + + scheduler = g_object_new (NAUTILUS_TYPE_SCHEDULER, NULL); + priv = nautilus_scheduler_get_instance_private (scheduler); + + priv->thread_pool = g_thread_pool_new (thread_pool_func, NULL, max_threads, FALSE, NULL); + + return scheduler; +} + +static gpointer +create_default_instance (gpointer data) +{ + (void) data; + + return nautilus_scheduler_new (16); +} + +NautilusScheduler * +nautilus_scheduler_get_default (void) +{ + static GOnce once = G_ONCE_INIT; + + g_once (&once, create_default_instance, NULL); + + return g_object_ref (once.retval); +} + + +void +nautilus_thread_work_run (NautilusThreadWork *work) +{ + work->func (work->func_data); +} + +void +nautilus_thread_work_free (NautilusThreadWork *work) +{ + g_free (work); +} + +NautilusThreadWork * +nautilus_thread_work_new (NautilusCallback callback, + gpointer data) +{ + NautilusThreadWork *work; + + work = g_new0 (NautilusThreadWork, 1); + + work->func = callback; + work->func_data = data; + + return work; +} diff --git a/src-ng/nautilus-scheduler.h b/src-ng/nautilus-scheduler.h new file mode 100644 index 000000000..e589e7a37 --- /dev/null +++ b/src-ng/nautilus-scheduler.h @@ -0,0 +1,62 @@ +/* Copyright (C) 2017 Ernestas Kulik + * + * 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 . + */ + +#ifndef NAUTILUS_SCHEDULER_H_INCLUDED +#define NAUTILUS_SCHEDULER_H_INCLUDED + +#include + +#define NAUTILUS_CALLBACK(x) ((NautilusCallback) x) +#define NAUTILUS_TYPE_SCHEDULER (nautilus_scheduler_get_type ()) + +G_DECLARE_DERIVABLE_TYPE (NautilusScheduler, nautilus_scheduler, + NAUTILUS, SCHEDULER, GObject) + +/** + * NautilusCallback: + * @data: (nullable): user data passed to #nautilus_scheduler_queue + */ +typedef void (*NautilusCallback) (gpointer data); + +struct _NautilusSchedulerClass +{ + GObjectClass parent_class; + + void (*queue) (NautilusScheduler *scheduler, + NautilusCallback func, + gpointer func_data); +}; + +/** + * nautilus_scheduler_queue: + * @scheduler: an initialized #NautilusScheduler + * @func: the #NautilusCallback to call + * @func_data: (nullable): additional data to pass to @func + */ +void nautilus_scheduler_queue (NautilusScheduler *scheduler, + NautilusCallback func, + gpointer func_data); + +/** + * nautilus_scheduler_get_default: + * + * Returns: (transfer full): the default #NautilusScheduler instance + */ +NautilusScheduler *nautilus_scheduler_get_default (void); + +#endif diff --git a/src-ng/nautilus-task-manager.c b/src-ng/nautilus-task-manager.c deleted file mode 100644 index 7c20a9753..000000000 --- a/src-ng/nautilus-task-manager.c +++ /dev/null @@ -1,117 +0,0 @@ -/* Copyright (C) 2017 Ernestas Kulik - * - * 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 . - */ - -#include "nautilus-task-manager.h" - -struct _NautilusTaskManager -{ - GObject parent_instance; - - GThreadPool *thread_pool; -}; - -G_DEFINE_TYPE (NautilusTaskManager, nautilus_task_manager, G_TYPE_OBJECT) - -static NautilusTaskManager *instance = NULL; - -static GObject * -constructor (GType type, - guint n_construct_properties, - GObjectConstructParam *construct_properties) -{ - static GMutex mutex; - GObjectClass *parent_class; - - g_mutex_lock (&mutex); - - if (instance != NULL) - { - g_mutex_unlock (&mutex); - return g_object_ref (instance); - } - - parent_class = G_OBJECT_CLASS (nautilus_task_manager_parent_class); - instance = NAUTILUS_TASK_MANAGER (parent_class->constructor (type, - n_construct_properties, - construct_properties)); - - g_object_add_weak_pointer (G_OBJECT (instance), (gpointer *) &instance); - - g_mutex_unlock (&mutex); - - return G_OBJECT (instance); -} - -static void -finalize (GObject *object) -{ - NautilusTaskManager *self; - - self = NAUTILUS_TASK_MANAGER (object); - - g_thread_pool_free (self->thread_pool, TRUE, TRUE); - - G_OBJECT_CLASS (nautilus_task_manager_parent_class)->finalize (object); -} - -static void -nautilus_task_manager_class_init (NautilusTaskManagerClass *klass) -{ - GObjectClass *object_class; - - object_class = G_OBJECT_CLASS (klass); - - object_class->constructor = constructor; - object_class->finalize = finalize; -} - -static void -execute_task (gpointer data, - gpointer user_data) -{ - g_autoptr (NautilusTask) task = NULL; - - task = NAUTILUS_TASK (data); - - nautilus_task_execute (task); -} - -static void -nautilus_task_manager_init (NautilusTaskManager *self) -{ - self->thread_pool = g_thread_pool_new (execute_task, self, - 16, FALSE, - NULL); -} - -void -nautilus_task_manager_queue_task (NautilusTaskManager *self, - NautilusTask *task) -{ - g_return_if_fail (NAUTILUS_IS_TASK_MANAGER (self)); - g_return_if_fail (NAUTILUS_IS_TASK (task)); - - g_thread_pool_push (self->thread_pool, g_object_ref (task), NULL); -} - -NautilusTaskManager * -nautilus_task_manager_dup_singleton (void) -{ - return g_object_new (NAUTILUS_TYPE_TASK_MANAGER, NULL); -} - diff --git a/src-ng/nautilus-task-manager.h b/src-ng/nautilus-task-manager.h deleted file mode 100644 index e895fdeb6..000000000 --- a/src-ng/nautilus-task-manager.h +++ /dev/null @@ -1,37 +0,0 @@ -/* Copyright (C) 2017 Ernestas Kulik - * - * 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 . - */ - -#ifndef NAUTILUS_TASK_MANAGER_H_INCLUDED -#define NAUTILUS_TASK_MANAGER_H_INCLUDED - -#include "nautilus-task.h" - -#include - -#define NAUTILUS_TYPE_TASK_MANAGER (nautilus_task_manager_get_type ()) - -G_DECLARE_FINAL_TYPE (NautilusTaskManager, nautilus_task_manager, - NAUTILUS, TASK_MANAGER, - GObject) - -void nautilus_task_manager_queue_task (NautilusTaskManager *self, - NautilusTask *task); - -NautilusTaskManager *nautilus_task_manager_dup_singleton (void); - -#endif diff --git a/src-ng/nautilus-task-private.h b/src-ng/nautilus-task-private.h deleted file mode 100644 index fc4895b7a..000000000 --- a/src-ng/nautilus-task-private.h +++ /dev/null @@ -1,29 +0,0 @@ -/* Copyright (C) 2017 Ernestas Kulik - * - * 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 . - */ - -#ifndef NAUTILUS_TASK_PRIVATE_H_INCLUDED -#define NAUTILUS_TASK_PRIVATE_H_INCLUDED - -#include "nautilus-task.h" - -void nautilus_task_emit_signal_in_main_context (NautilusTask *task, - guint signal_id, - GQuark detail, - ...); - -#endif diff --git a/src-ng/nautilus-task.c b/src-ng/nautilus-task.c index de6bdea36..8506648f8 100644 --- a/src-ng/nautilus-task.c +++ b/src-ng/nautilus-task.c @@ -18,150 +18,309 @@ #include "nautilus-task.h" -#include "nautilus-signal-utilities.h" +#include "nautilus-context-scheduler.h" -typedef struct +struct _NautilusTask { + GObject parent_instance; + + NautilusScheduler *scheduler; + + GClosure *closure; GCancellable *cancellable; - GMainContext *context; -} NautilusTaskPrivate; + GError *error; -G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (NautilusTask, nautilus_task, - G_TYPE_OBJECT) + GValue result; -enum -{ - PROP_CANCELLABLE = 1, - N_PROPERTIES + GMainContext *context; + GQueue *callbacks; }; -static GParamSpec *properties[N_PROPERTIES] = { NULL }; +G_DEFINE_TYPE (NautilusTask, nautilus_task, G_TYPE_OBJECT) static void -set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec) +finalize (GObject *object) { - switch (property_id) + NautilusTask *self; + + self = NAUTILUS_TASK (object); + + if (self->closure != NULL) { - case PROP_CANCELLABLE: - { - NautilusTask *self; - NautilusTaskPrivate *priv; + g_clear_pointer (&self->closure, g_closure_unref); + } + if (self->cancellable != NULL) + { + g_clear_object (&self->cancellable); + } + if (self->error != NULL) + { + g_clear_pointer (&self->error, g_error_free); + } - self = NAUTILUS_TASK (object); - priv = nautilus_task_get_instance_private (self); + g_queue_free (self->callbacks); - if (G_UNLIKELY (priv->cancellable) != NULL) - { - g_clear_object (&priv->cancellable); - } + G_OBJECT_CLASS (nautilus_task_parent_class)->finalize (object); +} - priv->cancellable = g_value_dup_object (value); - } - break; +static void +nautilus_task_class_init (NautilusTaskClass *klass) +{ + GObjectClass *object_class; - default: - { - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - } - } + object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = finalize; } static void -finalize (GObject *object) +nautilus_task_init (NautilusTask *self) { - NautilusTask *self; - NautilusTaskPrivate *priv; + self->scheduler = nautilus_scheduler_get_default (); + self->cancellable = NULL; + self->error = NULL; + self->context = NULL; + self->callbacks = g_queue_new (); +} - self = NAUTILUS_TASK (object); - priv = nautilus_task_get_instance_private (self); +GMainContext * +nautilus_task_get_main_context (NautilusTask *task) +{ + g_return_val_if_fail (NAUTILUS_IS_TASK (task), NULL); - g_clear_object (&priv->cancellable); - g_clear_pointer (&priv->context, g_main_context_unref); + if (task->context == NULL) + { + return NULL; + } - G_OBJECT_CLASS (nautilus_task_parent_class)->finalize (object); + return g_main_context_ref (task->context); +} + +void +nautilus_task_set_main_context (NautilusTask *task, + GMainContext *context) +{ + g_return_if_fail (NAUTILUS_IS_TASK (task)); + g_return_if_fail (context != NULL); + + if (task->context != NULL) + { + g_main_context_unref (task->context); + } + + task->context = g_main_context_ref (context); } static void -nautilus_task_class_init (NautilusTaskClass *klass) +nautilus_task_add_callback_closure (NautilusTask *task, + GClosure *closure) { - GObjectClass *object_class; + g_queue_push_tail (task->callbacks, g_closure_ref (closure)); +} - object_class = G_OBJECT_CLASS (klass); +void +nautilus_task_add_callback (NautilusTask *task, + NautilusTaskFunc callback, + gpointer user_data) +{ + g_autoptr (GClosure) closure = NULL; - object_class->set_property = set_property; - object_class->finalize = finalize; + g_return_if_fail (NAUTILUS_IS_TASK (task)); + g_return_if_fail (callback != NULL); + + closure = g_cclosure_new (G_CALLBACK (callback), user_data, NULL); - properties[PROP_CANCELLABLE] = - g_param_spec_object ("cancellable", "Cancellable", "Cancellable", - G_TYPE_CANCELLABLE, - G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE | G_PARAM_STATIC_NAME); + g_closure_set_marshal (closure, g_cclosure_marshal_VOID__VOID); - g_object_class_install_properties (object_class, N_PROPERTIES, properties); + nautilus_task_add_callback_closure (task, closure); } static void -nautilus_task_init (NautilusTask *self) +invoke_callbacks_iteration (gpointer data) +{ + NautilusTask *task; + g_autoptr (GClosure) closure = NULL; + GValue params = { 0 }; + + task = data; + closure = g_queue_pop_head (task->callbacks); + + g_value_init (¶ms, G_TYPE_OBJECT); + g_value_set_object (¶ms, task); + g_closure_invoke (closure, NULL, 1, ¶ms, NULL); + g_closure_invalidate (closure); + g_value_unset (¶ms); +} + +void +nautilus_task_complete (NautilusTask *task) { - NautilusTaskPrivate *priv; + g_return_if_fail (NAUTILUS_IS_TASK (task)); + + while (g_queue_peek_head (task->callbacks) != NULL) + { + if (task->context != NULL) + { + NautilusScheduler *context_scheduler; - priv = nautilus_task_get_instance_private (self); + context_scheduler = nautilus_context_scheduler_get_for_context (task->context); - priv->context = g_main_context_ref_thread_default (); + nautilus_scheduler_queue (context_scheduler, invoke_callbacks_iteration, task); + } + else + { + invoke_callbacks_iteration (task); + } + } } -GCancellable * -nautilus_task_get_cancellable (NautilusTask *task) +GValue * +nautilus_task_get_result (NautilusTask *task) { - NautilusTaskPrivate *priv; + g_return_val_if_fail (NAUTILUS_IS_TASK (task), NULL); - g_return_val_if_fail (NAUTILUS_TASK (task), NULL); + return &task->result; +} - priv = nautilus_task_get_instance_private (task); +void +nautilus_task_set_result (NautilusTask *task, + GType type, + gpointer result) +{ + g_return_if_fail (NAUTILUS_IS_TASK (task)); + g_return_if_fail (type != G_TYPE_INVALID); + g_return_if_fail (result != NULL); - if (priv->cancellable == NULL) + if (G_VALUE_TYPE (&task->result) != G_TYPE_INVALID) { - return NULL; + g_value_unset (&task->result); } - return g_object_ref (priv->cancellable); + g_value_init (&task->result, type); + g_value_set_instance (&task->result, result); +} + +GError * +nautilus_task_get_error (NautilusTask *task) +{ + GError *error; + + g_return_val_if_fail (NAUTILUS_IS_TASK (task), NULL); + + error = task->error; + task->error = NULL; + + return error; } void -nautilus_task_execute (NautilusTask *task) +nautilus_task_set_error (NautilusTask *task, + GError *error) { - NautilusTaskClass *klass; + g_return_if_fail (NAUTILUS_IS_TASK (task)); + g_return_if_fail (error != NULL); + + task->error = error; +} +void +nautilus_task_set_scheduler (NautilusTask *task, + NautilusScheduler *scheduler) +{ g_return_if_fail (NAUTILUS_IS_TASK (task)); + g_return_if_fail (NAUTILUS_IS_SCHEDULER (scheduler)); - klass = NAUTILUS_TASK_GET_CLASS (task); + g_object_unref (task->scheduler); + + task->scheduler = g_object_ref (scheduler); +} + +static void +nautilus_task_execute (gpointer user_data) +{ + NautilusTask *task; + GValue params = { 0 }; - g_return_if_fail (klass->execute != NULL); + task = user_data; - klass->execute (task); + g_value_init (¶ms, G_TYPE_OBJECT); + g_value_set_object (¶ms, task); + g_closure_invoke (task->closure, NULL, 1, ¶ms, NULL); + g_closure_invalidate (task->closure); + g_clear_pointer (&task->closure, g_closure_unref); + g_value_unset (¶ms); } void -nautilus_task_emit_signal_in_main_context (NautilusTask *task, - guint signal_id, - GQuark detail, - ...) +nautilus_task_run (NautilusTask *task) { - NautilusTaskPrivate *priv; - va_list ap; - g_return_if_fail (NAUTILUS_IS_TASK (task)); - priv = nautilus_task_get_instance_private (task); - va_start (ap, detail); + nautilus_scheduler_queue (task->scheduler, + NAUTILUS_CALLBACK (nautilus_task_execute), + g_object_ref (task)); +} + +GCancellable * +nautilus_task_get_cancellable (NautilusTask *task) +{ + g_return_val_if_fail (NAUTILUS_IS_TASK (task), NULL); + + return g_object_ref (task->cancellable); +} + +NautilusTask * +nautilus_task_new_with_closure (GClosure *closure, + GCancellable *cancellable) +{ + NautilusTask *instance; + + g_return_val_if_fail (closure != NULL, NULL); + if (cancellable != NULL) + { + g_return_val_if_fail (G_IS_CANCELLABLE (cancellable), NULL); + } + + instance = g_object_new (NAUTILUS_TYPE_TASK, NULL); - nautilus_emit_signal_in_main_context_va_list (task, - priv->context, - signal_id, - detail, - ap); + instance->closure = g_closure_ref (closure); + if (cancellable != NULL) + { + instance->cancellable = g_object_ref (cancellable); + } - va_end (ap); + return instance; +} + +/* Would be nice to accept a #GDestroyNotify for @user_data, + * but it’s not a #GClosureNotify, ergo UB. + */ +NautilusTask * +nautilus_task_new_with_func (NautilusTaskFunc func, + gpointer func_data, + GCancellable *cancellable) +{ + g_autoptr (GClosure) closure = NULL; + + g_return_val_if_fail (func != NULL, NULL); + + closure = g_cclosure_new (G_CALLBACK (func), func_data, NULL); + + g_closure_set_marshal (closure, g_cclosure_marshal_VOID__VOID); + + return nautilus_task_new_with_closure (closure, cancellable); +} + +static void +dummy_task_func (NautilusTask *task, + gpointer user_data) +{ + (void) task; + (void) user_data; +} + +NautilusTask * +nautilus_task_new (GCancellable *cancellable) +{ + return nautilus_task_new_with_func (dummy_task_func, NULL, cancellable); } diff --git a/src-ng/nautilus-task.h b/src-ng/nautilus-task.h index 86440b351..8e3281b66 100644 --- a/src-ng/nautilus-task.h +++ b/src-ng/nautilus-task.h @@ -19,27 +19,136 @@ #ifndef NAUTILUS_TASK_H_INCLUDED #define NAUTILUS_TASK_H_INCLUDED +#include "nautilus-scheduler.h" + #include #include #define NAUTILUS_TYPE_TASK (nautilus_task_get_type ()) -G_DECLARE_DERIVABLE_TYPE (NautilusTask, nautilus_task, - NAUTILUS, TASK, - GObject) +G_DECLARE_FINAL_TYPE (NautilusTask, nautilus_task, NAUTILUS, TASK, GObject) + +/** + * NautilusTaskFunc: + * @task: a #NautilusTask instance + * @task_data: (nullable): task data + */ +typedef void (*NautilusTaskFunc) (NautilusTask *task, + gpointer task_data); -typedef void (*NautilusTaskCallback) (NautilusTask *task, - gpointer user_data); +/** + * nautilus_task_get_main_context: + * @task: an initialized #NautilusTask + * + * Returns: (nullable) (transfer full): the main context set or %NULL + */ +GMainContext *nautilus_task_get_main_context (NautilusTask *task); +/** + * nautilus_task_set_main_context: + * @task: an initialized #NautilusTask + * @context: (transfer full): the main context + */ +void nautilus_task_set_main_context (NautilusTask *task, + GMainContext *context); -struct _NautilusTaskClass -{ - GObjectClass parent_class; +/** + * nautilus_task_add_callback: + * @task: an initialized #NautilusTask + * @callback: the function to call when @task completes + * @user_data: (nullable): additional data to pass to @callback + */ +void nautilus_task_add_callback (NautilusTask *task, + NautilusTaskFunc callback, + gpointer user_data); - void (*execute) (NautilusTask *task); -}; +/** + * nautilus_task_complete: + * @task: an initialized #NautilusTask + */ +void nautilus_task_complete (NautilusTask *task); +/** + * nautilus_task_get_result: + * @task: an initialized #NautilusTask + * + * Returns: (nullable) (transfer full): the set result or %NULL + */ +GValue *nautilus_task_get_result (NautilusTask *task); +/** + * nautilus_task_set_result: + * @task: an initialized #NautilusTask + * @type: the #GType of @result + * @result: the result + */ +void nautilus_task_set_result (NautilusTask *task, + GType type, + gpointer result); + +/** + * nautilus_task_get_error: + * @task: an initialized #NautilusTask + * + * Returns: (nullable) (transfer full): the set #GError or %NULL + */ +GError *nautilus_task_get_error (NautilusTask *task); +/** + * nautilus_task_set_error: + * @task: an initialized #NautilusTask + * @error: (transfer full): a #GError + */ +void nautilus_task_set_error (NautilusTask *task, + GError *error); + +/** + * nautilus_task_set_scheduler: + * @task: an initialized #NautilusTask + * @scheduler: (transfer full): the scheduler to use + */ +void nautilus_task_set_scheduler (NautilusTask *task, + NautilusScheduler *scheduler); + +/** + * nautilus_task_run: + * @task: an initialized #NautilusTask + * + * Schedules the task to be run asynchronously. + */ +void nautilus_task_run (NautilusTask *task); + +/** + * nautilus_task_get_cancellable: + * @task: an initialized #NautilusTask + * + * Returns: (nullable) (transfer full): a #GCancellable for @task + */ GCancellable *nautilus_task_get_cancellable (NautilusTask *task); -void nautilus_task_execute (NautilusTask *task); +/** + * nautilus_task_new_with_closure: + * @closure: (transfer full): the closure to invoke when executing + * @cancellable: (nullable) (transfer full): an initialized #GCancellable or %NULL + * + * Returns: a new #NautilusTask instance + */ +NautilusTask *nautilus_task_new_with_closure (GClosure *closure, + GCancellable *cancellable); +/** + * nautilus_task_new_with_func: + * @func: the function to call when executing + * @func_data: (nullable): data to pass to @func + * @cancellable: (nullable) (transfer full): an initialized #GCancellable or %NULL + * + * Returns: a new #NautilusTask instance + */ +NautilusTask *nautilus_task_new_with_func (NautilusTaskFunc func, + gpointer func_data, + GCancellable *cancellable); +/** + * nautilus_task_new: + * @cancellable: (nullable) (transfer full): an initialized #GCancellable or %NULL + * + * Returns: a new #NautilusTask instance + */ +NautilusTask *nautilus_task_new (GCancellable *cancellable); #endif diff --git a/src-ng/nautilus-tasks.c b/src-ng/nautilus-tasks.c new file mode 100644 index 000000000..518a64bca --- /dev/null +++ b/src-ng/nautilus-tasks.c @@ -0,0 +1,235 @@ +/* Copyright (C) 2017 Ernestas Kulik + * + * 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 . + */ + +#include "nautilus-tasks.h" + +#include "nautilus-file-changes.h" + +#include + +#ifndef GNOME_DESKTOP_USE_UNSTABLE_API +#define GNOME_DESKTOP_USE_UNSTABLE_API +#endif + +#include + +const char *const DEFAULT_ATTRIBUTES = "standard::*," + "access::*," + "mountable::*," + "time::*," + "unix::*," + "owner::*," + "selinux::*," + "thumbnail::*," + "id::filesystem," + "trash::orig-path," + "trash::deletion-date," + "metadata::*," + "recent::*"; + +void +nautilus_enumerate_children_task_func (NautilusTask *task, + gpointer data) +{ + GFile *location; + g_autoptr (GCancellable) cancellable = NULL; + GError *error = NULL; + g_autoptr (GFileEnumerator) enumerator = NULL; + GHashTable *hash_table; + GFileInfo *info; + + location = data; + cancellable = nautilus_task_get_cancellable (task); + enumerator = g_file_enumerate_children (location, DEFAULT_ATTRIBUTES, + G_FILE_QUERY_INFO_NONE, cancellable, &error); + + if (error != NULL) + { + nautilus_task_set_error (task, error); + nautilus_task_complete (task); + + return; + } + + hash_table = g_hash_table_new_full (g_file_hash, (GEqualFunc) g_file_equal, + g_object_unref, g_object_unref); + + do + { + GFile *child; + + info = g_file_enumerator_next_file (enumerator, cancellable, &error); + + if (error != NULL) + { + g_hash_table_destroy (hash_table); + + nautilus_task_set_error (task, error); + nautilus_task_complete (task); + + return; + } + + if (info != NULL) + { + child = g_file_enumerator_get_child (enumerator, info); + + g_assert (g_hash_table_insert (hash_table, child, info)); + } + } while (info != NULL); + + nautilus_task_set_result (task, G_TYPE_HASH_TABLE, hash_table); + nautilus_task_complete (task); +} + +void +nautilus_load_pixbuf_func (NautilusTask *task, + gpointer task_data) +{ + GError *error = NULL; + GdkPixbuf *pixbuf; + + pixbuf = gdk_pixbuf_new_from_file (task_data, &error); + + nautilus_task_set_error (task, error); + nautilus_task_set_result (task, GDK_TYPE_PIXBUF, pixbuf); + nautilus_task_complete (task); +} + +void +nautilus_rename_task_func (NautilusTask *task, + gpointer task_data) +{ + GHashTableIter iter; + gpointer key; + gpointer value; + g_autoptr (GCancellable) cancellable = NULL; + GError *error = NULL; + + g_hash_table_iter_init (&iter, (GHashTable *) task_data); + + while (g_hash_table_iter_next (&iter, &key, &value)) + { + GFile *location_from; + GFile *location_to; + + location_from = G_FILE (key); + location_to = g_file_set_display_name (location_from, + (const gchar *) value, + cancellable, &error); + + if (location_to != NULL) + { + nautilus_notify_file_renamed (location_from, location_to); + } + else + { + } + } + + nautilus_task_complete (task); +} + +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; +} + +void +nautilus_thumbnail_task_func (NautilusTask *task, + gpointer task_data) +{ + GFile *location; + GnomeDesktopThumbnailFactory *thumbnail_factory; + g_autofree gchar *uri = NULL; + g_autoptr (GFileInfo) file_info = NULL; + const gchar *content_type; + guint64 mtime; + GdkPixbuf *pixbuf; + + location = task_data; + 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)) + { + nautilus_task_complete (task); + return; + } + + 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); + } + + nautilus_task_set_result (task, GDK_TYPE_PIXBUF, g_object_ref (pixbuf)); + nautilus_task_complete (task); +} + +void +nautilus_query_info_func (NautilusTask *task, + gpointer task_data) +{ + g_autoptr (GCancellable) cancellable = NULL; + GError *error = NULL; + GFileInfo *info; + + cancellable = nautilus_task_get_cancellable (task); + info = g_file_query_info (task_data, + DEFAULT_ATTRIBUTES, + G_FILE_QUERY_INFO_NONE, + cancellable, + &error); + + nautilus_task_set_error (task, error); + nautilus_task_set_result (task, G_TYPE_FILE_INFO, info); + nautilus_task_complete (task); +} diff --git a/src-ng/nautilus-tasks.h b/src-ng/nautilus-tasks.h new file mode 100644 index 000000000..3ead61586 --- /dev/null +++ b/src-ng/nautilus-tasks.h @@ -0,0 +1,35 @@ +/* Copyright (C) 2017 Ernestas Kulik + * + * 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 . + */ + +#ifndef NAUTILUS_TASKS_H_INCLUDED +#define NAUTILUS_TASKS_H_INCLUDED + +#include "nautilus-task.h" + +void nautilus_enumerate_children_task_func (NautilusTask *task, + gpointer task_data); +void nautilus_load_pixbuf_func (NautilusTask *task, + gpointer task_data); +void nautilus_rename_task_func (NautilusTask *task, + gpointer task_data); +void nautilus_thumbnail_task_func (NautilusTask *task, + gpointer task_data); +void nautilus_query_info_func (NautilusTask *task, + gpointer task_data); + +#endif diff --git a/src-ng/tasks/nautilus-attribute-task.c b/src-ng/tasks/nautilus-attribute-task.c deleted file mode 100644 index 9d21517c9..000000000 --- a/src-ng/tasks/nautilus-attribute-task.c +++ /dev/null @@ -1,126 +0,0 @@ -/* Copyright (C) 2017 Ernestas Kulik - * - * 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 . - */ - -#include "nautilus-attribute-task.h" - -#include "nautilus-marshallers.h" -#include "nautilus-task-private.h" - -struct _NautilusAttributeTask -{ - NautilusTask parent_instance; - - GFile *file; - const char *attributes; - GFileQueryInfoFlags flags; -} NautilusAttributeTaskPrivate; - -G_DEFINE_TYPE (NautilusAttributeTask, nautilus_attribute_task, - NAUTILUS_TYPE_TASK) - -enum -{ - FINISHED, - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL] = { 0 }; - -static void -finalize (GObject *object) -{ - NautilusAttributeTask *self; - - self = NAUTILUS_ATTRIBUTE_TASK (object); - - g_clear_object (&self->file); - g_clear_pointer (&self->attributes, g_free); - - G_OBJECT_CLASS (nautilus_attribute_task_parent_class)->finalize (object); -} - -static void -execute (NautilusTask *task) -{ - NautilusAttributeTask *self; - g_autoptr (GCancellable) cancellable = NULL; - GError *error = NULL; - GFileInfo *info; - - self = NAUTILUS_ATTRIBUTE_TASK (task); - cancellable = nautilus_task_get_cancellable (task); - info = g_file_query_info (self->file, - self->attributes, - self->flags, - cancellable, - &error); - - nautilus_task_emit_signal_in_main_context (task, signals[FINISHED], 0, - self->file, info, error); -} - -static void -nautilus_attribute_task_class_init (NautilusAttributeTaskClass *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_BOXED, - G_TYPE_NONE, - 3, - G_TYPE_FILE, G_TYPE_FILE_INFO, G_TYPE_ERROR); - -} - -static void -nautilus_attribute_task_init (NautilusAttributeTask *self) -{ -} - -NautilusTask * -nautilus_attribute_task_new (GFile *file, - const char *attributes, - GFileQueryInfoFlags flags, - GCancellable *cancellable) -{ - NautilusAttributeTask *instance; - - g_return_val_if_fail (G_IS_FILE (file), NULL); - g_return_val_if_fail (attributes != NULL, NULL); - - instance = g_object_new (NAUTILUS_TYPE_ATTRIBUTE_TASK, - "cancellable", cancellable, - NULL); - - instance->file = g_object_ref (file); - instance->attributes = g_strdup (attributes); - instance->flags = flags; - - return NAUTILUS_TASK (instance); -} diff --git a/src-ng/tasks/nautilus-attribute-task.h b/src-ng/tasks/nautilus-attribute-task.h deleted file mode 100644 index c2d5848e2..000000000 --- a/src-ng/tasks/nautilus-attribute-task.h +++ /dev/null @@ -1,37 +0,0 @@ -/* Copyright (C) 2017 Ernestas Kulik - * - * 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 . - */ - -#ifndef NAUTILUS_ATTRIBUTE_TASK_H_INCLUDED -#define NAUTILUS_ATTRIBUTE_TASK_H_INCLUDED - -#include "nautilus-task.h" - -#include - -#define NAUTILUS_TYPE_ATTRIBUTE_TASK (nautilus_attribute_task_get_type ()) - -G_DECLARE_FINAL_TYPE (NautilusAttributeTask, nautilus_attribute_task, - NAUTILUS, ATTRIBUTE_TASK, - NautilusTask) - -NautilusTask *nautilus_attribute_task_new (GFile *file, - const char *attributes, - GFileQueryInfoFlags flags, - GCancellable *cancellable); - -#endif diff --git a/src-ng/tasks/nautilus-enumerate-children-task.c b/src-ng/tasks/nautilus-enumerate-children-task.c deleted file mode 100644 index 77d9a2829..000000000 --- a/src-ng/tasks/nautilus-enumerate-children-task.c +++ /dev/null @@ -1,142 +0,0 @@ -/* Copyright (C) 2017 Ernestas Kulik - * - * 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 . - */ - -#include "nautilus-enumerate-children-task.h" - -#include "nautilus-marshallers.h" -#include "nautilus-task-private.h" - -struct _NautilusEnumerateChildrenTask -{ - NautilusTask parent_instance; - - GFile *file; - const char *attributes; - GFileQueryInfoFlags flags; -}; - -G_DEFINE_TYPE (NautilusEnumerateChildrenTask, nautilus_enumerate_children_task, - NAUTILUS_TYPE_TASK) - -enum -{ - FINISHED, - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL] = { 0 }; - -static void -execute (NautilusTask *task) -{ - NautilusEnumerateChildrenTask *self; - g_autoptr (GCancellable) cancellable = NULL; - GError *error = NULL; - g_autoptr (GFileEnumerator) enumerator = NULL; - GHashTable *hash_table; - GFileInfo *info; - - self = NAUTILUS_ENUMERATE_CHILDREN_TASK (task); - cancellable = nautilus_task_get_cancellable (NAUTILUS_TASK (self)); - enumerator = g_file_enumerate_children (self->file, self->attributes, - self->flags, cancellable, &error); - - if (error != NULL) - { - nautilus_task_emit_signal_in_main_context (task, - signals[FINISHED], 0, - self->file, NULL, error); - } - - hash_table = g_hash_table_new_full (g_file_hash, (GEqualFunc) g_file_equal, - g_object_unref, g_object_unref); - - do - { - GFile *child; - - info = g_file_enumerator_next_file (enumerator, cancellable, &error); - - if (error != NULL) - { - g_hash_table_destroy (hash_table); - - nautilus_task_emit_signal_in_main_context (task, - signals[FINISHED], 0, - self->file, NULL, error); - - return; - } - - if (info != NULL) - { - child = g_file_enumerator_get_child (enumerator, info); - - g_assert (g_hash_table_insert (hash_table, child, info)); - } - } while (info != NULL); - - nautilus_task_emit_signal_in_main_context (task, signals[FINISHED], 0, - self->file, hash_table, error); -} - -static void -nautilus_enumerate_children_task_class_init (NautilusEnumerateChildrenTaskClass *klass) -{ - NautilusTaskClass *task_class; - - task_class = NAUTILUS_TASK_CLASS (klass); - - 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_BOXED_BOXED, - G_TYPE_NONE, - 3, - G_TYPE_FILE, G_TYPE_HASH_TABLE, G_TYPE_ERROR); -} - -static void -nautilus_enumerate_children_task_init (NautilusEnumerateChildrenTask *self) -{ -} - -NautilusTask * -nautilus_enumerate_children_task_new (GFile *file, - const char *attributes, - GFileQueryInfoFlags flags, - GCancellable *cancellable) -{ - NautilusEnumerateChildrenTask *instance; - - g_return_val_if_fail (G_IS_FILE (file), NULL); - g_return_val_if_fail (attributes != NULL, NULL); - - instance = g_object_new (NAUTILUS_TYPE_ENUMERATE_CHILDREN_TASK, - "cancellable", cancellable, - NULL); - - instance->file = g_object_ref (file); - instance->attributes = g_strdup (attributes); - instance->flags = flags; - - return NAUTILUS_TASK (instance); -} diff --git a/src-ng/tasks/nautilus-enumerate-children-task.h b/src-ng/tasks/nautilus-enumerate-children-task.h deleted file mode 100644 index f43887c31..000000000 --- a/src-ng/tasks/nautilus-enumerate-children-task.h +++ /dev/null @@ -1,38 +0,0 @@ -/* Copyright (C) 2017 Ernestas Kulik - * - * 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 . - */ - -#ifndef NAUTILUS_ENUMERATE_CHILDREN_TASK_H_INCLUDED -#define NAUTILUS_ENUMERATE_CHILDREN_TASK_H_INCLUDED - -#include "nautilus-task.h" - -#include - -#define NAUTILUS_TYPE_ENUMERATE_CHILDREN_TASK (nautilus_enumerate_children_task_get_type ()) - -G_DECLARE_FINAL_TYPE (NautilusEnumerateChildrenTask, - nautilus_enumerate_children_task, - NAUTILUS, ENUMERATE_CHILDREN_TASK, - NautilusTask) - -NautilusTask *nautilus_enumerate_children_task_new (GFile *file, - const char *attributes, - GFileQueryInfoFlags flags, - GCancellable *cancellable); - -#endif diff --git a/src-ng/tasks/nautilus-rename-task.c b/src-ng/tasks/nautilus-rename-task.c deleted file mode 100644 index 350d1089e..000000000 --- a/src-ng/tasks/nautilus-rename-task.c +++ /dev/null @@ -1,150 +0,0 @@ -/* Copyright (C) 2017 Ernestas Kulik - * - * 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 . - */ - -#include "nautilus-rename-task.h" - -#include "nautilus-file-changes.h" -#include "nautilus-task-private.h" - -#include - -struct _NautilusRenameTask -{ - NautilusTask parent_instance; - - GHashTable *targets; -}; - -G_DEFINE_TYPE (NautilusRenameTask, nautilus_rename_task, NAUTILUS_TYPE_TASK) - -enum -{ - FINISHED, - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL] = { 0 }; - -static void -finalize (GObject *object) -{ - NautilusRenameTask *self; - - self = NAUTILUS_RENAME_TASK (object); - - g_hash_table_destroy (self->targets); - - G_OBJECT_CLASS (nautilus_rename_task_parent_class)->finalize (object); -} - -static void -execute (NautilusTask *task) -{ - NautilusRenameTask *self; - GHashTableIter iter; - gpointer key; - gpointer value; - g_autoptr (GCancellable) cancellable = NULL; - GError *error = NULL; - - self = NAUTILUS_RENAME_TASK (task); - cancellable = nautilus_task_get_cancellable (task); - - g_hash_table_iter_init (&iter, self->targets); - - while (g_hash_table_iter_next (&iter, &key, &value)) - { - g_autoptr (GFile) location_from = NULL; - g_autoptr (GFile) location_to = NULL; - - location_from = G_FILE (key); - g_message ("Renaming GFile %p", - (gpointer) location_from); - location_to = g_file_set_display_name (location_from, - (const gchar *) value, - cancellable, &error); - - if (location_to != NULL) - { - g_message ("GFile %p renamed to %p", - (gpointer) location_from, - (gpointer) location_to); - nautilus_notify_file_renamed (location_from, location_to); - } - else - { - g_message ("Renaming GFile %p failed: %s", - (gpointer) location_from, - error->message); - } - } - - /* This will typically be handled before the file and its parent - * are notified of the changes. - */ - nautilus_task_emit_signal_in_main_context (task, signals[FINISHED], 0); -} - -static void -nautilus_rename_task_class_init (NautilusRenameTaskClass *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, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, - 0); -} - -static void -nautilus_rename_task_init (NautilusRenameTask *self) -{ - self->targets = g_hash_table_new_full (g_file_hash, (GEqualFunc) g_file_equal, - g_object_unref, g_free); -} - -void -nautilus_rename_task_add_target (NautilusRenameTask *task, - GFile *file, - const gchar *name) -{ - g_return_if_fail (NAUTILUS_IS_RENAME_TASK (task)); - g_return_if_fail (!g_hash_table_contains (task->targets, file)); - g_return_if_fail (G_IS_FILE (file)); - g_return_if_fail (name != NULL); - - (void) g_hash_table_insert (task->targets, - g_object_ref (file), g_strdup (name)); -} - -NautilusTask * -nautilus_rename_task_new (void) -{ - return g_object_new (NAUTILUS_TYPE_RENAME_TASK, NULL); -} diff --git a/src-ng/tasks/nautilus-rename-task.h b/src-ng/tasks/nautilus-rename-task.h deleted file mode 100644 index 9ffcaf02a..000000000 --- a/src-ng/tasks/nautilus-rename-task.h +++ /dev/null @@ -1,35 +0,0 @@ -/* Copyright (C) 2017 Ernestas Kulik - * - * 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 . - */ - -#ifndef NAUTILUS_RENAME_TASK_H_INCLUDED -#define NAUTILUS_RENAME_TASK_H_INCLUDED - -#include "nautilus-task.h" - -#define NAUTILUS_TYPE_RENAME_TASK (nautilus_rename_task_get_type ()) - -G_DECLARE_FINAL_TYPE (NautilusRenameTask, nautilus_rename_task, - NAUTILUS, RENAME_TASK, NautilusTask) - -void nautilus_rename_task_add_target (NautilusRenameTask *task, - GFile *file, - const gchar *name); - -NautilusTask *nautilus_rename_task_new (void); - -#endif diff --git a/src-ng/tasks/nautilus-thumbnail-task.c b/src-ng/tasks/nautilus-thumbnail-task.c deleted file mode 100644 index a5aaa613b..000000000 --- a/src-ng/tasks/nautilus-thumbnail-task.c +++ /dev/null @@ -1,287 +0,0 @@ -/* Copyright (C) 2017 Ernestas Kulik - * - * 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 . - */ - -#include "nautilus-thumbnail-task.h" - -#include "nautilus-marshallers.h" -#include "nautilus-task-private.h" - -#include - -#ifndef GNOME_DESKTOP_USE_UNSTABLE_API -#define GNOME_DESKTOP_USE_UNSTABLE_API -#endif - -#include - -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); -} diff --git a/src-ng/tasks/nautilus-thumbnail-task.h b/src-ng/tasks/nautilus-thumbnail-task.h deleted file mode 100644 index 1c95bd09e..000000000 --- a/src-ng/tasks/nautilus-thumbnail-task.h +++ /dev/null @@ -1,34 +0,0 @@ -/* Copyright (C) 2017 Ernestas Kulik - * - * 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 . - */ - -#ifndef NAUTILUS_THUMBNAIL_TASK_H_INCLUDED -#define NAUTILUS_THUMBNAIL_TASK_H_INCLUDED - -#include "nautilus-task.h" - -#include - -#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 -- cgit v1.2.1