[nautilus/wip/antoniof/extension-properties: 12/21] libnautilus-extension: Introduce model-based properties extensions




commit 6e8219e429326e4ddc386c07dd0f32220b0e0e43
Author: António Fernandes <antoniof gnome org>
Date:   Fri Aug 5 19:40:17 2022 +0100

    libnautilus-extension: Introduce model-based properties extensions
    
    This is meant to replace the existing GtkWidget-based solution.
    
    Part of https://gitlab.gnome.org/GNOME/nautilus/-/issues/2365

 libnautilus-extension/meson.build                  |   6 +
 libnautilus-extension/nautilus-extension.h         |   3 +
 libnautilus-extension/nautilus-properties-item.c   | 149 ++++++++++++++++++
 libnautilus-extension/nautilus-properties-item.h   |  61 ++++++++
 .../nautilus-properties-model-provider.c           |  29 ++++
 .../nautilus-properties-model-provider.h           |  66 ++++++++
 libnautilus-extension/nautilus-properties-model.c  | 167 +++++++++++++++++++++
 libnautilus-extension/nautilus-properties-model.h  |  71 +++++++++
 8 files changed, 552 insertions(+)
---
diff --git a/libnautilus-extension/meson.build b/libnautilus-extension/meson.build
index 8450873de..27f21a5b5 100644
--- a/libnautilus-extension/meson.build
+++ b/libnautilus-extension/meson.build
@@ -7,6 +7,9 @@ libnautilus_extension_headers = [
   'nautilus-info-provider.h',
   'nautilus-location-widget-provider.h',
   'nautilus-menu-provider.h',
+  'nautilus-properties-model-provider.h',
+  'nautilus-properties-model.h',
+  'nautilus-properties-item.h',
   'nautilus-property-page-provider.h',
   'nautilus-property-page.h',
   'nautilus-menu.h'
@@ -42,6 +45,9 @@ libnautilus_extension_sources = [
   'nautilus-location-widget-provider.c',
   'nautilus-menu-item.c',
   'nautilus-menu-provider.c',
+  'nautilus-properties-model-provider.c',
+  'nautilus-properties-model.c',
+  'nautilus-properties-item.c',
   'nautilus-property-page-provider.c',
   'nautilus-property-page.c',
   'nautilus-menu.c'
diff --git a/libnautilus-extension/nautilus-extension.h b/libnautilus-extension/nautilus-extension.h
index 894322eb9..af3f67837 100644
--- a/libnautilus-extension/nautilus-extension.h
+++ b/libnautilus-extension/nautilus-extension.h
@@ -26,6 +26,9 @@
 #include <libnautilus-extension/nautilus-location-widget-provider.h>
 #include <libnautilus-extension/nautilus-menu.h>
 #include <libnautilus-extension/nautilus-menu-provider.h>
+#include <libnautilus-extension/nautilus-properties-model.h>
+#include <libnautilus-extension/nautilus-properties-model-provider.h>
+#include <libnautilus-extension/nautilus-properties-item.h>
 #include <libnautilus-extension/nautilus-property-page.h>
 #include <libnautilus-extension/nautilus-property-page-provider.h>
 
diff --git a/libnautilus-extension/nautilus-properties-item.c 
b/libnautilus-extension/nautilus-properties-item.c
new file mode 100644
index 000000000..8731274a4
--- /dev/null
+++ b/libnautilus-extension/nautilus-properties-item.c
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2022 António Fernandes <antoniof gnome org>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include <config.h>
+#include "nautilus-properties-item.h"
+
+enum
+{
+    PROP_0,
+    PROP_NAME,
+    PROP_VALUE,
+    LAST_PROP
+};
+
+struct _NautilusPropertiesItem
+{
+    GObject parent_instance;
+
+    char *name;
+    char *value;
+};
+
+G_DEFINE_TYPE (NautilusPropertiesItem, nautilus_properties_item, G_TYPE_OBJECT)
+
+NautilusPropertiesItem *
+nautilus_properties_item_new (const char *name,
+                              const char *value)
+{
+    g_return_val_if_fail (name != NULL, NULL);
+    g_return_val_if_fail (name != NULL, NULL);
+
+    return g_object_new (NAUTILUS_TYPE_PROPERTIES_ITEM,
+                         "name", name,
+                         "value", value,
+                         NULL);
+}
+
+static void
+nautilus_properties_item_get_property (GObject    *object,
+                                       guint       param_id,
+                                       GValue     *value,
+                                       GParamSpec *pspec)
+{
+    NautilusPropertiesItem *self = NAUTILUS_PROPERTIES_ITEM (object);
+
+    switch (param_id)
+    {
+        case PROP_NAME:
+        {
+            g_value_set_string (value, self->name);
+        }
+        break;
+
+        case PROP_VALUE:
+        {
+            g_value_set_string (value, self->value);
+        }
+        break;
+
+        default:
+        {
+            G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+        }
+        break;
+    }
+}
+
+static void
+nautilus_properties_item_set_property (GObject      *object,
+                                       guint         param_id,
+                                       const GValue *value,
+                                       GParamSpec   *pspec)
+{
+    NautilusPropertiesItem *self = NAUTILUS_PROPERTIES_ITEM (object);
+
+    switch (param_id)
+    {
+        case PROP_NAME:
+        {
+            g_free (self->name);
+            self->name = g_value_dup_string (value);
+        }
+        break;
+
+        case PROP_VALUE:
+        {
+            g_free (self->value);
+            self->value = g_value_dup_string (value);
+        }
+        break;
+
+        default:
+        {
+            G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+        }
+        break;
+    }
+}
+
+static void
+nautilus_properties_item_finalize (GObject *object)
+{
+    NautilusPropertiesItem *self = NAUTILUS_PROPERTIES_ITEM (object);
+
+    g_free (self->name);
+    g_free (self->value);
+
+    G_OBJECT_CLASS (nautilus_properties_item_parent_class)->finalize (object);
+}
+
+static void
+nautilus_properties_item_init (NautilusPropertiesItem *self)
+{
+}
+
+static void
+nautilus_properties_item_class_init (NautilusPropertiesItemClass *class)
+{
+    GParamSpec *pspec;
+
+    G_OBJECT_CLASS (class)->finalize = nautilus_properties_item_finalize;
+    G_OBJECT_CLASS (class)->get_property = nautilus_properties_item_get_property;
+    G_OBJECT_CLASS (class)->set_property = nautilus_properties_item_set_property;
+
+    pspec = g_param_spec_string ("name", "", "",
+                                 NULL,
+                                 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+    g_object_class_install_property (G_OBJECT_CLASS (class), PROP_NAME, pspec);
+
+    pspec = g_param_spec_string ("value", "", "",
+                                 NULL,
+                                 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+    g_object_class_install_property (G_OBJECT_CLASS (class), PROP_VALUE, pspec);
+}
+
+const char *
+nautilus_properties_item_get_name (NautilusPropertiesItem *self)
+{
+    return self->name;
+}
+
+const char *
+nautilus_properties_item_get_value (NautilusPropertiesItem *self)
+{
+    return self->value;
+}
diff --git a/libnautilus-extension/nautilus-properties-item.h 
b/libnautilus-extension/nautilus-properties-item.h
new file mode 100644
index 000000000..5191816cd
--- /dev/null
+++ b/libnautilus-extension/nautilus-properties-item.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2022 António Fernandes <antoniof gnome org>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#pragma once
+
+#if !defined (NAUTILUS_EXTENSION_H) && !defined (NAUTILUS_COMPILATION)
+#warning "Only <nautilus-extension.h> should be included directly."
+#endif
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define NAUTILUS_TYPE_PROPERTIES_ITEM (nautilus_properties_item_get_type ())
+
+G_DECLARE_FINAL_TYPE (NautilusPropertiesItem,
+                      nautilus_properties_item,
+                      NAUTILUS, PROPERTIES_ITEM,
+                      GObject)
+
+/**
+ * SECTION:nautilus-properties-item
+ * @name: NautilusPropertiesItem
+ * @value: Properties item descriptor object
+ *
+ * #NautilusPropertiesItem is an object that describes a name & value pair in
+ * file properties. Extensions can provide #NautilusPropertiesItem objects in
+ * models provided by #NautilusPropertiesModel.
+ */
+
+/**
+ * nautilus_properties_item_new:
+ * @name: the user-visible name for the properties item.
+ * @model: the user-visible value for the properties item.
+ *
+ * Returns: (transfer full): a new #NautilusPropertiesItem
+ */
+NautilusPropertiesItem *nautilus_properties_item_new (const char *name,
+                                                      const char *value);
+
+/**
+ * nautilus_properties_item_get_name:
+ * @item: the properties item
+ *
+ * Returns: (transfer none): the name of this #NautilusPropertiesItem
+ */
+const char *nautilus_properties_item_get_name (NautilusPropertiesItem *self);
+
+/**
+ * nautilus_properties_item_get_value:
+ * @item: the properties item
+ *
+ * Returns: (transfer none): the value of this #NautilusPropertiesItem
+ */
+const char * nautilus_properties_item_get_value (NautilusPropertiesItem *self);
+
+
+G_END_DECLS
diff --git a/libnautilus-extension/nautilus-properties-model-provider.c 
b/libnautilus-extension/nautilus-properties-model-provider.c
new file mode 100644
index 000000000..4ade1105c
--- /dev/null
+++ b/libnautilus-extension/nautilus-properties-model-provider.c
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2022 The GNOME project contributors
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "nautilus-properties-model-provider.h"
+
+G_DEFINE_INTERFACE (NautilusPropertiesModelProvider, nautilus_properties_model_provider, G_TYPE_OBJECT)
+
+static void
+nautilus_properties_model_provider_default_init (NautilusPropertiesModelProviderInterface *klass)
+{
+}
+
+GList *
+nautilus_properties_model_provider_get_models (NautilusPropertiesModelProvider *self,
+                                               GList                           *files)
+{
+    NautilusPropertiesModelProviderInterface *iface;
+
+    g_return_val_if_fail (NAUTILUS_IS_PROPERTIES_MODEL_PROVIDER (self), NULL);
+
+    iface = NAUTILUS_PROPERTIES_MODEL_PROVIDER_GET_IFACE (self);
+
+    g_return_val_if_fail (iface->get_models != NULL, NULL);
+
+    return iface->get_models (self, files);
+}
diff --git a/libnautilus-extension/nautilus-properties-model-provider.h 
b/libnautilus-extension/nautilus-properties-model-provider.h
new file mode 100644
index 000000000..6caebd113
--- /dev/null
+++ b/libnautilus-extension/nautilus-properties-model-provider.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2022 The GNOME project contributors
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#pragma once
+
+#if !defined (NAUTILUS_EXTENSION_H) && !defined (NAUTILUS_COMPILATION)
+#warning "Only <nautilus-extension.h> should be included directly."
+#endif
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define NAUTILUS_TYPE_PROPERTIES_MODEL_PROVIDER (nautilus_properties_model_provider_get_type ())
+
+G_DECLARE_INTERFACE (NautilusPropertiesModelProvider,
+                     nautilus_properties_model_provider,
+                     NAUTILUS, PROPERTIES_MODEL_PROVIDER,
+                     GObject)
+
+/**
+ * SECTION:nautilus-properties-model-provider
+ * @title: NautilusPropertiesModelProvider
+ * @short_description: Interface to provide additional properties
+ *
+ * #NautilusPropertiesModelProvider allows extension to provide additional
+ * information for the file properties.
+ */
+
+/**
+ * NautilusPropertiesModelProviderInterface:
+ * @g_iface: The parent interface.
+ * @get_models: Returns a #GList of #NautilusPropertiesModel.
+ *   See nautilus_properties_model_provider_get_models() for details.
+ *
+ * Interface for extensions to provide additional properties.
+ */
+struct _NautilusPropertiesModelProviderInterface
+{
+    GTypeInterface g_iface;
+
+    GList *(*get_models) (NautilusPropertiesModelProvider *provider,
+                          GList                           *files);
+};
+
+/**
+ * nautilus_properties_model_provider_get_models:
+ * @provider: a #NautilusPropertiesModelProvider
+ * @files: (element-type NautilusFileInfo): a #GList of #NautilusFileInfo
+ *
+ * This function is called by the application when it wants properties models
+ * from the extension.
+ *
+ * This function is called in the main thread before the Properties are shown,
+ * so it should return quickly. The models can be populated and updated
+ * asynchronously.
+ *
+ * Returns: (nullable) (element-type NautilusPropertyModel) (transfer full): A #GList of allocated 
#NautilusPropertiesModel models.
+ */
+GList *nautilus_properties_model_provider_get_models (NautilusPropertiesModelProvider *provider,
+                                                      GList                           *files);
+
+G_END_DECLS
diff --git a/libnautilus-extension/nautilus-properties-model.c 
b/libnautilus-extension/nautilus-properties-model.c
new file mode 100644
index 000000000..b222ae047
--- /dev/null
+++ b/libnautilus-extension/nautilus-properties-model.c
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2022 The GNOME project contributors
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include <config.h>
+#include "nautilus-properties-model.h"
+#include "nautilus-properties-item.h"
+
+enum
+{
+    PROP_0,
+    PROP_TITLE,
+    PROP_MODEL,
+    LAST_PROP
+};
+
+struct _NautilusPropertiesModel
+{
+    GObject parent_instance;
+
+    char *title;
+    GListModel *model;
+};
+
+G_DEFINE_TYPE (NautilusPropertiesModel, nautilus_properties_model, G_TYPE_OBJECT)
+
+NautilusPropertiesModel *
+nautilus_properties_model_new (const char *title,
+                               GListModel *model)
+{
+    g_return_val_if_fail (title != NULL, NULL);
+    g_return_val_if_fail (G_IS_LIST_MODEL (model), NULL);
+    g_return_val_if_fail (g_list_model_get_item_type (model) == NAUTILUS_TYPE_PROPERTIES_ITEM, NULL);
+
+    return g_object_new (NAUTILUS_TYPE_PROPERTIES_MODEL,
+                         "title", title,
+                         "model", model,
+                         NULL);
+}
+
+static void
+nautilus_properties_model_get_property (GObject    *object,
+                                        guint       param_id,
+                                        GValue     *value,
+                                        GParamSpec *pspec)
+{
+    NautilusPropertiesModel *self = NAUTILUS_PROPERTIES_MODEL (object);
+
+    switch (param_id)
+    {
+        case PROP_TITLE:
+        {
+            g_value_set_string (value, self->title);
+        }
+        break;
+
+        case PROP_MODEL:
+        {
+            g_value_set_object (value, self->model);
+        }
+        break;
+
+        default:
+        {
+            G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+        }
+        break;
+    }
+}
+
+static void
+nautilus_properties_model_set_property (GObject      *object,
+                                        guint         param_id,
+                                        const GValue *value,
+                                        GParamSpec   *pspec)
+{
+    NautilusPropertiesModel *self = NAUTILUS_PROPERTIES_MODEL (object);
+
+    switch (param_id)
+    {
+        case PROP_TITLE:
+        {
+            g_free (self->title);
+            self->title = g_value_dup_string (value);
+        }
+        break;
+
+        case PROP_MODEL:
+        {
+            g_set_object (&self->model, g_value_get_object (value));
+        }
+        break;
+
+        default:
+        {
+            G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
+        }
+        break;
+    }
+}
+
+static void
+nautilus_properties_model_dispose (GObject *object)
+{
+    NautilusPropertiesModel *self = NAUTILUS_PROPERTIES_MODEL (object);
+
+    g_clear_object (&self->model);
+
+    G_OBJECT_CLASS (nautilus_properties_model_parent_class)->dispose (object);
+}
+
+static void
+nautilus_properties_model_finalize (GObject *object)
+{
+    NautilusPropertiesModel *self = NAUTILUS_PROPERTIES_MODEL (object);
+
+    g_free (self->title);
+
+    G_OBJECT_CLASS (nautilus_properties_model_parent_class)->finalize (object);
+}
+
+static void
+nautilus_properties_model_init (NautilusPropertiesModel *self)
+{
+}
+
+static void
+nautilus_properties_model_class_init (NautilusPropertiesModelClass *class)
+{
+    GParamSpec *pspec;
+
+    G_OBJECT_CLASS (class)->finalize = nautilus_properties_model_finalize;
+    G_OBJECT_CLASS (class)->dispose = nautilus_properties_model_dispose;
+    G_OBJECT_CLASS (class)->get_property = nautilus_properties_model_get_property;
+    G_OBJECT_CLASS (class)->set_property = nautilus_properties_model_set_property;
+
+    pspec = g_param_spec_string ("title", "", "",
+                                 NULL,
+                                 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+    g_object_class_install_property (G_OBJECT_CLASS (class), PROP_TITLE, pspec);
+
+    pspec = g_param_spec_object ("model", "", "",
+                                 G_TYPE_LIST_MODEL,
+                                 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+    g_object_class_install_property (G_OBJECT_CLASS (class), PROP_MODEL, pspec);
+}
+
+const char *
+nautilus_properties_model_get_title (NautilusPropertiesModel *self)
+{
+    return self->title;
+}
+
+void
+nautilus_properties_model_set_title (NautilusPropertiesModel *self,
+                                     const char              *title)
+{
+    g_object_set (self, "title", title, NULL);
+}
+
+GListModel *
+nautilus_properties_model_get_model (NautilusPropertiesModel *self)
+{
+    return self->model;
+}
diff --git a/libnautilus-extension/nautilus-properties-model.h 
b/libnautilus-extension/nautilus-properties-model.h
new file mode 100644
index 000000000..3b60ba928
--- /dev/null
+++ b/libnautilus-extension/nautilus-properties-model.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2022 The GNOME project contributors
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#pragma once
+
+#if !defined (NAUTILUS_EXTENSION_H) && !defined (NAUTILUS_COMPILATION)
+#warning "Only <nautilus-extension.h> should be included directly."
+#endif
+
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#define NAUTILUS_TYPE_PROPERTIES_MODEL (nautilus_properties_model_get_type ())
+
+G_DECLARE_FINAL_TYPE (NautilusPropertiesModel,
+                      nautilus_properties_model,
+                      NAUTILUS, PROPERTIES_MODEL,
+                      GObject)
+
+/**
+ * SECTION:nautilus-properties-model
+ * @title: NautilusPropertiesModel
+ * @short_description: Properties set descriptor model
+ *
+ * #NautilusPropertiesModel is an model that describes a set of file properties.
+ * Extensions can provide #NautilusPropertiesModel objects by registering a
+ * #NautilusPropertiesModelProvider and returning them from
+ * nautilus_properties_model_provider_get_models(), which will be called by
+ * the main application when creating file properties.
+ */
+
+/**
+ * nautilus_properties_model_new:
+ * @title: the user-visible name for the set of properties in this model
+ * @model: a #GListModel containing #NautilusPropertyItem objects.
+ *
+ * Returns: (transfer full): a new #NautilusPropertiesModel
+ */
+NautilusPropertiesModel *nautilus_properties_model_new (const char *title,
+                                                        GListModel *model);
+
+/**
+ * nautilus_properties_model_get_title:
+ * @self: the properties model
+ *
+ * Returns: (transfer none): the title of this #NautilusPropertiesModel
+ */
+const char *nautilus_properties_model_get_title (NautilusPropertiesModel *self);
+
+/**
+ * nautilus_properties_model_set_title:
+ * @self: the properties model
+ * @title: the new title of this #NautilusPropertiesModel
+ */
+void nautilus_properties_model_set_title (NautilusPropertiesModel *self,
+                                          const char              *title);
+
+/**
+ * nautilus_properties_model_get_model:
+ * @self: the properties model
+ *
+ * Returns: (transfer none): a #GListModel containing #NautilusPropertiesItem.
+ */
+GListModel * nautilus_properties_model_get_model (NautilusPropertiesModel *self);
+
+
+G_END_DECLS


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