diff options
author | Ernestas Kulik <ernestask@gnome.org> | 2017-07-08 17:03:04 +0300 |
---|---|---|
committer | Ernestas Kulik <ernestask@gnome.org> | 2017-08-17 18:54:05 +0300 |
commit | f6c05783eb1166404b87c5252fc6267af1d887fa (patch) | |
tree | 5043b87d6733d0bff3cecad10b8b8cbbad17eb23 | |
parent | 536175268afb7bf20f0771c570f602e9fbfcde78 (diff) | |
download | nautilus-f6c05783eb1166404b87c5252fc6267af1d887fa.tar.gz |
Yay for reinventing wheels
-rw-r--r-- | meson.build | 2 | ||||
-rw-r--r-- | src-ng/main.c | 59 | ||||
-rw-r--r-- | src-ng/meson.build | 21 | ||||
-rw-r--r-- | src-ng/nautilus-file.c | 242 | ||||
-rw-r--r-- | src-ng/nautilus-file.h | 47 | ||||
-rw-r--r-- | src-ng/nautilus-marshallers.list | 1 | ||||
-rw-r--r-- | src-ng/nautilus-task-manager.c | 115 | ||||
-rw-r--r-- | src-ng/nautilus-task-manager.h | 37 | ||||
-rw-r--r-- | src-ng/nautilus-task.c | 241 | ||||
-rw-r--r-- | src-ng/nautilus-task.h | 48 | ||||
-rw-r--r-- | src-ng/tasks/nautilus-attribute-task.c | 195 | ||||
-rw-r--r-- | src-ng/tasks/nautilus-attribute-task.h | 37 |
12 files changed, 1045 insertions, 0 deletions
diff --git a/meson.build b/meson.build index 2d3b39e33..92e4b4946 100644 --- a/meson.build +++ b/meson.build @@ -124,5 +124,7 @@ if get_option ('enable-nst-extension') subdir ('nautilus-sendto-extension') endif +subdir ('src-ng') + # Compile GSettings schemas when installing from source. meson.add_install_script ('build-aux/meson/postinstall.py') diff --git a/src-ng/main.c b/src-ng/main.c new file mode 100644 index 000000000..0a3ad0a60 --- /dev/null +++ b/src-ng/main.c @@ -0,0 +1,59 @@ +#include <stdlib.h> + +#include <glib.h> + +#include "nautilus-file.h" +#include "nautilus-task-manager.h" + +static void +got_info (NautilusFile *file, + GFileInfo *info, + GError *error, + gpointer user_data) +{ + g_message ("Got info for %p\n\tDisplay name: %s", + (gpointer) file, + g_file_info_get_display_name (info)); + + g_object_unref (info); + + g_main_loop_quit ((GMainLoop *) user_data); +} + +int +main (int argc, + char **argv) +{ + g_autoptr (NautilusTaskManager) manager = NULL; + g_autoptr (GFile) location = NULL; + g_autoptr (NautilusFile) file = NULL; + g_autoptr (NautilusFile) duplicate_file = NULL; + GMainLoop *loop; + + if (!(argc > 1)) + { + g_message ("No file provided, exiting"); + return EXIT_SUCCESS; + } + + manager = nautilus_task_manager_dup_singleton (); + location = g_file_new_for_commandline_arg (argv[1]); + + g_message ("Creating NautilusFile"); + file = nautilus_file_new (location); + g_message ("Got %p\n", (gpointer) file); + + g_message ("Creating another NautilusFile for the same location"); + duplicate_file = nautilus_file_new (location); + g_message ("Got %p, which is %s\n", + (gpointer) duplicate_file, + file == duplicate_file? "the same" : "not the same"); + + loop = g_main_loop_new (NULL, TRUE); + + nautilus_file_query_info (file, NULL, got_info, loop); + + g_main_loop_run (loop); + + return EXIT_SUCCESS; +} diff --git a/src-ng/meson.build b/src-ng/meson.build new file mode 100644 index 000000000..dbda07e75 --- /dev/null +++ b/src-ng/meson.build @@ -0,0 +1,21 @@ +nautilus_ng_sources = ['nautilus-task.c', + 'nautilus-task.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', + 'main.c'] + +nautilus_ng_dependencies = [gio, glib] + +nautilus_marshallers = gnome.genmarshal ('nautilus-marshallers', + sources: 'nautilus-marshallers.list', + prefix: 'nautilus_cclosure_marshal') + +nautilus_ng_sources += nautilus_marshallers + +nautilus_ng = executable ('nautilus-ng', nautilus_ng_sources, + dependencies: nautilus_ng_dependencies, + install: true) diff --git a/src-ng/nautilus-file.c b/src-ng/nautilus-file.c new file mode 100644 index 000000000..3b8c552cc --- /dev/null +++ b/src-ng/nautilus-file.c @@ -0,0 +1,242 @@ +/* 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-file.h" + +#include "nautilus-task-manager.h" +#include "tasks/nautilus-attribute-task.h" + +typedef enum +{ + INVALID, + PENDING, + VALID +} CacheState; + +typedef struct +{ + GFile *location; + + GFileInfo *info; + CacheState info_state; + + GMutex cache_mutex; +} NautilusFilePrivate; + +G_DEFINE_TYPE_WITH_PRIVATE (NautilusFile, nautilus_file, G_TYPE_OBJECT) + +enum +{ + PROP_LOCATION = 1, + N_PROPERTIES +}; + +static GParamSpec *properties[N_PROPERTIES] = { NULL }; +static GHashTable *files = NULL; +static GMutex files_mutex; + +static void +set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + NautilusFilePrivate *priv; + + priv = nautilus_file_get_instance_private (NAUTILUS_FILE (object)); + + switch (property_id) + { + case PROP_LOCATION: + { + priv->location = g_value_dup_object (value); + } + break; + + default: + { + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } + } +} + +static void +finalize (GObject *object) +{ + NautilusFilePrivate *priv; + + priv = nautilus_file_get_instance_private (NAUTILUS_FILE (object)); + + g_mutex_lock (&files_mutex); + 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); +} + +static void +nautilus_file_class_init (NautilusFileClass *klass) +{ + GObjectClass *object_class; + + object_class = G_OBJECT_CLASS (klass); + + object_class->set_property = set_property; + object_class->finalize = finalize; + + properties[PROP_LOCATION] = + g_param_spec_object ("location", "Location", "Location", + G_TYPE_FILE, + G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE | G_PARAM_STATIC_NAME); + + g_object_class_install_properties (object_class, N_PROPERTIES, properties); +} + +static void +nautilus_file_init (NautilusFile *self) +{ + NautilusFilePrivate *priv; + + priv = nautilus_file_get_instance_private (self); + + priv->info = g_file_info_new (); + + g_mutex_init (&priv->cache_mutex); +} + +typedef struct +{ + NautilusFile *file; + + NautilusFileInfoCallback callback; + gpointer callback_data; +} QueryInfoDetails; + +static void +on_query_info_finished (NautilusAttributeTask *task, + GFile *file, + GFileInfo *info, + GError *error, + gpointer data) +{ + QueryInfoDetails *details; + NautilusFilePrivate *priv; + + details = data; + priv = nautilus_file_get_instance_private (details->file); + + g_mutex_lock (&priv->cache_mutex); + g_file_info_copy_into (info, priv->info); + priv->info_state = VALID; + g_mutex_unlock (&priv->cache_mutex); + + details->callback (details->file, g_file_info_dup (info), error, + details->callback_data); + + g_free (details); +} + +void +nautilus_file_query_info (NautilusFile *file, + GCancellable *cancellable, + NautilusFileInfoCallback callback, + gpointer user_data) +{ + NautilusFilePrivate *priv; + g_autoptr (NautilusTask) task = NULL; + QueryInfoDetails *details; + g_autoptr (NautilusTaskManager) manager = NULL; + + priv = nautilus_file_get_instance_private (file); + + 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) + { + g_mutex_unlock (&priv->cache_mutex); + + callback (file, g_file_info_dup (priv->info), NULL, user_data); + } + g_mutex_unlock (&priv->cache_mutex); + + 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); + 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); +} + +NautilusFile * +nautilus_file_new (GFile *location) +{ + NautilusFile *file; + + g_return_val_if_fail (G_IS_FILE (location), NULL); + + g_mutex_lock (&files_mutex); + + if (files == NULL) + { + files = g_hash_table_new_full (g_file_hash, (GEqualFunc) g_file_equal, + g_object_unref, NULL); + } + + + file = g_hash_table_lookup (files, location); + if (file != NULL) + { + file = g_object_ref (file); + } + else + { + file = g_object_new (NAUTILUS_TYPE_FILE, "location", location, NULL); + + g_assert (g_hash_table_insert (files, location, file)); + } + + g_mutex_unlock (&files_mutex); + + return file; +} diff --git a/src-ng/nautilus-file.h b/src-ng/nautilus-file.h new file mode 100644 index 000000000..7781f6e68 --- /dev/null +++ b/src-ng/nautilus-file.h @@ -0,0 +1,47 @@ +/* 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_FILE_H_INCLUDED +#define NAUTILUS_FILE_H_INCLUDED + +#include <glib-object.h> + +#include <gio/gio.h> + +#define NAUTILUS_TYPE_FILE (nautilus_file_get_type ()) + +G_DECLARE_DERIVABLE_TYPE (NautilusFile, nautilus_file, NAUTILUS, FILE, GObject) + +typedef void (*NautilusFileInfoCallback) (NautilusFile *file, + GFileInfo *info, + GError *error, + gpointer user_data); + +struct _NautilusFileClass +{ + GObjectClass parent_class; +}; + +void nautilus_file_query_info (NautilusFile *file, + GCancellable *cancellable, + NautilusFileInfoCallback callback, + gpointer user_data); + +NautilusFile *nautilus_file_new (GFile *location); + +#endif diff --git a/src-ng/nautilus-marshallers.list b/src-ng/nautilus-marshallers.list new file mode 100644 index 000000000..29f507b15 --- /dev/null +++ b/src-ng/nautilus-marshallers.list @@ -0,0 +1 @@ +VOID:OBJECT,OBJECT,BOXED diff --git a/src-ng/nautilus-task-manager.c b/src-ng/nautilus-task-manager.c new file mode 100644 index 000000000..037c7a481 --- /dev/null +++ b/src-ng/nautilus-task-manager.c @@ -0,0 +1,115 @@ +/* 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-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); +} + +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 new file mode 100644 index 000000000..6d9440f09 --- /dev/null +++ b/src-ng/nautilus-task-manager.h @@ -0,0 +1,37 @@ +/* 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_TASK_MANAGER_H_INCLUDED +#define NAUTILUS_TASK_MANAGER_H_INCLUDED + +#include "nautilus-task.h" + +#include <glib-object.h> + +#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.c b/src-ng/nautilus-task.c new file mode 100644 index 000000000..c08545587 --- /dev/null +++ b/src-ng/nautilus-task.c @@ -0,0 +1,241 @@ +/* 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-task.h" + +#include <gobject/gvaluecollector.h> + +typedef struct +{ + GCancellable *cancellable; + GMainContext *context; +} NautilusTaskPrivate; + +G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (NautilusTask, nautilus_task, + G_TYPE_OBJECT) + +typedef struct +{ + GValue instance_and_params[4]; + guint signal_id; + int n_values; +} EmissionData; + +enum +{ + PROP_CANCELLABLE = 1, + N_PROPERTIES +}; + +static GParamSpec *properties[N_PROPERTIES] = { NULL }; + +static void +set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) + { + case PROP_CANCELLABLE: + { + NautilusTask *self; + NautilusTaskPrivate *priv; + + self = NAUTILUS_TASK (object); + priv = nautilus_task_get_instance_private (self); + + if (G_UNLIKELY (priv->cancellable) != NULL) + { + g_clear_object (&priv->cancellable); + } + + priv->cancellable = g_value_dup_object (value); + } + break; + + default: + { + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } + } +} + +static void +finalize (GObject *object) +{ + NautilusTask *self; + NautilusTaskPrivate *priv; + + self = NAUTILUS_TASK (object); + priv = nautilus_task_get_instance_private (self); + + g_clear_object (&priv->cancellable); + g_clear_pointer (&priv->context, g_main_context_unref); + + G_OBJECT_CLASS (nautilus_task_parent_class)->finalize (object); +} + +static void +emission_data_free (EmissionData *data) +{ + for (int i = 0; i < data->n_values; i++) + { + g_value_unset (&data->instance_and_params[i]); + } + + g_free (data); +} + +static gboolean +emit_signal (gpointer data) +{ + EmissionData *emission_data; + + emission_data = data; + + g_signal_emitv (emission_data->instance_and_params, + emission_data->signal_id, + 0, NULL); + + g_clear_pointer (&emission_data, emission_data_free); + + return FALSE; +} + +static void +emit_signal_in_main_context (NautilusTask *instance, + guint signal_id, + ...) +{ + va_list ap; + EmissionData *emission_data; + GSignalQuery query; + g_autofree gchar *error = NULL; + NautilusTaskPrivate *priv; + + emission_data = g_new0 (EmissionData, 1); + priv = nautilus_task_get_instance_private (instance); + + va_start (ap, signal_id); + + g_value_init (&emission_data->instance_and_params[0], + G_TYPE_FROM_INSTANCE (instance)); + g_value_set_instance (&emission_data->instance_and_params[0], instance); + + emission_data->signal_id = signal_id; + + g_signal_query (signal_id, &query); + + if (query.signal_id == 0) + { + g_clear_pointer (&emission_data, emission_data_free); + + va_end (ap); + + return; + } + + for (int i = 0; i < query.n_params; i++) + { + G_VALUE_COLLECT_INIT (&emission_data->instance_and_params[i + 1], + query.param_types[i], + ap, 0, &error); + + if (error != NULL) + { + break; + } + + emission_data->n_values++; + } + + if (error != NULL) + { + g_clear_pointer (&emission_data, emission_data_free); + + va_end (ap); + + return; + } + + g_main_context_invoke (priv->context, emit_signal, emission_data); + + va_end (ap); +} + +static void +nautilus_task_class_init (NautilusTaskClass *klass) +{ + GObjectClass *object_class; + + object_class = G_OBJECT_CLASS (klass); + + object_class->set_property = set_property; + object_class->finalize = finalize; + + klass->emit_signal_in_main_context = emit_signal_in_main_context; + + 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_object_class_install_properties (object_class, N_PROPERTIES, properties); +} + +static void +nautilus_task_init (NautilusTask *self) +{ + NautilusTaskPrivate *priv; + + priv = nautilus_task_get_instance_private (self); + + priv->context = g_main_context_ref_thread_default (); +} + +GCancellable * +nautilus_task_get_cancellable (NautilusTask *task) +{ + NautilusTaskPrivate *priv; + + g_return_val_if_fail (NAUTILUS_TASK (task), NULL); + + priv = nautilus_task_get_instance_private (task); + + if (priv->cancellable == NULL) + { + return NULL; + } + + return g_object_ref (priv->cancellable); +} + +void +nautilus_task_execute (NautilusTask *task) +{ + NautilusTaskClass *klass; + + g_return_if_fail (NAUTILUS_IS_TASK (task)); + + klass = NAUTILUS_TASK_GET_CLASS (task); + + g_return_if_fail (klass->execute != NULL); + + klass->execute (task); +} diff --git a/src-ng/nautilus-task.h b/src-ng/nautilus-task.h new file mode 100644 index 000000000..8c6eea014 --- /dev/null +++ b/src-ng/nautilus-task.h @@ -0,0 +1,48 @@ +/* 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_TASK_H +#define NAUTILUS_TASK_H + +#include <gio/gio.h> +#include <glib-object.h> + +#define NAUTILUS_TYPE_TASK (nautilus_task_get_type ()) + +G_DECLARE_DERIVABLE_TYPE (NautilusTask, nautilus_task, + NAUTILUS, TASK, + GObject) + +typedef void (*NautilusTaskCallback) (NautilusTask *task, + gpointer user_data); + +struct _NautilusTaskClass +{ + GObjectClass parent_class; + + void (*execute) (NautilusTask *task); + void (*emit_signal_in_main_context) (NautilusTask *instance, + guint signal_id, + ...); +}; + +GCancellable *nautilus_task_get_cancellable (NautilusTask *task); + +void nautilus_task_execute (NautilusTask *task); + +#endif diff --git a/src-ng/tasks/nautilus-attribute-task.c b/src-ng/tasks/nautilus-attribute-task.c new file mode 100644 index 000000000..ebc0ddd1a --- /dev/null +++ b/src-ng/tasks/nautilus-attribute-task.c @@ -0,0 +1,195 @@ +/* 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-attribute-task.h" + +#include "nautilus-marshallers.h" + +struct _NautilusAttributeTask +{ + GObject parent_instance; + + GFile *file; + const char *attributes; + + GFileQueryInfoFlags flags; +} NautilusAttributeTaskPrivate; + +G_DEFINE_TYPE (NautilusAttributeTask, nautilus_attribute_task, + NAUTILUS_TYPE_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; + + 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; + NautilusTaskClass *klass; + + self = NAUTILUS_ATTRIBUTE_TASK (task); + cancellable = nautilus_task_get_cancellable (NAUTILUS_TASK (self)); + info = g_file_query_info (self->file, + self->attributes, + self->flags, + cancellable, + &error); + klass = NAUTILUS_TASK_CLASS (G_OBJECT_GET_CLASS (self)); + + klass->emit_signal_in_main_context (task, signals[FINISHED], + 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->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, + 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) +{ + self->file = NULL; + self->attributes = NULL; + self->flags = 0; +} + +NautilusTask * +nautilus_attribute_task_new (GFile *file, + const char *attributes, + GFileQueryInfoFlags flags, + GCancellable *cancellable) +{ + return g_object_new (NAUTILUS_TYPE_ATTRIBUTE_TASK, + "file", file, + "attributes", attributes, + "flags", flags, + "cancellable", cancellable, + NULL); +} diff --git a/src-ng/tasks/nautilus-attribute-task.h b/src-ng/tasks/nautilus-attribute-task.h new file mode 100644 index 000000000..fba86b2ca --- /dev/null +++ b/src-ng/tasks/nautilus-attribute-task.h @@ -0,0 +1,37 @@ +/* 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_ATTRIBUTE_TASK_H_INCLUDED +#define NAUTILUS_ATTRIBUTE_TASK_H_INCLUDED + +#include "nautilus-task.h" + +#include <gio/gio.h> + +#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 |