diff options
-rw-r--r-- | src-ng/main.c | 64 | ||||
-rw-r--r-- | src-ng/meson.build | 4 | ||||
-rw-r--r-- | src-ng/nautilus-cache.c | 259 | ||||
-rw-r--r-- | src-ng/nautilus-cache.h | 59 | ||||
-rw-r--r-- | src-ng/nautilus-directory.c | 160 | ||||
-rw-r--r-- | src-ng/nautilus-directory.h | 10 | ||||
-rw-r--r-- | src-ng/nautilus-file.c | 99 | ||||
-rw-r--r-- | src-ng/nautilus-file.h | 9 | ||||
-rw-r--r-- | src-ng/nautilus-marshallers.list | 1 | ||||
-rw-r--r-- | src-ng/nautilus-task-manager.c | 2 | ||||
-rw-r--r-- | src-ng/tasks/nautilus-attribute-task.c | 98 | ||||
-rw-r--r-- | src-ng/tasks/nautilus-enumerate-children-task.c | 141 | ||||
-rw-r--r-- | src-ng/tasks/nautilus-enumerate-children-task.h | 38 |
13 files changed, 830 insertions, 114 deletions
diff --git a/src-ng/main.c b/src-ng/main.c index f5474bb79..49a328189 100644 --- a/src-ng/main.c +++ b/src-ng/main.c @@ -14,12 +14,51 @@ got_info (NautilusFile *file, { g_message ("Got info for %p", (gpointer) file); - g_message ("\tDisplay name: %s\n", + g_message ("\tDisplay name: %s", g_file_info_get_display_name (info)); + g_message ("\tFile is directory: %s\n", + NAUTILUS_IS_DIRECTORY (file)? "yes" : "no"); g_object_unref (info); - g_main_loop_quit ((GMainLoop *) user_data); + 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_message ("Got children for %p", (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); } int @@ -43,9 +82,7 @@ main (int argc, g_message ("Creating NautilusFile"); file = nautilus_file_new (location); - g_message ("\tGot %p", (gpointer) file); - g_message ("\tFile is directory: %s\n", - NAUTILUS_IS_DIRECTORY (file)? "yes" : "no"); + g_message ("\tGot %p\n", (gpointer) file); g_message ("Creating another NautilusFile for the same location"); duplicate_file = nautilus_file_new (location); @@ -55,7 +92,22 @@ main (int argc, loop = g_main_loop_new (NULL, TRUE); - nautilus_file_query_info (file, NULL, got_info, loop); + 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); diff --git a/src-ng/meson.build b/src-ng/meson.build index 8f1fec6ee..aa6288410 100644 --- a/src-ng/meson.build +++ b/src-ng/meson.build @@ -8,6 +8,10 @@ nautilus_ng_sources = ['nautilus-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', 'main.c'] nautilus_ng_dependencies = [gio, glib] diff --git a/src-ng/nautilus-cache.c b/src-ng/nautilus-cache.c new file mode 100644 index 000000000..f27a6d904 --- /dev/null +++ b/src-ng/nautilus-cache.c @@ -0,0 +1,259 @@ +/* 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 <http://www.gnu.org/licenses/>. + */ + +#include "nautilus-cache.h" + +typedef struct +{ + gpointer value; + GDestroyNotify destroy_func; + + NautilusCacheState state; + + GMutex mutex; +} CacheItemDetails; + +struct _NautilusCache +{ + GObject parent_instance; + + GHashTable *items; +}; + +G_DEFINE_TYPE (NautilusCache, nautilus_cache, G_TYPE_OBJECT) + +static CacheItemDetails * +cache_item_details_new (GDestroyNotify destroy_func) +{ + CacheItemDetails *details; + + details = g_new0 (CacheItemDetails, 1); + + details->destroy_func = destroy_func; + + g_mutex_init (&details->mutex); + + return details; +} + +static void +cache_item_details_destroy (CacheItemDetails *details) +{ + if (details->destroy_func != NULL) + { + details->destroy_func (details->value); + } + g_mutex_clear (&details->mutex); + g_free (details); +} + +static void +finalize (GObject *object) +{ + NautilusCache *self; + + self = NAUTILUS_CACHE (object); + + g_hash_table_destroy (self->items); + + G_OBJECT_CLASS (nautilus_cache_parent_class)->finalize (object); +} + +static void +nautilus_cache_class_init (NautilusCacheClass *klass) +{ + GObjectClass *object_class; + + object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = finalize; +} + +static void +nautilus_cache_init (NautilusCache *self) +{ + self->items = + g_hash_table_new_full (g_direct_hash, g_direct_equal, + NULL, + (GDestroyNotify) cache_item_details_destroy); +} + +NautilusCacheState +nautilus_cache_item_get_state (NautilusCache *cache, + gssize item) +{ + CacheItemDetails *details; + + g_return_val_if_fail (NAUTILUS_IS_CACHE (cache), NAUTILUS_CACHE_INVALID); + g_return_val_if_fail (g_hash_table_contains (cache->items, + GINT_TO_POINTER (item)), + NAUTILUS_CACHE_INVALID); + + details = g_hash_table_lookup (cache->items, GINT_TO_POINTER (item)); + + return details->state; +} + +void +nautilus_cache_item_invalidate (NautilusCache *cache, + gssize item, + gboolean destroy) +{ + CacheItemDetails *details; + + g_return_if_fail (NAUTILUS_IS_CACHE (cache)); + g_return_if_fail (g_hash_table_contains (cache->items, + GINT_TO_POINTER (item))); + + details = g_hash_table_lookup (cache->items, GINT_TO_POINTER (item)); + + g_mutex_lock (&details->mutex); + + /* There might be cases where the cache holding a ref on an object is a + * problem. + */ + if (destroy && + details->destroy_func != NULL && G_LIKELY (details->value != NULL)) + { + details->destroy_func (details->value); + } + + details->state = NAUTILUS_CACHE_INVALID; + + g_mutex_unlock (&details->mutex); +} + +void +nautilus_cache_item_set_pending (NautilusCache *cache, + gssize item) +{ + CacheItemDetails *details; + + g_return_if_fail (NAUTILUS_IS_CACHE (cache)); + g_return_if_fail (g_hash_table_contains (cache->items, + GINT_TO_POINTER (item))); + + details = g_hash_table_lookup (cache->items, GINT_TO_POINTER (item)); + + g_mutex_lock (&details->mutex); + + /* This whole method feels quite clunky. + * Changing the state from valid to pending should probably be treated + * as programmer error (or a bug). + */ + g_warn_if_fail (details->state == NAUTILUS_CACHE_INVALID); + if (details->state != NAUTILUS_CACHE_INVALID) + { + g_mutex_unlock (&details->mutex); + return; + } + + details->state = NAUTILUS_CACHE_PENDING; + + g_mutex_unlock (&details->mutex); +} + +gpointer +nautilus_cache_item_get_value (NautilusCache *cache, + gssize item, + NautilusCopyFunc copy_func) +{ + CacheItemDetails *details; + + g_return_val_if_fail (NAUTILUS_IS_CACHE (cache), NULL); + g_return_val_if_fail (g_hash_table_contains (cache->items, + GINT_TO_POINTER (item)), + NULL); + + details = g_hash_table_lookup (cache->items, GINT_TO_POINTER (item)); + + if (copy_func == NULL) + { + return details->value; + } + else + { + gpointer ret; + + g_mutex_lock (&details->mutex); + + ret = copy_func (details->value); + + g_mutex_unlock (&details->mutex); + + return ret; + } +} + +void +nautilus_cache_item_set_value (NautilusCache *cache, + gssize item, + gpointer value) +{ + CacheItemDetails *details; + + g_return_if_fail (NAUTILUS_IS_CACHE (cache)); + g_return_if_fail (g_hash_table_contains (cache->items, + GINT_TO_POINTER (item))); + + details = g_hash_table_lookup (cache->items, GINT_TO_POINTER (item)); + + g_mutex_lock (&details->mutex); + + /* We’ll treat this as a cancellation of the update. */ + if (details->state != NAUTILUS_CACHE_PENDING) + { + g_mutex_unlock (&details->mutex); + + return; + } + + if (details->destroy_func != NULL && G_LIKELY (details->value != NULL)) + { + g_clear_pointer (&details->value, details->destroy_func); + } + + details->value = value; + details->state = NAUTILUS_CACHE_VALID; + + g_mutex_unlock (&details->mutex); +} + +gssize +nautilus_cache_install_item (NautilusCache *cache, + GDestroyNotify destroy_func) +{ + CacheItemDetails *details; + guint size; + + g_return_val_if_fail (NAUTILUS_IS_CACHE (cache), -1); + + details = cache_item_details_new (destroy_func); + size = g_hash_table_size (cache->items); + + g_hash_table_insert (cache->items, GUINT_TO_POINTER (size), details); + + /* This is a bit evil, but is unlikely to cause problems… ever. */ + return (gssize) size; +} + +NautilusCache * +nautilus_cache_new (void) +{ + return g_object_new (NAUTILUS_TYPE_CACHE, NULL); +} diff --git a/src-ng/nautilus-cache.h b/src-ng/nautilus-cache.h new file mode 100644 index 000000000..eade4ee89 --- /dev/null +++ b/src-ng/nautilus-cache.h @@ -0,0 +1,59 @@ +/* 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 <http://www.gnu.org/licenses/>. + */ + +#include <glib.h> +#include <glib-object.h> + +#define NAUTILUS_TYPE_CACHE (nautilus_cache_get_type ()) + +G_DECLARE_FINAL_TYPE (NautilusCache, nautilus_cache, NAUTILUS, CACHE, GObject) + +/* GCopyFunc has too many parameters for our taste. */ +typedef gpointer (*NautilusCopyFunc) (gpointer data); +#define NAUTILUS_COPY_FUNC(x) ((NautilusCopyFunc) x) + +typedef enum +{ + NAUTILUS_CACHE_INVALID, + NAUTILUS_CACHE_PENDING, + NAUTILUS_CACHE_VALID +} NautilusCacheState; + +void nautilus_cache_invalidate_all (NautilusCache *cache); + +NautilusCacheState nautilus_cache_item_get_state (NautilusCache *cache, + gssize item); + +void nautilus_cache_item_invalidate (NautilusCache *cache, + gssize item, + gboolean destroy); +void nautilus_cache_item_set_pending (NautilusCache *cache, + gssize item); + +gpointer nautilus_cache_item_get_value (NautilusCache *cache, + gssize item, + NautilusCopyFunc copy_func); +void nautilus_cache_item_set_value (NautilusCache *cache, + gssize item, + gpointer value); + +/* TODO: TTL for highly volatile items? */ +gssize nautilus_cache_install_item (NautilusCache *cache, + GDestroyNotify destroy_func); + +NautilusCache *nautilus_cache_new (void); diff --git a/src-ng/nautilus-directory.c b/src-ng/nautilus-directory.c index e509265a2..9ded88431 100644 --- a/src-ng/nautilus-directory.c +++ b/src-ng/nautilus-directory.c @@ -18,7 +18,24 @@ #include "nautilus-directory.h" -G_DEFINE_TYPE (NautilusDirectory, nautilus_directory, NAUTILUS_TYPE_FILE) +#include "nautilus-cache.h" +#include "nautilus-task-manager.h" +#include "tasks/nautilus-enumerate-children-task.h" + +enum +{ + CHILDREN, + N_ITEMS +}; + +typedef struct +{ + NautilusCache *cache; + gssize cache_items[N_ITEMS]; +} NautilusDirectoryPrivate; + +G_DEFINE_TYPE_WITH_PRIVATE (NautilusDirectory, nautilus_directory, + NAUTILUS_TYPE_FILE) static void nautilus_directory_class_init (NautilusDirectoryClass *klass) @@ -26,8 +43,149 @@ nautilus_directory_class_init (NautilusDirectoryClass *klass) } static void +file_list_free (gpointer data) +{ + g_autoptr (GList) list = NULL; + + list = data; + + for (GList *i = list; i != NULL; i = i->next) + { + g_object_unref (i->data); + } +} + +static void nautilus_directory_init (NautilusDirectory *self) { + NautilusDirectoryPrivate *priv; + + priv = nautilus_directory_get_instance_private (self); + + priv->cache = nautilus_cache_new (); + priv->cache_items[CHILDREN] = + nautilus_cache_install_item (priv->cache, + (GDestroyNotify) file_list_free); +} + +typedef struct +{ + NautilusDirectory *directory; + + NautilusEnumerateChildrenCallback callback; + gpointer callback_data; +} EnumerateChildrenDetails; + +static void +create_file_list (gpointer key, + gpointer value, + gpointer user_data) +{ + GList **list; + + list = user_data; + + *list = g_list_prepend (*list, + nautilus_file_new_with_info (G_FILE (key), + G_FILE_INFO (value))); +} + +static void +on_enumerate_children_finished (NautilusEnumerateChildrenTask *task, + GFile *file, + GHashTable *files, + GError *error, + gpointer user_data) +{ + EnumerateChildrenDetails *details; + NautilusDirectoryPrivate *priv; + NautilusCacheState cache_state; + GList *children = NULL; + + details = user_data; + priv = nautilus_directory_get_instance_private (details->directory); + cache_state = nautilus_cache_item_get_state (priv->cache, + priv->cache_items[CHILDREN]); + + if (cache_state == NAUTILUS_CACHE_INVALID) + { + /* TODO: restart */ + return; + } + + g_hash_table_foreach (files, create_file_list, &children); + + nautilus_cache_item_set_value (priv->cache, priv->cache_items[CHILDREN], + children); + + details->callback (details->directory, g_list_copy (children), error, + details->callback_data); + + g_free (details); +} + +void +nautilus_directory_enumerate_children (NautilusDirectory *directory, + GCancellable *cancellable, + NautilusEnumerateChildrenCallback callback, + gpointer user_data) +{ + NautilusDirectoryPrivate *priv; + 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)); + + priv = nautilus_directory_get_instance_private (directory); + cache_state = nautilus_cache_item_get_state (priv->cache, + priv->cache_items[CHILDREN]); + + if (cache_state == NAUTILUS_CACHE_PENDING || + cache_state == NAUTILUS_CACHE_VALID) + { + callback (directory, + nautilus_cache_item_get_value (priv->cache, + priv->cache_items[CHILDREN], + (NautilusCopyFunc) g_list_copy), + NULL, user_data); + + return; + } + + nautilus_cache_item_set_pending (priv->cache, + 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); } NautilusFile * diff --git a/src-ng/nautilus-directory.h b/src-ng/nautilus-directory.h index be1c33a69..9743467bb 100644 --- a/src-ng/nautilus-directory.h +++ b/src-ng/nautilus-directory.h @@ -24,9 +24,19 @@ G_DECLARE_DERIVABLE_TYPE (NautilusDirectory, nautilus_directory, NAUTILUS, DIRECTORY, NautilusFile) +typedef void (*NautilusEnumerateChildrenCallback) (NautilusDirectory *directory, + GList *children, + GError *error, + gpointer user_data); + struct _NautilusDirectoryClass { NautilusFileClass parent_class; }; +void nautilus_directory_enumerate_children (NautilusDirectory *directory, + GCancellable *cancellable, + NautilusEnumerateChildrenCallback callback, + gpointer user_data); + NautilusFile *nautilus_directory_new (GFile *location); diff --git a/src-ng/nautilus-file.c b/src-ng/nautilus-file.c index 65692a83a..b19a1e287 100644 --- a/src-ng/nautilus-file.c +++ b/src-ng/nautilus-file.c @@ -18,25 +18,23 @@ #include "nautilus-file.h" +#include "nautilus-cache.h" #include "nautilus-directory.h" #include "nautilus-task-manager.h" #include "tasks/nautilus-attribute-task.h" -typedef enum +enum { - INVALID, - PENDING, - VALID -} CacheState; + INFO, + N_ITEMS +}; typedef struct { GFile *location; - GFileInfo *info; - CacheState info_state; - - GMutex cache_mutex; + NautilusCache *cache; + gssize cache_items[N_ITEMS]; } NautilusFilePrivate; G_DEFINE_TYPE_WITH_PRIVATE (NautilusFile, nautilus_file, G_TYPE_OBJECT) @@ -135,8 +133,6 @@ finalize (GObject *object) g_hash_table_remove (files, priv->location); g_mutex_unlock (&files_mutex); - g_mutex_clear (&priv->cache_mutex); - G_OBJECT_CLASS (nautilus_file_parent_class)->finalize (object); } @@ -166,9 +162,9 @@ nautilus_file_init (NautilusFile *self) priv = nautilus_file_get_instance_private (self); - priv->info = g_file_info_new (); - - g_mutex_init (&priv->cache_mutex); + priv->cache = nautilus_cache_new (); + priv->cache_items[INFO] = nautilus_cache_install_item (priv->cache, + g_object_unref); } typedef struct @@ -188,14 +184,21 @@ on_query_info_finished (NautilusAttributeTask *task, { QueryInfoDetails *details; NautilusFilePrivate *priv; + NautilusCacheState cache_state; details = data; priv = nautilus_file_get_instance_private (details->file); + cache_state = nautilus_cache_item_get_state (priv->cache, + priv->cache_items[INFO]); - g_mutex_lock (&priv->cache_mutex); - g_file_info_copy_into (info, priv->info); - priv->info_state = VALID; - g_mutex_unlock (&priv->cache_mutex); + if (cache_state == NAUTILUS_CACHE_INVALID) + { + /* TODO: restart */ + return; + } + + nautilus_cache_item_set_value (priv->cache, priv->cache_items[INFO], + info); details->callback (details->file, g_file_info_dup (info), error, details->callback_data); @@ -210,24 +213,41 @@ nautilus_file_query_info (NautilusFile *file, gpointer user_data) { NautilusFilePrivate *priv; + NautilusCacheState cache_state; g_autoptr (NautilusTask) task = NULL; QueryInfoDetails *details; g_autoptr (NautilusTaskManager) manager = NULL; + g_return_if_fail (NAUTILUS_IS_FILE (file)); + + g_debug ("%s: called for %p", __func__, (gpointer) file); + priv = nautilus_file_get_instance_private (file); + cache_state = nautilus_cache_item_get_state (priv->cache, + priv->cache_items[INFO]); - g_mutex_lock (&priv->cache_mutex); /* This is not the right thing to do if a cache update is pending. * A task reference could be stored and we could connect to the signal, * but there might be a better way. */ - if (priv->info_state == PENDING || priv->info_state == VALID) + if (cache_state == NAUTILUS_CACHE_PENDING || + cache_state == NAUTILUS_CACHE_VALID) { - g_mutex_unlock (&priv->cache_mutex); + GFileInfo *info; + + g_debug ("%s: info for %p is either pending or valid", + __func__, (gpointer) file); + + info = nautilus_cache_item_get_value (priv->cache, + priv->cache_items[INFO], + NAUTILUS_COPY_FUNC (g_file_info_dup)); + + callback (file, info, NULL, user_data); - callback (file, g_file_info_dup (priv->info), NULL, user_data); + return; } - g_mutex_unlock (&priv->cache_mutex); + + nautilus_cache_item_set_pending (priv->cache, priv->cache_items[INFO]); task = nautilus_attribute_task_new (priv->location, "standard::*," @@ -258,6 +278,39 @@ nautilus_file_query_info (NautilusFile *file, nautilus_task_manager_queue_task (manager, task); } +GFile * +nautilus_file_get_location (NautilusFile *file) +{ + NautilusFilePrivate *priv; + + g_return_val_if_fail (NAUTILUS_IS_FILE (file), NULL); + + priv = nautilus_file_get_instance_private (file); + + return g_object_ref (priv->location); +} + +NautilusFile * +nautilus_file_new_with_info (GFile *location, + GFileInfo *info) +{ + NautilusFile *instance; + NautilusFilePrivate *priv; + + g_return_val_if_fail (G_IS_FILE (location), NULL); + g_return_val_if_fail (G_IS_FILE_INFO (info), NULL); + + instance = nautilus_file_new (location); + priv = nautilus_file_get_instance_private (instance); + + /* Ergh. */ + nautilus_cache_item_set_pending (priv->cache, priv->cache_items[INFO]); + nautilus_cache_item_set_value (priv->cache, priv->cache_items[INFO], + info); + + return instance; +} + NautilusFile * nautilus_file_new (GFile *location) { diff --git a/src-ng/nautilus-file.h b/src-ng/nautilus-file.h index 7781f6e68..b0caaaf47 100644 --- a/src-ng/nautilus-file.h +++ b/src-ng/nautilus-file.h @@ -42,6 +42,13 @@ void nautilus_file_query_info (NautilusFile *file, NautilusFileInfoCallback callback, gpointer user_data); -NautilusFile *nautilus_file_new (GFile *location); +GFile *nautilus_file_get_location (NautilusFile *file); + +/* Overwrites the info if the file exists in cache. + * Used by NautilusDirectory when enumerating children. + */ +NautilusFile *nautilus_file_new_with_info (GFile *location, + GFileInfo *info); +NautilusFile *nautilus_file_new (GFile *location); #endif diff --git a/src-ng/nautilus-marshallers.list b/src-ng/nautilus-marshallers.list index 29f507b15..c53470021 100644 --- a/src-ng/nautilus-marshallers.list +++ b/src-ng/nautilus-marshallers.list @@ -1 +1,2 @@ VOID:OBJECT,OBJECT,BOXED +VOID:OBJECT,BOXED,BOXED diff --git a/src-ng/nautilus-task-manager.c b/src-ng/nautilus-task-manager.c index 037c7a481..17db97a34 100644 --- a/src-ng/nautilus-task-manager.c +++ b/src-ng/nautilus-task-manager.c @@ -65,6 +65,8 @@ finalize (GObject *object) 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 diff --git a/src-ng/tasks/nautilus-attribute-task.c b/src-ng/tasks/nautilus-attribute-task.c index ebc0ddd1a..11af3277a 100644 --- a/src-ng/tasks/nautilus-attribute-task.c +++ b/src-ng/tasks/nautilus-attribute-task.c @@ -22,11 +22,10 @@ struct _NautilusAttributeTask { - GObject parent_instance; + NautilusTask parent_instance; GFile *file; const char *attributes; - GFileQueryInfoFlags flags; } NautilusAttributeTaskPrivate; @@ -35,66 +34,13 @@ G_DEFINE_TYPE (NautilusAttributeTask, nautilus_attribute_task, enum { - PROP_FILE = 1, - PROP_ATTRIBUTES, - PROP_FLAGS, - N_PROPERTIES -}; - -enum -{ FINISHED, LAST_SIGNAL }; -static GParamSpec *properties[N_PROPERTIES] = { NULL }; static guint signals[LAST_SIGNAL] = { 0 }; static void -set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec) -{ - NautilusAttributeTask *self; - - self = NAUTILUS_ATTRIBUTE_TASK (object); - - switch (property_id) - { - case PROP_FILE: - { - if (G_UNLIKELY (self->file != NULL)) - { - g_clear_object (&self->file); - } - - self->file = g_value_dup_object (value); - } - break; - - case PROP_ATTRIBUTES: - { - g_free ((gpointer) self->attributes); - - self->attributes = g_value_dup_string (value); - } - break; - - case PROP_FLAGS: - { - self->flags = g_value_get_int (value); - } - break; - - default: - { - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - } - } -} - -static void finalize (GObject *object) { NautilusAttributeTask *self; @@ -138,29 +84,10 @@ nautilus_attribute_task_class_init (NautilusAttributeTaskClass *klass) object_class = G_OBJECT_CLASS (klass); task_class = NAUTILUS_TASK_CLASS (klass); - object_class->set_property = set_property; object_class->finalize = finalize; task_class->execute = execute; - properties[PROP_FILE] = - g_param_spec_object ("file", "File", "File", - G_TYPE_FILE, - G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE | G_PARAM_STATIC_NAME); - - properties[PROP_ATTRIBUTES] = - g_param_spec_string ("attributes", "Attributes", "Attributes", - NULL, - G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE | G_PARAM_STATIC_NAME); - - properties[PROP_FLAGS] = - g_param_spec_int ("flags", "Flags", "Flags", - G_FILE_QUERY_INFO_NONE, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, - G_FILE_QUERY_INFO_NONE, - G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE | G_PARAM_STATIC_NAME); - - g_object_class_install_properties (object_class, N_PROPERTIES, properties); - signals[FINISHED] = g_signal_new ("finished", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, @@ -175,9 +102,6 @@ nautilus_attribute_task_class_init (NautilusAttributeTaskClass *klass) static void nautilus_attribute_task_init (NautilusAttributeTask *self) { - self->file = NULL; - self->attributes = NULL; - self->flags = 0; } NautilusTask * @@ -186,10 +110,18 @@ nautilus_attribute_task_new (GFile *file, GFileQueryInfoFlags flags, GCancellable *cancellable) { - return g_object_new (NAUTILUS_TYPE_ATTRIBUTE_TASK, - "file", file, - "attributes", attributes, - "flags", flags, - "cancellable", cancellable, - NULL); + 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-enumerate-children-task.c b/src-ng/tasks/nautilus-enumerate-children-task.c new file mode 100644 index 000000000..ddb0c425e --- /dev/null +++ b/src-ng/tasks/nautilus-enumerate-children-task.c @@ -0,0 +1,141 @@ +/* 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 <http://www.gnu.org/licenses/>. + */ + +#include "nautilus-enumerate-children-task.h" + +#include "nautilus-marshallers.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; + NautilusTaskClass *klass; + 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)); + klass = NAUTILUS_TASK_CLASS (G_OBJECT_GET_CLASS (self)); + enumerator = g_file_enumerate_children (self->file, self->attributes, + self->flags, cancellable, &error); + + if (error != NULL) + { + klass->emit_signal_in_main_context (task, signals[FINISHED], + 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); + + klass->emit_signal_in_main_context (task, signals[FINISHED], + 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); + + klass->emit_signal_in_main_context (task, signals[FINISHED], + 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 new file mode 100644 index 000000000..2aa76ee0d --- /dev/null +++ b/src-ng/tasks/nautilus-enumerate-children-task.h @@ -0,0 +1,38 @@ +/* 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 <http://www.gnu.org/licenses/>. + */ + +#ifndef NAUTILUS_ENUMERATE_CHILDREN_TASK_H_INCLUDED +#define NAUTILUS_ENUMERATE_CHILDREN_TASK_H_INCLUDED + +#include "nautilus-task.h" + +#include <gio/gio.h> + +#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 |