[nautilus/wip/ernestask/tasks: 42/49] Yay for reinventing wheels



commit d7f34cee40f8090fbfabb1de50650b4a8669b10f
Author: Ernestas Kulik <ernestask gnome org>
Date:   Sat Jul 8 17:03:04 2017 +0300

    Yay for reinventing wheels

 meson.build                            |    2 +
 src-ng/main.c                          |   59 ++++++++
 src-ng/meson.build                     |   21 +++
 src-ng/nautilus-file.c                 |  242 ++++++++++++++++++++++++++++++++
 src-ng/nautilus-file.h                 |   47 ++++++
 src-ng/nautilus-marshallers.list       |    1 +
 src-ng/nautilus-task-manager.c         |  115 +++++++++++++++
 src-ng/nautilus-task-manager.h         |   37 +++++
 src-ng/nautilus-task.c                 |  241 +++++++++++++++++++++++++++++++
 src-ng/nautilus-task.h                 |   48 +++++++
 src-ng/tasks/nautilus-attribute-task.c |  195 +++++++++++++++++++++++++
 src-ng/tasks/nautilus-attribute-task.h |   37 +++++
 12 files changed, 1045 insertions(+), 0 deletions(-)
---
diff --git a/meson.build b/meson.build
index 7756602..52534d1 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 0000000..0a3ad0a
--- /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 0000000..dbda07e
--- /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 0000000..3b8c552
--- /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 0000000..7781f6e
--- /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 0000000..29f507b
--- /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 0000000..037c7a4
--- /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 0000000..6d9440f
--- /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 0000000..c085455
--- /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 0000000..8c6eea0
--- /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 0000000..ebc0ddd
--- /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 0000000..fba86b2
--- /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


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]