1 /* This file is part of GEGL
2  *
3  * GEGL is free software; you can redistribute it and/or
4  * modify it under the terms of the GNU Lesser General Public
5  * License as published by the Free Software Foundation; either
6  * version 3 of the License, or (at your option) any later version.
7  *
8  * GEGL is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11  * Lesser General Public License for more details.
12  *
13  * You should have received a copy of the GNU Lesser General Public
14  * License along with GEGL; if not, see <https://www.gnu.org/licenses/>.
15  *
16  * Copyright 2014 Øyvind Kolås
17  */
18 
19 #include "config.h"
20 
21 #include <glib-object.h>
22 #include <string.h>
23 
24 #include "gegl.h"
25 #include "gegl-operation.h"
26 #include "gegl-operations.h"
27 #include "gegl-operation-property-keys.h"
28 
29 static GHashTable *
gegl_param_spec_get_property_key_ht(GParamSpec * pspec,gboolean create)30 gegl_param_spec_get_property_key_ht (GParamSpec  *pspec,
31                                      gboolean     create)
32 {
33   GHashTable *ret = NULL;
34   if (pspec)
35     {
36       GQuark quark = g_quark_from_static_string ("gegl-property-keys");
37       ret = g_param_spec_get_qdata (pspec, quark);
38       if (!ret && create)
39       {
40         ret = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
41         g_param_spec_set_qdata_full (pspec, quark, ret,
42                                      (GDestroyNotify)g_hash_table_unref);
43       }
44     }
45   return ret;
46 }
47 
48 const gchar *
gegl_param_spec_get_property_key(GParamSpec * pspec,const gchar * key_name)49 gegl_param_spec_get_property_key (GParamSpec  *pspec,
50                                   const gchar *key_name)
51 {
52   GHashTable *ht;
53   ht = gegl_param_spec_get_property_key_ht (pspec, FALSE);
54   if (ht)
55     return g_hash_table_lookup (ht, key_name);
56   return NULL;
57 }
58 
59 void
gegl_param_spec_set_property_key(GParamSpec * pspec,const gchar * key_name,const gchar * value)60 gegl_param_spec_set_property_key (GParamSpec  *pspec,
61                                   const gchar *key_name,
62                                   const gchar *value)
63 {
64   GHashTable *ht;
65   ht = gegl_param_spec_get_property_key_ht (pspec, TRUE);
66 
67   if (value)
68     g_hash_table_insert (ht, g_strdup (key_name), g_strdup (value));
69   else
70     g_hash_table_remove (ht, key_name);
71 }
72 
73 static GHashTable *
gegl_operation_class_get_property_key_ht(GeglOperationClass * operation_class,const gchar * property_name,gboolean create)74 gegl_operation_class_get_property_key_ht (GeglOperationClass *operation_class,
75                                           const gchar        *property_name,
76                                           gboolean            create)
77 {
78   GParamSpec *pspec;
79   pspec = g_object_class_find_property (G_OBJECT_CLASS (operation_class),
80                                         property_name);
81   if (pspec)
82     return gegl_param_spec_get_property_key_ht (pspec, create);
83   return NULL;
84 }
85 
86 gchar **
gegl_operation_list_property_keys(const gchar * operation_name,const gchar * property_name,guint * n_keys)87 gegl_operation_list_property_keys (const gchar *operation_name,
88                                    const gchar *property_name,
89                                    guint       *n_keys)
90 {
91   GType         type;
92   GObjectClass *klass;
93   GHashTable   *ht = NULL;
94   GList        *list, *l;
95   gchar       **ret;
96   int count;
97   int i;
98   type = gegl_operation_gtype_from_name (operation_name);
99   if (!type)
100     {
101       if (n_keys)
102         *n_keys = 0;
103       return NULL;
104     }
105   klass  = g_type_class_ref (type);
106   ht = gegl_operation_class_get_property_key_ht (GEGL_OPERATION_CLASS (klass),
107                                                  property_name, FALSE);
108   if (!ht)
109   {
110     count = 0;
111     ret = g_malloc0 (sizeof (gpointer));;
112   }
113   else
114   {
115     count = g_hash_table_size (ht);
116     ret = g_malloc0 (sizeof (gpointer) * (count + 1));
117     list = g_hash_table_get_keys (ht);
118     for (i = 0, l = list; l; l = l->next, i++)
119       {
120         ret[i] = l->data;
121       }
122     g_list_free (list);
123   }
124   if (n_keys)
125     *n_keys = count;
126   g_type_class_unref (klass);
127   return ret;
128 }
129 
130 void
gegl_operation_class_set_property_key(GeglOperationClass * operation_class,const gchar * property_name,const gchar * key_name,const gchar * value)131 gegl_operation_class_set_property_key (GeglOperationClass *operation_class,
132                                        const gchar        *property_name,
133                                        const gchar        *key_name,
134                                        const gchar        *value)
135 {
136   GParamSpec *pspec;
137   pspec = g_object_class_find_property (G_OBJECT_CLASS (operation_class),
138                                         property_name);
139   if (pspec)
140     gegl_param_spec_set_property_key (pspec, key_name, value);
141 }
142 
143 
144 const gchar *
gegl_operation_class_get_property_key(GeglOperationClass * operation_class,const gchar * property_name,const gchar * key_name)145 gegl_operation_class_get_property_key (GeglOperationClass *operation_class,
146                                        const gchar        *property_name,
147                                        const gchar        *key_name)
148 {
149   GParamSpec *pspec;
150   pspec = g_object_class_find_property (G_OBJECT_CLASS (operation_class),
151                                         property_name);
152   if (pspec)
153     return gegl_param_spec_get_property_key (pspec, key_name);
154   return NULL;
155 }
156 
157 const gchar *
gegl_operation_get_property_key(const gchar * operation_name,const gchar * property_name,const gchar * property_key_name)158 gegl_operation_get_property_key (const gchar *operation_name,
159                                  const gchar *property_name,
160                                  const gchar *property_key_name)
161 {
162   GType         type;
163   GObjectClass *klass;
164   const gchar  *ret = NULL;
165   type = gegl_operation_gtype_from_name (operation_name);
166   if (!type)
167     {
168       return NULL;
169     }
170   klass  = g_type_class_ref (type);
171   ret = gegl_operation_class_get_property_key (GEGL_OPERATION_CLASS (klass),
172                                                property_name,
173                                                property_key_name);
174   g_type_class_unref (klass);
175   return ret;
176 }
177