1 #include <stdlib.h>
2 #include <glib/gprintf.h>
3 #include "MakerDialogUtil.h"
4 #include "MakerDialogProperty.h"
5
6 /*============================================
7 * PropertyContext Methods
8 */
9
property_context_default(PropertyContext * ctx)10 void property_context_default(PropertyContext * ctx)
11 {
12 if (ctx->spec->defaultValue == NULL)
13 return;
14 mkdg_log(DEBUG, "property_context_default(%s)", ctx->spec->key);
15 gboolean ret =
16 property_context_from_string(ctx, ctx->spec->defaultValue);
17 if (!ret) {
18 mkdg_log(WARN,
19 "property_context_default(%s): failed to convert string %s, return NULL",
20 ctx->spec->key, ctx->spec->defaultValue);
21 }
22 }
23
property_context_new(MkdgPropertySpec * spec,MkdgBackend * backend,gpointer parent,gpointer auxData)24 PropertyContext *property_context_new(MkdgPropertySpec * spec,
25 MkdgBackend * backend,
26 gpointer parent, gpointer auxData)
27 {
28 if (spec == NULL) {
29 return NULL;
30 }
31 mkdg_log(INFO, "property_context_new(%s,-,-,-)", spec->key);
32 PropertyContext *ctx = g_new0(PropertyContext, 1);
33 ctx->spec = spec;
34 ctx->backend = backend;
35 ctx->parent = parent;
36 ctx->auxData = auxData;
37 g_value_init(&(ctx->value), ctx->spec->valueType);
38 if (ctx->backend != NULL) {
39 GValue *value = property_context_read(ctx, NULL);
40 if (value == NULL) {
41 property_context_default(ctx);
42 }
43 } else {
44 property_context_default(ctx);
45 }
46 mkdg_log(DEBUG, "property_context_new(%s):Done", ctx->spec->key);
47 return ctx;
48 }
49
property_context_to_string(PropertyContext * ctx)50 gchar *property_context_to_string(PropertyContext * ctx)
51 {
52 if (ctx == NULL) {
53 return NULL;
54 }
55 return mkdg_g_value_to_string(&(ctx->value));
56 }
57
property_context_from_string(PropertyContext * ctx,const gchar * str)58 gboolean property_context_from_string(PropertyContext * ctx,
59 const gchar * str)
60 {
61 if (ctx == NULL) {
62 return FALSE;
63 }
64 return mkdg_g_value_from_string(&(ctx->value), str);
65 }
66
property_context_from_gvalue(PropertyContext * ctx,GValue * value)67 gboolean property_context_from_gvalue(PropertyContext * ctx,
68 GValue * value)
69 {
70 if (ctx == NULL) {
71 return FALSE;
72 }
73 if (!G_IS_VALUE(value)) {
74 return FALSE;
75 }
76 g_value_copy(value, &(ctx->value));
77 return TRUE;
78 }
79
80 /* read: backend -> Context */
81 /* write: Context -> backend */
82 /* get: Context -> GValue */
83 /* set: GValue -> Context */
84 /* load: read then get, errors in read are ignored */
85 /* save: set then write */
86 /* apply: Context -> apply callback */
87 /* use: load then apply */
88 /* assign: save then apply */
property_context_read(PropertyContext * ctx,gpointer userData)89 GValue *property_context_read(PropertyContext * ctx, gpointer userData)
90 {
91 if (ctx == NULL) {
92 return NULL;
93 }
94 mkdg_log(DEBUG, "property_context_read(%s,-)", ctx->spec->key);
95 if (mkdg_has_flag
96 (ctx->spec->propertyFlags, MKDG_PROPERTY_FLAG_NO_BACKEND)) {
97 return NULL;
98 }
99 if (ctx->backend == NULL) {
100 return NULL;
101 }
102 GValue *result = mkdg_backend_read(ctx->backend, &(ctx->value),
103 ctx->spec->subSection,
104 ctx->spec->key, userData);
105
106 if (result == NULL) {
107 mkdg_log(WARN, "property_context_read(%s): failed to read key",
108 ctx->spec->key);
109 }
110 return result;
111 }
112
property_context_write(PropertyContext * ctx,gpointer userData)113 gboolean property_context_write(PropertyContext * ctx, gpointer userData)
114 {
115 if (ctx == NULL) {
116 return FALSE;
117 }
118 mkdg_log(DEBUG, "property_context_read(%s,-)", ctx->spec->key);
119 if (mkdg_has_flag
120 (ctx->spec->propertyFlags, MKDG_PROPERTY_FLAG_NO_BACKEND)) {
121 return FALSE;
122 }
123 if (ctx->backend == NULL) {
124 return FALSE;
125 }
126 return ctx->backend->writeFunc(ctx->backend, &(ctx->value),
127 ctx->spec->subSection, ctx->spec->key,
128 userData);
129 }
130
property_context_get(PropertyContext * ctx)131 GValue *property_context_get(PropertyContext * ctx)
132 {
133 if (ctx == NULL) {
134 mkdg_log(WARN, "property_context_get(-): ctx is NULL");
135 return NULL;
136 }
137 mkdg_log(DEBUG, "property_context_get(%s): value=%s",
138 ctx->spec->key, mkdg_g_value_to_string(&(ctx->value)));
139 return &(ctx->value);
140 }
141
property_context_set(PropertyContext * ctx,GValue * value)142 gboolean property_context_set(PropertyContext * ctx, GValue * value)
143 {
144 if (ctx == NULL) {
145 mkdg_log(WARN, "property_context_set(-): ctx is NULL");
146 return FALSE;
147 }
148 if (!G_IS_VALUE(value)) {
149 mkdg_log(WARN, "property_context_set(%s): value is not GValue",
150 ctx->spec->key);
151 return FALSE;
152 }
153 mkdg_log(DEBUG, "property_context_set(%s,%s)", ctx->spec->key,
154 mkdg_g_value_to_string(value));
155 g_value_copy(value, &(ctx->value));
156 return TRUE;
157 }
158
property_context_load(PropertyContext * ctx,gpointer userData)159 GValue *property_context_load(PropertyContext * ctx, gpointer userData)
160 {
161 mkdg_log(DEBUG, "property_context_load(%s,-)", ctx->spec->key);
162 property_context_read(ctx, userData);
163 return property_context_get(ctx);
164 }
165
property_context_save(PropertyContext * ctx,GValue * value,gpointer userData)166 gboolean property_context_save(PropertyContext * ctx, GValue * value,
167 gpointer userData)
168 {
169 mkdg_log(DEBUG, "property_context_save(%s,-)", ctx->spec->key);
170 if (!property_context_set(ctx, value)) {
171 return FALSE;
172 }
173 return property_context_write(ctx, userData);
174 }
175
property_context_apply(PropertyContext * ctx,gpointer userData)176 gboolean property_context_apply(PropertyContext * ctx, gpointer userData)
177 {
178 if (ctx == NULL || ctx->parent == NULL) {
179 mkdg_log(WARN,
180 "property_context_apply(%s): either ctx or ctx->parent is NULL",
181 ctx->spec->key);
182 return FALSE;
183 }
184 if (ctx->spec->applyFunc == NULL ){
185 mkdg_log(DEBUG, "property_context_apply(%s,-): No apply function, skip", ctx->spec->key);
186 return TRUE;
187 }
188 mkdg_log(DEBUG, "property_context_apply(%s,-): value %s",
189 ctx->spec->key, mkdg_g_value_to_string(&(ctx->value)));
190 return ctx->spec->applyFunc(ctx, userData);
191 }
192
property_context_use(PropertyContext * ctx,gpointer userData)193 gboolean property_context_use(PropertyContext * ctx, gpointer userData)
194 {
195 mkdg_log(DEBUG, "property_context_use(%s,-)", ctx->spec->key);
196 GValue *ret = property_context_load(ctx, userData);
197 if (ret == NULL) {
198 mkdg_log(WARN,
199 "property_context_use(%s): property_context_load return NULL",
200 ctx->spec->key);
201 return FALSE;
202 }
203 return property_context_apply(ctx, userData);
204 }
205
property_context_free(PropertyContext * ctx)206 void property_context_free(PropertyContext * ctx)
207 {
208 mkdg_log(INFO, "property_context_free(%s,-)", ctx->spec->key);
209 g_value_unset(&(ctx->value));
210 g_free(ctx);
211 }
212
213
214 /*============================================
215 * MkdgProperties Methods
216 */
217
218 /* This alone is sufficient to generate schemas */
mkdg_properties_from_spec_array(MkdgPropertySpec specs[],MkdgBackend * backend,gpointer parent,gpointer auxData)219 MkdgProperties *mkdg_properties_from_spec_array(MkdgPropertySpec specs[],
220 MkdgBackend * backend,
221 gpointer parent,
222 gpointer auxData)
223 {
224 gsize arraySize = 0;
225 gsize i;
226 for (i = 0; specs[i].valueType != G_TYPE_INVALID; i++) {
227 arraySize++;
228 }
229 MkdgProperties *result = g_new0(MkdgProperties, 1);
230 result->backend = backend;
231 result->contexts = g_ptr_array_sized_new(arraySize);
232 result->auxData = auxData;
233 for (i = 0; i < arraySize; i++) {
234 PropertyContext *ctx = property_context_new(&specs[i], backend,
235 parent, auxData);
236 g_ptr_array_add(result->contexts, (gpointer) ctx);
237 }
238 return result;
239 }
240
mkdg_properties_find_by_key(MkdgProperties * properties,const gchar * key)241 PropertyContext *mkdg_properties_find_by_key(MkdgProperties * properties,
242 const gchar * key)
243 {
244 gsize i;
245 for (i = 0; i < mkdg_properties_size(properties); i++) {
246 PropertyContext *ctx = mkdg_properties_index(properties, i);
247 if (STRING_EQUALS(ctx->spec->key, key)) {
248 return ctx;
249 }
250 }
251 return NULL;
252 }
253
mkdg_properties_index(MkdgProperties * properties,guint index)254 PropertyContext *mkdg_properties_index(MkdgProperties *
255 properties, guint index)
256 {
257 return (PropertyContext *)
258 g_ptr_array_index(properties->contexts, index);
259 }
260
mkdg_properties_get_by_key(MkdgProperties * properties,const gchar * key)261 GValue *mkdg_properties_get_by_key(MkdgProperties * properties,
262 const gchar * key)
263 {
264 if (properties == NULL) {
265 return NULL;
266 }
267 PropertyContext *ctx = mkdg_properties_find_by_key(properties, key);
268 return property_context_get(ctx);
269 }
270
mkdg_properties_set_by_key(MkdgProperties * properties,const gchar * key,GValue * value)271 gboolean mkdg_properties_set_by_key(MkdgProperties * properties,
272 const gchar * key, GValue * value)
273 {
274 if (properties == NULL) {
275 return FALSE;
276 }
277 PropertyContext *ctx = mkdg_properties_find_by_key(properties, key);
278 return property_context_set(ctx, value);
279 }
280
mkdg_properties_set_boolean_by_key(MkdgProperties * properties,const gchar * key,gboolean boolValue)281 gboolean mkdg_properties_set_boolean_by_key(MkdgProperties * properties,
282 const gchar * key,
283 gboolean boolValue)
284 {
285 GValue gValue = { 0 };
286 g_value_init(&gValue, G_TYPE_BOOLEAN);
287 g_value_set_boolean(&gValue, boolValue);
288 gboolean result = mkdg_properties_set_by_key(properties, key, &gValue);
289 g_value_unset(&gValue);
290 return result;
291 }
292
mkdg_properties_set_int_by_key(MkdgProperties * properties,const gchar * key,gint intValue)293 gboolean mkdg_properties_set_int_by_key(MkdgProperties * properties,
294 const gchar * key, gint intValue)
295 {
296 GValue gValue = { 0 };
297 g_value_init(&gValue, G_TYPE_INT);
298 g_value_set_int(&gValue, intValue);
299 gboolean result = mkdg_properties_set_by_key(properties, key, &gValue);
300 g_value_unset(&gValue);
301 return result;
302 }
303
mkdg_properties_set_string_by_key(MkdgProperties * properties,const gchar * key,const gchar * stringValue)304 gboolean mkdg_properties_set_string_by_key(MkdgProperties * properties,
305 const gchar * key,
306 const gchar * stringValue)
307 {
308 GValue gValue = { 0 };
309 g_value_init(&gValue, G_TYPE_STRING);
310 g_value_set_string(&gValue, stringValue);
311 gboolean result = mkdg_properties_set_by_key(properties, key, &gValue);
312 g_value_unset(&gValue);
313 return result;
314 }
315
mkdg_properties_load_by_key(MkdgProperties * properties,const gchar * key,gpointer userData)316 GValue *mkdg_properties_load_by_key(MkdgProperties * properties,
317 const gchar * key, gpointer userData)
318 {
319 if (properties == NULL) {
320 return NULL;
321 }
322 PropertyContext *ctx = mkdg_properties_find_by_key(properties, key);
323 return property_context_load(ctx, userData);
324 }
325
mkdg_properties_save_by_key(MkdgProperties * properties,const gchar * key,GValue * value,gpointer userData)326 gboolean mkdg_properties_save_by_key(MkdgProperties * properties,
327 const gchar * key, GValue * value,
328 gpointer userData)
329 {
330 if (properties == NULL) {
331 return FALSE;
332 }
333 PropertyContext *ctx = mkdg_properties_find_by_key(properties, key);
334 return property_context_save(ctx, value, userData);
335 }
336
mkdg_properties_save_boolean_by_key(MkdgProperties * properties,const gchar * key,gboolean boolValue,gpointer userData)337 gboolean mkdg_properties_save_boolean_by_key(MkdgProperties * properties,
338 const gchar * key,
339 gboolean boolValue,
340 gpointer userData)
341 {
342 GValue gValue = { 0 };
343 g_value_init(&gValue, G_TYPE_BOOLEAN);
344 g_value_set_boolean(&gValue, boolValue);
345 gboolean result =
346 mkdg_properties_save_by_key(properties, key, &gValue, userData);
347 g_value_unset(&gValue);
348 return result;
349 }
350
mkdg_properties_save_int_by_key(MkdgProperties * properties,const gchar * key,gint intValue,gpointer userData)351 gboolean mkdg_properties_save_int_by_key(MkdgProperties * properties,
352 const gchar * key, gint intValue,
353 gpointer userData)
354 {
355 GValue gValue = { 0 };
356 g_value_init(&gValue, G_TYPE_INT);
357 g_value_set_int(&gValue, intValue);
358 gboolean result =
359 mkdg_properties_save_by_key(properties, key, &gValue, userData);
360 g_value_unset(&gValue);
361 return result;
362 }
363
mkdg_properties_save_string_by_key(MkdgProperties * properties,const gchar * key,const gchar * stringValue,gpointer userData)364 gboolean mkdg_properties_save_string_by_key(MkdgProperties * properties,
365 const gchar * key,
366 const gchar * stringValue,
367 gpointer userData)
368 {
369 GValue gValue = { 0 };
370 g_value_init(&gValue, G_TYPE_STRING);
371 g_value_set_string(&gValue, stringValue);
372 gboolean result =
373 mkdg_properties_save_by_key(properties, key, &gValue, userData);
374 g_value_unset(&gValue);
375 return result;
376 }
377
mkdg_properties_apply_by_key(MkdgProperties * properties,const gchar * key,gpointer userData)378 gboolean mkdg_properties_apply_by_key(MkdgProperties * properties,
379 const gchar * key, gpointer userData)
380 {
381 if (properties == NULL) {
382 return FALSE;
383 }
384 PropertyContext *ctx = mkdg_properties_find_by_key(properties, key);
385 return property_context_apply(ctx, userData);
386 }
387
mkdg_properties_size(MkdgProperties * properties)388 gsize mkdg_properties_size(MkdgProperties * properties)
389 {
390 return properties->contexts->len;
391 }
392
393 /* For setup interface */
mkdg_properties_load_all(MkdgProperties * properties,gpointer userData)394 gboolean mkdg_properties_load_all(MkdgProperties * properties,
395 gpointer userData)
396 {
397 gsize i;
398 gboolean result = TRUE;
399 for (i = 0; i < mkdg_properties_size(properties); i++) {
400 PropertyContext *ctx = mkdg_properties_index(properties, i);
401 GValue *value = property_context_load(ctx, userData);
402 if (value == NULL) {
403 result = FALSE;
404 }
405 }
406 return result;
407 }
408
mkdg_properties_write_all(MkdgProperties * properties,gpointer userData)409 gboolean mkdg_properties_write_all(MkdgProperties * properties,
410 gpointer userData)
411 {
412 gsize i;
413 gboolean result = TRUE;
414 for (i = 0; i < mkdg_properties_size(properties); i++) {
415 PropertyContext *ctx = mkdg_properties_index(properties, i);
416 gboolean ret = property_context_write(ctx, userData);
417 if (!ret) {
418 result = FALSE;
419 }
420 }
421 return result;
422 }
423
424 /* For actual runtime */
mkdg_properties_apply_all(MkdgProperties * properties,gpointer userData)425 gboolean mkdg_properties_apply_all(MkdgProperties * properties,
426 gpointer userData)
427 {
428 gsize i;
429 gboolean result = TRUE;
430 for (i = 0; i < mkdg_properties_size(properties); i++) {
431 PropertyContext *ctx = mkdg_properties_index(properties, i);
432 gboolean ret = property_context_apply(ctx, userData);
433 if (!ret) {
434 result = FALSE;
435 }
436 }
437 return result;
438 }
439
mkdg_properties_use_all(MkdgProperties * properties,gpointer userData)440 gboolean mkdg_properties_use_all(MkdgProperties * properties,
441 gpointer userData)
442 {
443 gsize i;
444 gboolean result = TRUE;
445 for (i = 0; i < mkdg_properties_size(properties); i++) {
446 PropertyContext *ctx = mkdg_properties_index(properties, i);
447 gboolean ret = property_context_use(ctx, userData);
448 if (!ret) {
449 result = FALSE;
450 }
451 }
452 return result;
453 }
454
mkdg_properties_free(MkdgProperties * properties)455 void mkdg_properties_free(MkdgProperties * properties)
456 {
457 gsize i;
458 for (i = 0; i < mkdg_properties_size(properties); i++) {
459 PropertyContext *ctx = mkdg_properties_index(properties, i);
460 property_context_free(ctx);
461 }
462 g_ptr_array_free(properties->contexts, TRUE);
463 g_free(properties);
464 }
465