[nautilus/wip/ernestask/tasks-irisified: 28/28] Iris-ify tasks
- From: Ernestas Kulik <ernestask src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [nautilus/wip/ernestask/tasks-irisified: 28/28] Iris-ify tasks
- Date: Thu, 17 Aug 2017 15:57:26 +0000 (UTC)
commit da669e43a15442a6ee641aa5b8197837856a168b
Author: Ernestas Kulik <ernestask gnome org>
Date: Tue Aug 15 21:38:44 2017 +0300
Iris-ify tasks
For ∞x more flexibility.
meson.build | 2 +-
src-ng/meson.build | 54 ++--
src-ng/nautilus-context-scheduler.c | 166 ++++++++++
...umbnail-task.h => nautilus-context-scheduler.h} | 23 +-
src-ng/nautilus-directory.c | 49 +---
src-ng/nautilus-file.c | 58 +---
src-ng/nautilus-file.h | 1 +
src-ng/{main.c => nautilus-main.c} | 29 +-
src-ng/nautilus-scheduler-private.h | 49 +++
src-ng/nautilus-scheduler.c | 158 ++++++++++
src-ng/nautilus-scheduler.h | 62 ++++
src-ng/nautilus-task-manager.c | 117 -------
src-ng/nautilus-task-manager.h | 37 ---
src-ng/nautilus-task-private.h | 29 --
src-ng/nautilus-task.c | 327 +++++++++++++++-----
src-ng/nautilus-task.h | 131 +++++++-
src-ng/nautilus-tasks.c | 235 ++++++++++++++
.../nautilus-attribute-task.h => nautilus-tasks.h} | 26 +-
src-ng/tasks/nautilus-attribute-task.c | 126 --------
src-ng/tasks/nautilus-enumerate-children-task.c | 142 ---------
src-ng/tasks/nautilus-enumerate-children-task.h | 38 ---
src-ng/tasks/nautilus-rename-task.c | 150 ---------
src-ng/tasks/nautilus-rename-task.h | 35 --
src-ng/tasks/nautilus-thumbnail-task.c | 287 -----------------
24 files changed, 1126 insertions(+), 1205 deletions(-)
---
diff --git a/meson.build b/meson.build
index 92e4b49..5530f94 100644
--- a/meson.build
+++ b/meson.build
@@ -20,7 +20,7 @@ searchproviderdir = join_paths (datadir, 'gnome-shell', 'search-providers')
servicedir = join_paths (datadir, 'dbus-1', 'services')
sysconfdir = get_option ('sysconfdir')
-glib_ver = '>=2.51.2'
+glib_ver = '>=2.53.5'
gnome_desktop_ver = '>=3.0.0'
pango_ver = '1.28.3'
gtk_ver = '>=3.22.6'
diff --git a/src-ng/meson.build b/src-ng/meson.build
index 493af05..bfc1cf3 100644
--- a/src-ng/meson.build
+++ b/src-ng/meson.build
@@ -2,33 +2,33 @@ resources = gnome.compile_resources ('nautilus-ng-resources',
join_paths ('res', 'org.gnome.Nautilus.gresource.xml'),
source_dir: 'res')
-nautilus_ng_sources = [resources,
- 'nautilus-task.c',
- 'nautilus-task.h',
- 'nautilus-task-private.h',
- 'nautilus-task-manager.c',
- 'nautilus-task-manager.h',
- 'nautilus-file.c',
- 'nautilus-file.h',
- 'tasks/nautilus-attribute-task.c',
- 'tasks/nautilus-attribute-task.h',
- 'nautilus-directory.c',
- 'nautilus-directory.h',
- 'tasks/nautilus-enumerate-children-task.c',
- 'tasks/nautilus-enumerate-children-task.h',
- 'nautilus-cache.c',
- 'nautilus-cache.h',
- 'tasks/nautilus-rename-task.c',
- 'tasks/nautilus-rename-task.h',
- 'nautilus-file-changes.c',
- 'nautilus-file-changes.h',
- 'nautilus-signal-utilities.c',
- 'nautilus-signal-utilities.h',
- 'nautilus-file-table.c',
- 'nautilus-file-table.h',
- 'tasks/nautilus-thumbnail-task.c',
- 'tasks/nautilus-thumbnail-task.h',
- 'main.c']
+nautilus_ng_sources = [
+ resources,
+ 'nautilus-task.c',
+ 'nautilus-task.h',
+ 'nautilus-file.c',
+ 'nautilus-file.h',
+ 'nautilus-directory.c',
+ 'nautilus-directory.h',
+ 'nautilus-cache.c',
+ 'nautilus-cache.h',
+ 'nautilus-file-changes.c',
+ 'nautilus-file-changes.h',
+ 'nautilus-signal-utilities.c',
+ 'nautilus-signal-utilities.h',
+ 'nautilus-file-table.c',
+ 'nautilus-file-table.h',
+ 'nautilus-attribute.c',
+ 'nautilus-attribute.h',
+ 'nautilus-tasks.c',
+ 'nautilus-tasks.h',
+ 'nautilus-scheduler.c',
+ 'nautilus-scheduler.h',
+ 'nautilus-context-scheduler.c',
+ 'nautilus-context-scheduler.h',
+ 'nautilus-scheduler-private.h',
+ 'nautilus-main.c'
+]
nautilus_ng_dependencies = [gio, glib, gnome_desktop, gtk]
diff --git a/src-ng/nautilus-context-scheduler.c b/src-ng/nautilus-context-scheduler.c
new file mode 100644
index 0000000..5f7723a
--- /dev/null
+++ b/src-ng/nautilus-context-scheduler.c
@@ -0,0 +1,166 @@
+/* Copyright (C) 2017 Ernestas Kulik <ernestask gnome org>
+ *
+ * This file is part of Nautilus.
+ *
+ * Nautilus is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Nautilus is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Nautilus. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include "nautilus-context-scheduler.h"
+
+#include "nautilus-scheduler-private.h"
+
+struct _NautilusContextScheduler
+{
+ NautilusScheduler parent_instance;
+
+ GMainContext *context;
+ guint source_id;
+
+ GQueue *queue;
+};
+
+G_DEFINE_TYPE (NautilusContextScheduler, nautilus_context_scheduler,
+ NAUTILUS_TYPE_SCHEDULER)
+
+typedef struct
+{
+ GSource parent_instance;
+
+ NautilusContextScheduler *scheduler;
+} NautilusSource;
+
+G_LOCK_DEFINE_STATIC (table_mutex);
+static GHashTable *scheduler_table = NULL;
+
+static void
+queue (NautilusScheduler *scheduler,
+ NautilusCallback func,
+ gpointer func_data)
+{
+ NautilusContextScheduler *context_scheduler;
+ NautilusThreadWork *work;
+
+ context_scheduler = NAUTILUS_CONTEXT_SCHEDULER (scheduler);
+ work = nautilus_thread_work_new (func, func_data);
+
+ g_queue_push_tail (context_scheduler->queue, work);
+}
+
+static void
+nautilus_context_scheduler_class_init (NautilusContextSchedulerClass *klass)
+{
+ NautilusSchedulerClass *scheduler_class;
+
+ scheduler_class = NAUTILUS_SCHEDULER_CLASS (klass);
+
+ scheduler_class->queue = queue;
+}
+
+static gboolean
+source_prepare (GSource *source,
+ gint *timeout)
+{
+ NautilusSource *nautilus_source;
+
+ nautilus_source = (NautilusSource *) source;
+
+ *timeout = -1;
+
+ return !g_queue_is_empty (nautilus_source->scheduler->queue);
+}
+
+static gboolean
+source_check (GSource *source)
+{
+ NautilusSource *nautilus_source;
+
+ nautilus_source = (NautilusSource *) source;
+
+ return !g_queue_is_empty (nautilus_source->scheduler->queue);
+}
+
+static gboolean
+source_dispatch (GSource *source,
+ GSourceFunc callback,
+ gpointer user_data)
+{
+ return callback (user_data);
+}
+
+static GSourceFuncs source_funcs =
+{
+ source_prepare,
+ source_check,
+ source_dispatch,
+ NULL
+};
+
+static gboolean
+source_callback (gpointer data)
+{
+ NautilusContextScheduler *scheduler;
+ NautilusThreadWork *work;
+
+ scheduler = data;
+
+ while ((work = g_queue_pop_head (scheduler->queue)) != NULL)
+ {
+ nautilus_thread_work_run (work);
+ }
+
+ return G_SOURCE_CONTINUE;
+}
+
+static void
+nautilus_context_scheduler_init (NautilusContextScheduler *self)
+{
+ g_autoptr (GSource) source = NULL;
+
+ source = g_source_new (&source_funcs, sizeof (NautilusSource));
+
+ g_source_set_priority (source, G_PRIORITY_DEFAULT_IDLE);
+ g_source_set_callback (source, source_callback, self, NULL);
+
+ self->source_id = g_source_attach (source, self->context);
+}
+
+NautilusScheduler *
+nautilus_context_scheduler_get_for_context (GMainContext *context)
+{
+ NautilusContextScheduler *scheduler;
+
+ g_return_val_if_fail (context != NULL, NULL);
+
+ G_LOCK (table_mutex);
+
+ if (scheduler_table == NULL)
+ {
+ scheduler_table = g_hash_table_new_full (g_direct_hash, g_direct_equal,
+ NULL, g_object_unref);
+ }
+
+ scheduler = g_hash_table_lookup (scheduler_table, context);
+ if (scheduler == NULL)
+ {
+ scheduler = g_object_new (NAUTILUS_TYPE_CONTEXT_SCHEDULER, NULL);
+
+ scheduler->context = context;
+
+ g_hash_table_insert (scheduler_table, context, scheduler);
+ }
+
+ G_UNLOCK (table_mutex);
+
+ return NAUTILUS_SCHEDULER (scheduler);
+}
diff --git a/src-ng/tasks/nautilus-thumbnail-task.h b/src-ng/nautilus-context-scheduler.h
similarity index 56%
rename from src-ng/tasks/nautilus-thumbnail-task.h
rename to src-ng/nautilus-context-scheduler.h
index 1c95bd0..18a753f 100644
--- a/src-ng/tasks/nautilus-thumbnail-task.h
+++ b/src-ng/nautilus-context-scheduler.h
@@ -16,19 +16,22 @@
* along with Nautilus. If not, see <https://www.gnu.org/licenses/>.
*/
-#ifndef NAUTILUS_THUMBNAIL_TASK_H_INCLUDED
-#define NAUTILUS_THUMBNAIL_TASK_H_INCLUDED
+#ifndef NAUTILUS_CONTEXT_SCHEDULER_H_INCLUDED
+#define NAUTILUS_CONTEXT_SCHEDULER_H_INCLUDED
-#include "nautilus-task.h"
+#include "nautilus-scheduler.h"
-#include <gio/gio.h>
+#define NAUTILUS_TYPE_CONTEXT_SCHEDULER (nautilus_context_scheduler_get_type ())
-#define NAUTILUS_TYPE_THUMBNAIL_TASK (nautilus_thumbnail_task_get_type ())
+G_DECLARE_FINAL_TYPE (NautilusContextScheduler, nautilus_context_scheduler,
+ NAUTILUS, CONTEXT_SCHEDULER, NautilusScheduler)
-G_DECLARE_FINAL_TYPE (NautilusThumbnailTask, nautilus_thumbnail_task,
- NAUTILUS, THUMBNAIL_TASK, NautilusTask)
-
-NautilusTask *nautilus_thumbnail_task_new (GFile *location,
- gboolean use_external_thumbnailer);
+/**
+ * nautilus_context_scheduler_get_for_context:
+ * @context: a valid main context
+ *
+ * Returns: (transfer none): the scheduler for @context
+ */
+NautilusScheduler *nautilus_context_scheduler_get_for_context (GMainContext *context);
#endif
diff --git a/src-ng/nautilus-directory.c b/src-ng/nautilus-directory.c
index c125a39..a4c8c13 100644
--- a/src-ng/nautilus-directory.c
+++ b/src-ng/nautilus-directory.c
@@ -19,8 +19,8 @@
#include "nautilus-directory.h"
#include "nautilus-cache.h"
-#include "nautilus-task-manager.h"
-#include "tasks/nautilus-enumerate-children-task.h"
+#include "nautilus-task.h"
+#include "nautilus-tasks.h"
enum
{
@@ -101,7 +101,7 @@ typedef struct
gpointer callback_data;
} EnumerateChildrenDetails;
-static void
+/*static void
create_file_list (gpointer key,
gpointer value,
gpointer user_data)
@@ -113,9 +113,9 @@ create_file_list (gpointer key,
*list = g_list_prepend (*list,
nautilus_file_new_with_info (G_FILE (key),
G_FILE_INFO (value)));
-}
+}*/
-static void
+/*static void
on_enumerate_children_finished (NautilusEnumerateChildrenTask *task,
GFile *file,
GHashTable *files,
@@ -133,9 +133,9 @@ on_enumerate_children_finished (NautilusEnumerateChildrenTask *task,
priv->cache_items[CHILDREN]);
if (cache_state == NAUTILUS_CACHE_INVALID)
- {
+ {*/
/* TODO: restart */
- return;
+ /*return;
}
g_hash_table_foreach (files, create_file_list, &children);
@@ -147,7 +147,7 @@ on_enumerate_children_finished (NautilusEnumerateChildrenTask *task,
details->callback_data);
g_free (details);
-}
+}*/
void
nautilus_directory_enumerate_children (NautilusDirectory *directory,
@@ -159,8 +159,6 @@ nautilus_directory_enumerate_children (NautilusDirectory *direct
NautilusCacheState cache_state;
g_autoptr (GFile) location = NULL;
g_autoptr (NautilusTask) task = NULL;
- EnumerateChildrenDetails *details;
- g_autoptr (NautilusTaskManager) task_manager = NULL;
g_return_if_fail (NAUTILUS_IS_DIRECTORY (directory));
@@ -184,33 +182,10 @@ nautilus_directory_enumerate_children (NautilusDirectory *direct
priv->cache_items[CHILDREN]);
location = nautilus_file_get_location (NAUTILUS_FILE (directory));
- task = nautilus_enumerate_children_task_new (location,
- "standard::*,"
- "access::*,"
- "mountable::*,"
- "time::*,"
- "unix::*,"
- "owner::*,"
- "selinux::*,"
- "thumbnail::*,"
- "id::filesystem,"
- "trash::orig-path,"
- "trash::deletion-date,"
- "metadata::*,"
- "recent::*",
- G_FILE_QUERY_INFO_NONE,
- cancellable);
- details = g_new0 (EnumerateChildrenDetails, 1);
- task_manager = nautilus_task_manager_dup_singleton ();
-
- details->directory = directory;
- details->callback = callback;
- details->callback_data = user_data;
-
- g_signal_connect (task, "finished",
- G_CALLBACK (on_enumerate_children_finished), details);
-
- nautilus_task_manager_queue_task (task_manager, task);
+ task = nautilus_task_new_with_func (nautilus_enumerate_children_task_func, location,
+ cancellable);
+
+ nautilus_task_run (task);
}
NautilusFile *
diff --git a/src-ng/nautilus-file.c b/src-ng/nautilus-file.c
index 9701be1..b543880 100644
--- a/src-ng/nautilus-file.c
+++ b/src-ng/nautilus-file.c
@@ -21,9 +21,8 @@
#include "nautilus-cache.h"
#include "nautilus-directory.h"
#include "nautilus-file-table.h"
-#include "nautilus-task-manager.h"
-#include "tasks/nautilus-attribute-task.h"
-#include "tasks/nautilus-thumbnail-task.h"
+#include "nautilus-task.h"
+#include "nautilus-tasks.h"
enum
{
@@ -203,7 +202,7 @@ typedef struct
gpointer callback_data;
} QueryInfoDetails;
-static void
+/*static void
on_query_info_finished (NautilusAttributeTask *task,
GFile *file,
GFileInfo *info,
@@ -220,9 +219,9 @@ on_query_info_finished (NautilusAttributeTask *task,
priv->cache_items[INFO]);
if (cache_state == NAUTILUS_CACHE_INVALID)
- {
+ {*/
/* TODO: restart */
- return;
+ /*return;
}
nautilus_cache_item_set_value (priv->cache, priv->cache_items[INFO],
@@ -232,7 +231,7 @@ on_query_info_finished (NautilusAttributeTask *task,
details->callback_data);
g_free (details);
-}
+}*/
void
nautilus_file_query_info (NautilusFile *file,
@@ -242,9 +241,9 @@ nautilus_file_query_info (NautilusFile *file,
{
NautilusFilePrivate *priv;
NautilusCacheState cache_state;
+ GFile *location;
g_autoptr (NautilusTask) task = NULL;
QueryInfoDetails *details;
- g_autoptr (NautilusTaskManager) manager = NULL;
g_return_if_fail (NAUTILUS_IS_FILE (file));
@@ -277,61 +276,34 @@ nautilus_file_query_info (NautilusFile *file,
nautilus_cache_item_set_pending (priv->cache, priv->cache_items[INFO]);
- task = nautilus_attribute_task_new (priv->location,
- "standard::*,"
- "access::*,"
- "mountable::*,"
- "time::*,"
- "unix::*,"
- "owner::*,"
- "selinux::*,"
- "thumbnail::*,"
- "id::filesystem,"
- "trash::orig-path,"
- "trash::deletion-date,"
- "metadata::*,"
- "recent::*",
- G_FILE_QUERY_INFO_NONE,
- cancellable);
+ location = nautilus_file_get_location (file);
+ task = nautilus_task_new_with_func (nautilus_query_info_func, location, cancellable);
+
details = g_new0 (QueryInfoDetails, 1);
- manager = nautilus_task_manager_dup_singleton ();
details->file = file;
details->callback = callback;
details->callback_data = user_data;
- g_signal_connect (task, "finished",
- G_CALLBACK (on_query_info_finished), details);
-
- nautilus_task_manager_queue_task (manager, task);
+ nautilus_task_run (task);
}
-typedef struct
-{
- NautilusFile *file;
-
- NautilusFileInfoCallback callback;
- gpointer callback_data;
-} GetThumbnailDetails;
-
void
nautilus_file_get_thumbnail (NautilusFile *file,
+ GCancellable *cancellable,
NautilusThumbnailCallback callback,
gpointer user_data)
{
g_autoptr (GFile) location = NULL;
g_autoptr (NautilusTask) task = NULL;
- GetThumbnailDetails *details;
- g_autoptr (NautilusTaskManager) manager = NULL;
g_return_if_fail (NAUTILUS_IS_FILE (file));
location = nautilus_file_get_location (file);
- task = nautilus_thumbnail_task_new (location, TRUE);
- details = g_new0 (GetThumbnailDetails, 1);
- manager = nautilus_task_manager_dup_singleton ();
+ task = nautilus_task_new_with_func (nautilus_thumbnail_task_func,
+ g_object_ref (location), cancellable);
- nautilus_task_manager_queue_task (manager, task);
+ nautilus_task_run (task);
}
NautilusFile *
diff --git a/src-ng/nautilus-file.h b/src-ng/nautilus-file.h
index 8d26aea..8d9407b 100644
--- a/src-ng/nautilus-file.h
+++ b/src-ng/nautilus-file.h
@@ -55,6 +55,7 @@ void nautilus_file_query_info (NautilusFile *file,
NautilusFileInfoCallback callback,
gpointer user_data);
void nautilus_file_get_thumbnail (NautilusFile *file,
+ GCancellable *cancellable,
NautilusThumbnailCallback callback,
gpointer user_data);
diff --git a/src-ng/main.c b/src-ng/nautilus-main.c
similarity index 91%
rename from src-ng/main.c
rename to src-ng/nautilus-main.c
index fa36b59..57f5e80 100644
--- a/src-ng/main.c
+++ b/src-ng/nautilus-main.c
@@ -6,9 +6,8 @@
#include "nautilus-directory.h"
#include "nautilus-file.h"
-#include "nautilus-task-manager.h"
-#include "tasks/nautilus-rename-task.h"
-#include "tasks/nautilus-thumbnail-task.h"
+#include "nautilus-task.h"
+#include "nautilus-tasks.h"
static void
got_info (NautilusFile *file,
@@ -121,7 +120,7 @@ _rename (const gchar *target,
g_autoptr (GFile) location = NULL;
g_autoptr (NautilusFile) file = NULL;
g_autoptr (NautilusFile) parent = NULL;
- g_autoptr (NautilusTaskManager) manager = NULL;
+ g_autoptr (GHashTable) targets = NULL;
g_autoptr (NautilusTask) task = NULL;
GMainLoop *loop;
@@ -132,22 +131,21 @@ _rename (const gchar *target,
parent = nautilus_file_get_parent (file);
g_message ("Constructed NautilusFile %p for location %p",
(gpointer) file, (gpointer) location);
- manager = nautilus_task_manager_dup_singleton ();
- task = nautilus_rename_task_new ();
+ targets = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, NULL);
+ task = nautilus_task_new_with_func (nautilus_rename_task_func, targets, NULL);
loop = g_main_loop_new (NULL, TRUE);
+ (void) g_hash_table_insert (targets, location, name);
+
g_signal_connect (parent, "children-changed",
G_CALLBACK (on_children_changed), loop);
- nautilus_rename_task_add_target (NAUTILUS_RENAME_TASK (task),
- location, name);
-
- nautilus_task_manager_queue_task (manager, task);
+ nautilus_task_run (task);
g_main_loop_run (loop);
}
-static void
+/*static void
on_thumbnail_finished (NautilusThumbnailTask *task,
GFile *location,
GdkPixbuf *thumbnail,
@@ -164,7 +162,7 @@ on_thumbnail_finished (NautilusThumbnailTask *task,
gtk_container_add (GTK_CONTAINER (user_data), image);
g_object_unref (thumbnail);
-}
+}*/
static gboolean
on_window_deleted (GtkWidget *widget,
@@ -179,7 +177,7 @@ on_window_deleted (GtkWidget *widget,
static void
display_thumbnail (const gchar *path)
{
- GtkWidget *window;
+ /*GtkWidget *window;
g_autoptr (GFile) location = NULL;
g_autoptr (NautilusTask) task = NULL;
g_autoptr (NautilusTaskManager) task_manager = NULL;
@@ -198,7 +196,7 @@ display_thumbnail (const gchar *path)
nautilus_task_manager_queue_task (task_manager, task);
- gtk_main ();
+ gtk_main ();*/
}
int
@@ -231,7 +229,6 @@ main (int argc,
{ NULL }
};
GError *error = NULL;
- g_autoptr (NautilusTaskManager) manager = NULL;
setlocale (LC_ALL, "");
@@ -253,8 +250,6 @@ main (int argc,
return EXIT_FAILURE;
}
- manager = nautilus_task_manager_dup_singleton ();
-
if (check)
{
perform_self_test_checks (files[0]);
diff --git a/src-ng/nautilus-scheduler-private.h b/src-ng/nautilus-scheduler-private.h
new file mode 100644
index 0000000..737c2a5
--- /dev/null
+++ b/src-ng/nautilus-scheduler-private.h
@@ -0,0 +1,49 @@
+/* Copyright (C) 2017 Ernestas Kulik <ernestask gnome org>
+ *
+ * This file is part of Nautilus.
+ *
+ * Nautilus is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Nautilus is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Nautilus. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef NAUTILUS_SCHEDULER_PRIVATE_H_INCLUDED
+#define NAUTILUS_SCHEDULER_PRIVATE_H_INCLUDED
+
+#include "nautilus-scheduler.h"
+
+typedef struct NautilusThreadWork NautilusThreadWork;
+
+/**
+ * nautilus_thread_work_run:
+ * @work: an initialized #NautilusThreadWork
+ */
+void nautilus_thread_work_run (NautilusThreadWork *work);
+
+/**
+ * nautilus_thread_work_free:
+ * @work: an initialized #NautilusThreadWork
+ */
+void nautilus_thread_work_free (NautilusThreadWork *work);
+/**
+ * nautilus_thread_work_new:
+ * @callback: the function to call
+ * @data: data to pass to @callback
+ *
+ * Returns: (transfer full): a new #NautilusThreadWork instance
+ */
+NautilusThreadWork *nautilus_thread_work_new (NautilusCallback callback,
+ gpointer data);
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (NautilusThreadWork, nautilus_thread_work_free)
+
+#endif
diff --git a/src-ng/nautilus-scheduler.c b/src-ng/nautilus-scheduler.c
new file mode 100644
index 0000000..6695efc
--- /dev/null
+++ b/src-ng/nautilus-scheduler.c
@@ -0,0 +1,158 @@
+/* Copyright (C) 2017 Ernestas Kulik <ernestask gnome org>
+ *
+ * This file is part of Nautilus.
+ *
+ * Nautilus is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Nautilus is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Nautilus. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include "nautilus-scheduler-private.h"
+
+typedef struct
+{
+ GThreadPool *thread_pool;
+} NautilusSchedulerPrivate;
+
+G_DEFINE_TYPE_WITH_PRIVATE (NautilusScheduler, nautilus_scheduler, G_TYPE_OBJECT)
+
+struct NautilusThreadWork
+{
+ NautilusCallback func;
+ gpointer func_data;
+};
+
+static void
+finalize (GObject *object)
+{
+ NautilusScheduler *scheduler;
+ NautilusSchedulerPrivate *priv;
+
+ scheduler = NAUTILUS_SCHEDULER (object);
+ priv = nautilus_scheduler_get_instance_private (scheduler);
+
+ g_thread_pool_free (priv->thread_pool, TRUE, TRUE);
+
+ G_OBJECT_CLASS (nautilus_scheduler_parent_class)->finalize (object);
+}
+
+static void
+queue (NautilusScheduler *scheduler,
+ NautilusCallback func,
+ gpointer func_data)
+{
+ NautilusSchedulerPrivate *priv;
+ NautilusThreadWork *work;
+
+ priv = nautilus_scheduler_get_instance_private (scheduler);
+ work = nautilus_thread_work_new (func, func_data);
+
+ (void) g_thread_pool_push (priv->thread_pool, work, NULL);
+}
+
+static void
+nautilus_scheduler_class_init (NautilusSchedulerClass *klass)
+{
+ GObjectClass *object_class;
+
+ object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = finalize;
+
+ klass->queue = queue;
+}
+
+static void
+nautilus_scheduler_init (NautilusScheduler *self)
+{
+}
+
+void
+nautilus_scheduler_queue (NautilusScheduler *scheduler,
+ NautilusCallback func,
+ gpointer func_data)
+{
+ g_return_if_fail (NAUTILUS_IS_SCHEDULER (scheduler));
+ g_return_if_fail (func != NULL);
+
+ NAUTILUS_SCHEDULER_GET_CLASS (scheduler)->queue (scheduler, func, func_data);
+}
+
+static void
+thread_pool_func (gpointer data,
+ gpointer user_data)
+{
+ g_autoptr (NautilusThreadWork) work = NULL;
+
+ work = data;
+
+ nautilus_thread_work_run (work);
+}
+
+static NautilusScheduler *
+nautilus_scheduler_new (gint max_threads)
+{
+ NautilusScheduler *scheduler;
+ NautilusSchedulerPrivate *priv;
+
+ scheduler = g_object_new (NAUTILUS_TYPE_SCHEDULER, NULL);
+ priv = nautilus_scheduler_get_instance_private (scheduler);
+
+ priv->thread_pool = g_thread_pool_new (thread_pool_func, NULL, max_threads, FALSE, NULL);
+
+ return scheduler;
+}
+
+static gpointer
+create_default_instance (gpointer data)
+{
+ (void) data;
+
+ return nautilus_scheduler_new (16);
+}
+
+NautilusScheduler *
+nautilus_scheduler_get_default (void)
+{
+ static GOnce once = G_ONCE_INIT;
+
+ g_once (&once, create_default_instance, NULL);
+
+ return g_object_ref (once.retval);
+}
+
+
+void
+nautilus_thread_work_run (NautilusThreadWork *work)
+{
+ work->func (work->func_data);
+}
+
+void
+nautilus_thread_work_free (NautilusThreadWork *work)
+{
+ g_free (work);
+}
+
+NautilusThreadWork *
+nautilus_thread_work_new (NautilusCallback callback,
+ gpointer data)
+{
+ NautilusThreadWork *work;
+
+ work = g_new0 (NautilusThreadWork, 1);
+
+ work->func = callback;
+ work->func_data = data;
+
+ return work;
+}
diff --git a/src-ng/nautilus-scheduler.h b/src-ng/nautilus-scheduler.h
new file mode 100644
index 0000000..e589e7a
--- /dev/null
+++ b/src-ng/nautilus-scheduler.h
@@ -0,0 +1,62 @@
+/* Copyright (C) 2017 Ernestas Kulik <ernestask gnome org>
+ *
+ * This file is part of Nautilus.
+ *
+ * Nautilus is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Nautilus is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Nautilus. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef NAUTILUS_SCHEDULER_H_INCLUDED
+#define NAUTILUS_SCHEDULER_H_INCLUDED
+
+#include <glib-object.h>
+
+#define NAUTILUS_CALLBACK(x) ((NautilusCallback) x)
+#define NAUTILUS_TYPE_SCHEDULER (nautilus_scheduler_get_type ())
+
+G_DECLARE_DERIVABLE_TYPE (NautilusScheduler, nautilus_scheduler,
+ NAUTILUS, SCHEDULER, GObject)
+
+/**
+ * NautilusCallback:
+ * @data: (nullable): user data passed to #nautilus_scheduler_queue
+ */
+typedef void (*NautilusCallback) (gpointer data);
+
+struct _NautilusSchedulerClass
+{
+ GObjectClass parent_class;
+
+ void (*queue) (NautilusScheduler *scheduler,
+ NautilusCallback func,
+ gpointer func_data);
+};
+
+/**
+ * nautilus_scheduler_queue:
+ * @scheduler: an initialized #NautilusScheduler
+ * @func: the #NautilusCallback to call
+ * @func_data: (nullable): additional data to pass to @func
+ */
+void nautilus_scheduler_queue (NautilusScheduler *scheduler,
+ NautilusCallback func,
+ gpointer func_data);
+
+/**
+ * nautilus_scheduler_get_default:
+ *
+ * Returns: (transfer full): the default #NautilusScheduler instance
+ */
+NautilusScheduler *nautilus_scheduler_get_default (void);
+
+#endif
diff --git a/src-ng/nautilus-task.c b/src-ng/nautilus-task.c
index de6bdea..8506648 100644
--- a/src-ng/nautilus-task.c
+++ b/src-ng/nautilus-task.c
@@ -18,150 +18,309 @@
#include "nautilus-task.h"
-#include "nautilus-signal-utilities.h"
+#include "nautilus-context-scheduler.h"
-typedef struct
+struct _NautilusTask
{
+ GObject parent_instance;
+
+ NautilusScheduler *scheduler;
+
+ GClosure *closure;
GCancellable *cancellable;
- GMainContext *context;
-} NautilusTaskPrivate;
+ GError *error;
-G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (NautilusTask, nautilus_task,
- G_TYPE_OBJECT)
+ GValue result;
-enum
-{
- PROP_CANCELLABLE = 1,
- N_PROPERTIES
+ GMainContext *context;
+ GQueue *callbacks;
};
-static GParamSpec *properties[N_PROPERTIES] = { NULL };
+G_DEFINE_TYPE (NautilusTask, nautilus_task, G_TYPE_OBJECT)
static void
-set_property (GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec)
+finalize (GObject *object)
{
- switch (property_id)
+ NautilusTask *self;
+
+ self = NAUTILUS_TASK (object);
+
+ if (self->closure != NULL)
{
- case PROP_CANCELLABLE:
- {
- NautilusTask *self;
- NautilusTaskPrivate *priv;
+ g_clear_pointer (&self->closure, g_closure_unref);
+ }
+ if (self->cancellable != NULL)
+ {
+ g_clear_object (&self->cancellable);
+ }
+ if (self->error != NULL)
+ {
+ g_clear_pointer (&self->error, g_error_free);
+ }
- self = NAUTILUS_TASK (object);
- priv = nautilus_task_get_instance_private (self);
+ g_queue_free (self->callbacks);
- if (G_UNLIKELY (priv->cancellable) != NULL)
- {
- g_clear_object (&priv->cancellable);
- }
+ G_OBJECT_CLASS (nautilus_task_parent_class)->finalize (object);
+}
- priv->cancellable = g_value_dup_object (value);
- }
- break;
+static void
+nautilus_task_class_init (NautilusTaskClass *klass)
+{
+ GObjectClass *object_class;
- default:
- {
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
- }
- }
+ object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = finalize;
}
static void
-finalize (GObject *object)
+nautilus_task_init (NautilusTask *self)
{
- NautilusTask *self;
- NautilusTaskPrivate *priv;
+ self->scheduler = nautilus_scheduler_get_default ();
+ self->cancellable = NULL;
+ self->error = NULL;
+ self->context = NULL;
+ self->callbacks = g_queue_new ();
+}
- self = NAUTILUS_TASK (object);
- priv = nautilus_task_get_instance_private (self);
+GMainContext *
+nautilus_task_get_main_context (NautilusTask *task)
+{
+ g_return_val_if_fail (NAUTILUS_IS_TASK (task), NULL);
- g_clear_object (&priv->cancellable);
- g_clear_pointer (&priv->context, g_main_context_unref);
+ if (task->context == NULL)
+ {
+ return NULL;
+ }
- G_OBJECT_CLASS (nautilus_task_parent_class)->finalize (object);
+ return g_main_context_ref (task->context);
+}
+
+void
+nautilus_task_set_main_context (NautilusTask *task,
+ GMainContext *context)
+{
+ g_return_if_fail (NAUTILUS_IS_TASK (task));
+ g_return_if_fail (context != NULL);
+
+ if (task->context != NULL)
+ {
+ g_main_context_unref (task->context);
+ }
+
+ task->context = g_main_context_ref (context);
}
static void
-nautilus_task_class_init (NautilusTaskClass *klass)
+nautilus_task_add_callback_closure (NautilusTask *task,
+ GClosure *closure)
{
- GObjectClass *object_class;
+ g_queue_push_tail (task->callbacks, g_closure_ref (closure));
+}
- object_class = G_OBJECT_CLASS (klass);
+void
+nautilus_task_add_callback (NautilusTask *task,
+ NautilusTaskFunc callback,
+ gpointer user_data)
+{
+ g_autoptr (GClosure) closure = NULL;
- object_class->set_property = set_property;
- object_class->finalize = finalize;
+ g_return_if_fail (NAUTILUS_IS_TASK (task));
+ g_return_if_fail (callback != NULL);
+
+ closure = g_cclosure_new (G_CALLBACK (callback), user_data, NULL);
- properties[PROP_CANCELLABLE] =
- g_param_spec_object ("cancellable", "Cancellable", "Cancellable",
- G_TYPE_CANCELLABLE,
- G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE | G_PARAM_STATIC_NAME);
+ g_closure_set_marshal (closure, g_cclosure_marshal_VOID__VOID);
- g_object_class_install_properties (object_class, N_PROPERTIES, properties);
+ nautilus_task_add_callback_closure (task, closure);
}
static void
-nautilus_task_init (NautilusTask *self)
+invoke_callbacks_iteration (gpointer data)
+{
+ NautilusTask *task;
+ g_autoptr (GClosure) closure = NULL;
+ GValue params = { 0 };
+
+ task = data;
+ closure = g_queue_pop_head (task->callbacks);
+
+ g_value_init (¶ms, G_TYPE_OBJECT);
+ g_value_set_object (¶ms, task);
+ g_closure_invoke (closure, NULL, 1, ¶ms, NULL);
+ g_closure_invalidate (closure);
+ g_value_unset (¶ms);
+}
+
+void
+nautilus_task_complete (NautilusTask *task)
{
- NautilusTaskPrivate *priv;
+ g_return_if_fail (NAUTILUS_IS_TASK (task));
+
+ while (g_queue_peek_head (task->callbacks) != NULL)
+ {
+ if (task->context != NULL)
+ {
+ NautilusScheduler *context_scheduler;
- priv = nautilus_task_get_instance_private (self);
+ context_scheduler = nautilus_context_scheduler_get_for_context (task->context);
- priv->context = g_main_context_ref_thread_default ();
+ nautilus_scheduler_queue (context_scheduler, invoke_callbacks_iteration, task);
+ }
+ else
+ {
+ invoke_callbacks_iteration (task);
+ }
+ }
}
-GCancellable *
-nautilus_task_get_cancellable (NautilusTask *task)
+GValue *
+nautilus_task_get_result (NautilusTask *task)
{
- NautilusTaskPrivate *priv;
+ g_return_val_if_fail (NAUTILUS_IS_TASK (task), NULL);
- g_return_val_if_fail (NAUTILUS_TASK (task), NULL);
+ return &task->result;
+}
- priv = nautilus_task_get_instance_private (task);
+void
+nautilus_task_set_result (NautilusTask *task,
+ GType type,
+ gpointer result)
+{
+ g_return_if_fail (NAUTILUS_IS_TASK (task));
+ g_return_if_fail (type != G_TYPE_INVALID);
+ g_return_if_fail (result != NULL);
- if (priv->cancellable == NULL)
+ if (G_VALUE_TYPE (&task->result) != G_TYPE_INVALID)
{
- return NULL;
+ g_value_unset (&task->result);
}
- return g_object_ref (priv->cancellable);
+ g_value_init (&task->result, type);
+ g_value_set_instance (&task->result, result);
+}
+
+GError *
+nautilus_task_get_error (NautilusTask *task)
+{
+ GError *error;
+
+ g_return_val_if_fail (NAUTILUS_IS_TASK (task), NULL);
+
+ error = task->error;
+ task->error = NULL;
+
+ return error;
}
void
-nautilus_task_execute (NautilusTask *task)
+nautilus_task_set_error (NautilusTask *task,
+ GError *error)
{
- NautilusTaskClass *klass;
+ g_return_if_fail (NAUTILUS_IS_TASK (task));
+ g_return_if_fail (error != NULL);
+
+ task->error = error;
+}
+void
+nautilus_task_set_scheduler (NautilusTask *task,
+ NautilusScheduler *scheduler)
+{
g_return_if_fail (NAUTILUS_IS_TASK (task));
+ g_return_if_fail (NAUTILUS_IS_SCHEDULER (scheduler));
- klass = NAUTILUS_TASK_GET_CLASS (task);
+ g_object_unref (task->scheduler);
+
+ task->scheduler = g_object_ref (scheduler);
+}
+
+static void
+nautilus_task_execute (gpointer user_data)
+{
+ NautilusTask *task;
+ GValue params = { 0 };
- g_return_if_fail (klass->execute != NULL);
+ task = user_data;
- klass->execute (task);
+ g_value_init (¶ms, G_TYPE_OBJECT);
+ g_value_set_object (¶ms, task);
+ g_closure_invoke (task->closure, NULL, 1, ¶ms, NULL);
+ g_closure_invalidate (task->closure);
+ g_clear_pointer (&task->closure, g_closure_unref);
+ g_value_unset (¶ms);
}
void
-nautilus_task_emit_signal_in_main_context (NautilusTask *task,
- guint signal_id,
- GQuark detail,
- ...)
+nautilus_task_run (NautilusTask *task)
{
- NautilusTaskPrivate *priv;
- va_list ap;
-
g_return_if_fail (NAUTILUS_IS_TASK (task));
- priv = nautilus_task_get_instance_private (task);
- va_start (ap, detail);
+ nautilus_scheduler_queue (task->scheduler,
+ NAUTILUS_CALLBACK (nautilus_task_execute),
+ g_object_ref (task));
+}
+
+GCancellable *
+nautilus_task_get_cancellable (NautilusTask *task)
+{
+ g_return_val_if_fail (NAUTILUS_IS_TASK (task), NULL);
+
+ return g_object_ref (task->cancellable);
+}
+
+NautilusTask *
+nautilus_task_new_with_closure (GClosure *closure,
+ GCancellable *cancellable)
+{
+ NautilusTask *instance;
+
+ g_return_val_if_fail (closure != NULL, NULL);
+ if (cancellable != NULL)
+ {
+ g_return_val_if_fail (G_IS_CANCELLABLE (cancellable), NULL);
+ }
+
+ instance = g_object_new (NAUTILUS_TYPE_TASK, NULL);
- nautilus_emit_signal_in_main_context_va_list (task,
- priv->context,
- signal_id,
- detail,
- ap);
+ instance->closure = g_closure_ref (closure);
+ if (cancellable != NULL)
+ {
+ instance->cancellable = g_object_ref (cancellable);
+ }
- va_end (ap);
+ return instance;
+}
+
+/* Would be nice to accept a #GDestroyNotify for @user_data,
+ * but it’s not a #GClosureNotify, ergo UB.
+ */
+NautilusTask *
+nautilus_task_new_with_func (NautilusTaskFunc func,
+ gpointer func_data,
+ GCancellable *cancellable)
+{
+ g_autoptr (GClosure) closure = NULL;
+
+ g_return_val_if_fail (func != NULL, NULL);
+
+ closure = g_cclosure_new (G_CALLBACK (func), func_data, NULL);
+
+ g_closure_set_marshal (closure, g_cclosure_marshal_VOID__VOID);
+
+ return nautilus_task_new_with_closure (closure, cancellable);
+}
+
+static void
+dummy_task_func (NautilusTask *task,
+ gpointer user_data)
+{
+ (void) task;
+ (void) user_data;
+}
+
+NautilusTask *
+nautilus_task_new (GCancellable *cancellable)
+{
+ return nautilus_task_new_with_func (dummy_task_func, NULL, cancellable);
}
diff --git a/src-ng/nautilus-task.h b/src-ng/nautilus-task.h
index 86440b3..8e3281b 100644
--- a/src-ng/nautilus-task.h
+++ b/src-ng/nautilus-task.h
@@ -19,27 +19,136 @@
#ifndef NAUTILUS_TASK_H_INCLUDED
#define NAUTILUS_TASK_H_INCLUDED
+#include "nautilus-scheduler.h"
+
#include <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)
+G_DECLARE_FINAL_TYPE (NautilusTask, nautilus_task, NAUTILUS, TASK, GObject)
+
+/**
+ * NautilusTaskFunc:
+ * @task: a #NautilusTask instance
+ * @task_data: (nullable): task data
+ */
+typedef void (*NautilusTaskFunc) (NautilusTask *task,
+ gpointer task_data);
-typedef void (*NautilusTaskCallback) (NautilusTask *task,
- gpointer user_data);
+/**
+ * nautilus_task_get_main_context:
+ * @task: an initialized #NautilusTask
+ *
+ * Returns: (nullable) (transfer full): the main context set or %NULL
+ */
+GMainContext *nautilus_task_get_main_context (NautilusTask *task);
+/**
+ * nautilus_task_set_main_context:
+ * @task: an initialized #NautilusTask
+ * @context: (transfer full): the main context
+ */
+void nautilus_task_set_main_context (NautilusTask *task,
+ GMainContext *context);
-struct _NautilusTaskClass
-{
- GObjectClass parent_class;
+/**
+ * nautilus_task_add_callback:
+ * @task: an initialized #NautilusTask
+ * @callback: the function to call when @task completes
+ * @user_data: (nullable): additional data to pass to @callback
+ */
+void nautilus_task_add_callback (NautilusTask *task,
+ NautilusTaskFunc callback,
+ gpointer user_data);
- void (*execute) (NautilusTask *task);
-};
+/**
+ * nautilus_task_complete:
+ * @task: an initialized #NautilusTask
+ */
+void nautilus_task_complete (NautilusTask *task);
+/**
+ * nautilus_task_get_result:
+ * @task: an initialized #NautilusTask
+ *
+ * Returns: (nullable) (transfer full): the set result or %NULL
+ */
+GValue *nautilus_task_get_result (NautilusTask *task);
+/**
+ * nautilus_task_set_result:
+ * @task: an initialized #NautilusTask
+ * @type: the #GType of @result
+ * @result: the result
+ */
+void nautilus_task_set_result (NautilusTask *task,
+ GType type,
+ gpointer result);
+
+/**
+ * nautilus_task_get_error:
+ * @task: an initialized #NautilusTask
+ *
+ * Returns: (nullable) (transfer full): the set #GError or %NULL
+ */
+GError *nautilus_task_get_error (NautilusTask *task);
+/**
+ * nautilus_task_set_error:
+ * @task: an initialized #NautilusTask
+ * @error: (transfer full): a #GError
+ */
+void nautilus_task_set_error (NautilusTask *task,
+ GError *error);
+
+/**
+ * nautilus_task_set_scheduler:
+ * @task: an initialized #NautilusTask
+ * @scheduler: (transfer full): the scheduler to use
+ */
+void nautilus_task_set_scheduler (NautilusTask *task,
+ NautilusScheduler *scheduler);
+
+/**
+ * nautilus_task_run:
+ * @task: an initialized #NautilusTask
+ *
+ * Schedules the task to be run asynchronously.
+ */
+void nautilus_task_run (NautilusTask *task);
+
+/**
+ * nautilus_task_get_cancellable:
+ * @task: an initialized #NautilusTask
+ *
+ * Returns: (nullable) (transfer full): a #GCancellable for @task
+ */
GCancellable *nautilus_task_get_cancellable (NautilusTask *task);
-void nautilus_task_execute (NautilusTask *task);
+/**
+ * nautilus_task_new_with_closure:
+ * @closure: (transfer full): the closure to invoke when executing
+ * @cancellable: (nullable) (transfer full): an initialized #GCancellable or %NULL
+ *
+ * Returns: a new #NautilusTask instance
+ */
+NautilusTask *nautilus_task_new_with_closure (GClosure *closure,
+ GCancellable *cancellable);
+/**
+ * nautilus_task_new_with_func:
+ * @func: the function to call when executing
+ * @func_data: (nullable): data to pass to @func
+ * @cancellable: (nullable) (transfer full): an initialized #GCancellable or %NULL
+ *
+ * Returns: a new #NautilusTask instance
+ */
+NautilusTask *nautilus_task_new_with_func (NautilusTaskFunc func,
+ gpointer func_data,
+ GCancellable *cancellable);
+/**
+ * nautilus_task_new:
+ * @cancellable: (nullable) (transfer full): an initialized #GCancellable or %NULL
+ *
+ * Returns: a new #NautilusTask instance
+ */
+NautilusTask *nautilus_task_new (GCancellable *cancellable);
#endif
diff --git a/src-ng/nautilus-tasks.c b/src-ng/nautilus-tasks.c
new file mode 100644
index 0000000..518a64b
--- /dev/null
+++ b/src-ng/nautilus-tasks.c
@@ -0,0 +1,235 @@
+/* Copyright (C) 2017 Ernestas Kulik <ernestask gnome org>
+ *
+ * This file is part of Nautilus.
+ *
+ * Nautilus is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Nautilus is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Nautilus. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include "nautilus-tasks.h"
+
+#include "nautilus-file-changes.h"
+
+#include <gdk-pixbuf/gdk-pixbuf.h>
+
+#ifndef GNOME_DESKTOP_USE_UNSTABLE_API
+#define GNOME_DESKTOP_USE_UNSTABLE_API
+#endif
+
+#include <libgnome-desktop/gnome-desktop-thumbnail.h>
+
+const char *const DEFAULT_ATTRIBUTES = "standard::*,"
+ "access::*,"
+ "mountable::*,"
+ "time::*,"
+ "unix::*,"
+ "owner::*,"
+ "selinux::*,"
+ "thumbnail::*,"
+ "id::filesystem,"
+ "trash::orig-path,"
+ "trash::deletion-date,"
+ "metadata::*,"
+ "recent::*";
+
+void
+nautilus_enumerate_children_task_func (NautilusTask *task,
+ gpointer data)
+{
+ GFile *location;
+ g_autoptr (GCancellable) cancellable = NULL;
+ GError *error = NULL;
+ g_autoptr (GFileEnumerator) enumerator = NULL;
+ GHashTable *hash_table;
+ GFileInfo *info;
+
+ location = data;
+ cancellable = nautilus_task_get_cancellable (task);
+ enumerator = g_file_enumerate_children (location, DEFAULT_ATTRIBUTES,
+ G_FILE_QUERY_INFO_NONE, cancellable, &error);
+
+ if (error != NULL)
+ {
+ nautilus_task_set_error (task, error);
+ nautilus_task_complete (task);
+
+ return;
+ }
+
+ hash_table = g_hash_table_new_full (g_file_hash, (GEqualFunc) g_file_equal,
+ g_object_unref, g_object_unref);
+
+ do
+ {
+ GFile *child;
+
+ info = g_file_enumerator_next_file (enumerator, cancellable, &error);
+
+ if (error != NULL)
+ {
+ g_hash_table_destroy (hash_table);
+
+ nautilus_task_set_error (task, error);
+ nautilus_task_complete (task);
+
+ return;
+ }
+
+ if (info != NULL)
+ {
+ child = g_file_enumerator_get_child (enumerator, info);
+
+ g_assert (g_hash_table_insert (hash_table, child, info));
+ }
+ } while (info != NULL);
+
+ nautilus_task_set_result (task, G_TYPE_HASH_TABLE, hash_table);
+ nautilus_task_complete (task);
+}
+
+void
+nautilus_load_pixbuf_func (NautilusTask *task,
+ gpointer task_data)
+{
+ GError *error = NULL;
+ GdkPixbuf *pixbuf;
+
+ pixbuf = gdk_pixbuf_new_from_file (task_data, &error);
+
+ nautilus_task_set_error (task, error);
+ nautilus_task_set_result (task, GDK_TYPE_PIXBUF, pixbuf);
+ nautilus_task_complete (task);
+}
+
+void
+nautilus_rename_task_func (NautilusTask *task,
+ gpointer task_data)
+{
+ GHashTableIter iter;
+ gpointer key;
+ gpointer value;
+ g_autoptr (GCancellable) cancellable = NULL;
+ GError *error = NULL;
+
+ g_hash_table_iter_init (&iter, (GHashTable *) task_data);
+
+ while (g_hash_table_iter_next (&iter, &key, &value))
+ {
+ GFile *location_from;
+ GFile *location_to;
+
+ location_from = G_FILE (key);
+ location_to = g_file_set_display_name (location_from,
+ (const gchar *) value,
+ cancellable, &error);
+
+ if (location_to != NULL)
+ {
+ nautilus_notify_file_renamed (location_from, location_to);
+ }
+ else
+ {
+ }
+ }
+
+ nautilus_task_complete (task);
+}
+
+static gpointer
+create_thumbnail_factory (gpointer data)
+{
+ (void) data;
+
+ return gnome_desktop_thumbnail_factory_new (GNOME_DESKTOP_THUMBNAIL_SIZE_LARGE);
+}
+
+static GnomeDesktopThumbnailFactory *
+get_thumbnail_factory (void)
+{
+ static GOnce once = G_ONCE_INIT;
+
+ g_once (&once, create_thumbnail_factory, NULL);
+
+ return once.retval;
+}
+
+void
+nautilus_thumbnail_task_func (NautilusTask *task,
+ gpointer task_data)
+{
+ GFile *location;
+ GnomeDesktopThumbnailFactory *thumbnail_factory;
+ g_autofree gchar *uri = NULL;
+ g_autoptr (GFileInfo) file_info = NULL;
+ const gchar *content_type;
+ guint64 mtime;
+ GdkPixbuf *pixbuf;
+
+ location = task_data;
+ thumbnail_factory = get_thumbnail_factory ();
+ uri = g_file_get_uri (location);
+ file_info = g_file_query_info (location,
+ G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE ","
+ G_FILE_ATTRIBUTE_TIME_MODIFIED,
+ G_FILE_QUERY_INFO_NONE,
+ NULL, NULL);
+ content_type = g_file_info_get_content_type (file_info);
+ mtime = g_file_info_get_attribute_uint64 (file_info,
+ G_FILE_ATTRIBUTE_TIME_MODIFIED);
+
+ if (!gnome_desktop_thumbnail_factory_can_thumbnail (thumbnail_factory,
+ uri, content_type,
+ mtime))
+ {
+ nautilus_task_complete (task);
+ return;
+ }
+
+ pixbuf = gnome_desktop_thumbnail_factory_generate_thumbnail (thumbnail_factory,
+ uri,
+ content_type);
+
+ if (pixbuf != NULL)
+ {
+ gnome_desktop_thumbnail_factory_save_thumbnail (thumbnail_factory,
+ pixbuf, uri, mtime);
+ }
+ else
+ {
+ gnome_desktop_thumbnail_factory_create_failed_thumbnail (thumbnail_factory,
+ uri, mtime);
+ }
+
+ nautilus_task_set_result (task, GDK_TYPE_PIXBUF, g_object_ref (pixbuf));
+ nautilus_task_complete (task);
+}
+
+void
+nautilus_query_info_func (NautilusTask *task,
+ gpointer task_data)
+{
+ g_autoptr (GCancellable) cancellable = NULL;
+ GError *error = NULL;
+ GFileInfo *info;
+
+ cancellable = nautilus_task_get_cancellable (task);
+ info = g_file_query_info (task_data,
+ DEFAULT_ATTRIBUTES,
+ G_FILE_QUERY_INFO_NONE,
+ cancellable,
+ &error);
+
+ nautilus_task_set_error (task, error);
+ nautilus_task_set_result (task, G_TYPE_FILE_INFO, info);
+ nautilus_task_complete (task);
+}
diff --git a/src-ng/tasks/nautilus-attribute-task.h b/src-ng/nautilus-tasks.h
similarity index 51%
rename from src-ng/tasks/nautilus-attribute-task.h
rename to src-ng/nautilus-tasks.h
index c2d5848..3ead615 100644
--- a/src-ng/tasks/nautilus-attribute-task.h
+++ b/src-ng/nautilus-tasks.h
@@ -16,22 +16,20 @@
* along with Nautilus. If not, see <https://www.gnu.org/licenses/>.
*/
-#ifndef NAUTILUS_ATTRIBUTE_TASK_H_INCLUDED
-#define NAUTILUS_ATTRIBUTE_TASK_H_INCLUDED
+#ifndef NAUTILUS_TASKS_H_INCLUDED
+#define NAUTILUS_TASKS_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);
+void nautilus_enumerate_children_task_func (NautilusTask *task,
+ gpointer task_data);
+void nautilus_load_pixbuf_func (NautilusTask *task,
+ gpointer task_data);
+void nautilus_rename_task_func (NautilusTask *task,
+ gpointer task_data);
+void nautilus_thumbnail_task_func (NautilusTask *task,
+ gpointer task_data);
+void nautilus_query_info_func (NautilusTask *task,
+ gpointer task_data);
#endif
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]