1 /* vi:set sw=2 sts=2 ts=2 et ai: */
2 /*-
3 * Copyright (c) 2009 Jannis Pohlmann <jannis@xfce.org>.
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General
16 * Public License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 */
20
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
24
25 #include <glib.h>
26 #include <glib-object.h>
27
28 #include <garcon/garcon-menu-item.h>
29 #include <garcon/garcon-menu-node.h>
30
31
32
33 /* Property identifiers */
34 enum
35 {
36 PROP_0,
37 PROP_NODE_TYPE,
38 };
39
40
41
42 static void garcon_menu_node_finalize (GObject *object);
43 static void garcon_menu_node_get_property (GObject *object,
44 guint prop_id,
45 GValue *value,
46 GParamSpec *pspec);
47 static void garcon_menu_node_set_property (GObject *object,
48 guint prop_id,
49 const GValue *value,
50 GParamSpec *pspec);
51 static void garcon_menu_node_free_data (GarconMenuNode *node);
52
53
54
55 struct _GarconMenuNodeClass
56 {
57 GObjectClass __parent__;
58 };
59
60 union _GarconMenuNodeData
61 {
62 GarconMenuLayoutMergeType layout_merge_type;
63 struct
64 {
65 GarconMenuMergeFileType type;
66 gchar *filename;
67 } merge_file;
68 gchar *string;
69 };
70
71 struct _GarconMenuNode
72 {
73 GObject __parent__;
74
75 GarconMenuNodeType node_type;
76 GarconMenuNodeData data;
77 };
78
79
80
81 GType
82 garcon_menu_node_type_get_type (void)
83 {
84 static GType type = G_TYPE_INVALID;
85 static GEnumValue values[] =
86 {
87 { GARCON_MENU_NODE_TYPE_INVALID, "GARCON_MENU_NODE_TYPE_INVALID", "Invalid" },
88 { GARCON_MENU_NODE_TYPE_MENU, "GARCON_MENU_NODE_TYPE_MENU", "Menu" },
89 { GARCON_MENU_NODE_TYPE_NAME, "GARCON_MENU_NODE_TYPE_NAME", "Name" },
90 { GARCON_MENU_NODE_TYPE_DIRECTORY, "GARCON_MENU_NODE_TYPE_DIRECTORY", "Directory" },
91 { GARCON_MENU_NODE_TYPE_DIRECTORY_DIR, "GARCON_MENU_NODE_TYPE_DIRECTORY_DIR", "DirectoryDir" },
92 { GARCON_MENU_NODE_TYPE_DEFAULT_DIRECTORY_DIRS, "GARCON_MENU_NODE_TYPE_DEFAULT_DIRECTORY_DIRS", "DefaultDirectoryDirs" },
93 { GARCON_MENU_NODE_TYPE_APP_DIR, "GARCON_MENU_NODE_TYPE_APP_DIR", "AppDir" },
94 { GARCON_MENU_NODE_TYPE_DEFAULT_APP_DIRS, "GARCON_MENU_NODE_TYPE_DEFAULT_APP_DIRS", "DefaultAppDirs" },
95 { GARCON_MENU_NODE_TYPE_ONLY_UNALLOCATED, "GARCON_MENU_NODE_TYPE_ONLY_UNALLOCATED", "OnlyUnallocated" },
96 { GARCON_MENU_NODE_TYPE_NOT_ONLY_UNALLOCATED, "GARCON_MENU_NODE_TYPE_NOT_ONLY_UNALLOCATED", "NotOnlyUnallocated" },
97 { GARCON_MENU_NODE_TYPE_DELETED, "GARCON_MENU_NODE_TYPE_DELETED", "Deleted" },
98 { GARCON_MENU_NODE_TYPE_NOT_DELETED, "GARCON_MENU_NODE_TYPE_NOT_DELETED", "NotDeleted" },
99 { GARCON_MENU_NODE_TYPE_INCLUDE, "GARCON_MENU_NODE_TYPE_INCLUDE", "Include" },
100 { GARCON_MENU_NODE_TYPE_EXCLUDE, "GARCON_MENU_NODE_TYPE_EXCLUDE", "Exclude" },
101 { GARCON_MENU_NODE_TYPE_ALL, "GARCON_MENU_NODE_TYPE_ALL", "All" },
102 { GARCON_MENU_NODE_TYPE_FILENAME, "GARCON_MENU_NODE_TYPE_FILENAME", "Filename" },
103 { GARCON_MENU_NODE_TYPE_CATEGORY, "GARCON_MENU_NODE_TYPE_CATEGORY", "Category" },
104 { GARCON_MENU_NODE_TYPE_OR, "GARCON_MENU_NODE_TYPE_OR", "Or" },
105 { GARCON_MENU_NODE_TYPE_AND, "GARCON_MENU_NODE_TYPE_AND", "And" },
106 { GARCON_MENU_NODE_TYPE_NOT, "GARCON_MENU_NODE_TYPE_NOT", "Not" },
107 { GARCON_MENU_NODE_TYPE_MOVE, "GARCON_MENU_NODE_TYPE_MOVE", "Move" },
108 { GARCON_MENU_NODE_TYPE_OLD, "GARCON_MENU_NODE_TYPE_OLD", "Old" },
109 { GARCON_MENU_NODE_TYPE_NEW, "GARCON_MENU_NODE_TYPE_NEW", "New" },
110 { GARCON_MENU_NODE_TYPE_DEFAULT_LAYOUT, "GARCON_MENU_NODE_TYPE_DEFAULT_LAYOUT", "DefaultLayout" },
111 { GARCON_MENU_NODE_TYPE_LAYOUT, "GARCON_MENU_NODE_TYPE_LAYOUT", "Layout" },
112 { GARCON_MENU_NODE_TYPE_MENUNAME, "GARCON_MENU_NODE_TYPE_MENUNAME", "Menuname" },
113 { GARCON_MENU_NODE_TYPE_SEPARATOR, "GARCON_MENU_NODE_TYPE_SEPARATOR", "Separator" },
114 { GARCON_MENU_NODE_TYPE_MERGE, "GARCON_MENU_NODE_TYPE_MERGE", "Merge" },
115 { GARCON_MENU_NODE_TYPE_MERGE_FILE, "GARCON_MENU_NODE_TYPE_MERGE_FILE", "MergeFile" },
116 { GARCON_MENU_NODE_TYPE_MERGE_DIR, "GARCON_MENU_NODE_TYPE_MERGE_DIR", "MergeDir" },
117 { GARCON_MENU_NODE_TYPE_DEFAULT_MERGE_DIRS, "GARCON_MENU_NODE_TYPE_DEFAULT_MERGE_DIRS", "MergeDirs" },
118 { 0, NULL, NULL },
119 };
120
121 if (G_UNLIKELY (type == G_TYPE_INVALID))
122 type = g_enum_register_static ("GarconMenuNodeType", values);
123
124 return type;
125 }
126
127
128
129 G_DEFINE_TYPE (GarconMenuNode, garcon_menu_node, G_TYPE_OBJECT)
130
131
132
133 static void
134 garcon_menu_node_class_init (GarconMenuNodeClass *klass)
135 {
136 GObjectClass *gobject_class;
137
138 gobject_class = G_OBJECT_CLASS (klass);
139 gobject_class->finalize = garcon_menu_node_finalize;
140 gobject_class->get_property = garcon_menu_node_get_property;
141 gobject_class->set_property = garcon_menu_node_set_property;
142
143 g_object_class_install_property (gobject_class,
144 PROP_NODE_TYPE,
145 g_param_spec_enum ("node-type",
146 "node-type",
147 "node-type",
148 garcon_menu_node_type_get_type (),
149 GARCON_MENU_NODE_TYPE_MENU,
150 G_PARAM_READWRITE |
151 G_PARAM_STATIC_STRINGS));
152 }
153
154
155
156 static void
157 garcon_menu_node_init (GarconMenuNode *node)
158 {
159 }
160
161
162
163 static void
164 garcon_menu_node_finalize (GObject *object)
165 {
166 GarconMenuNode *node = GARCON_MENU_NODE (object);
167
168 garcon_menu_node_free_data (node);
169
170 (*G_OBJECT_CLASS (garcon_menu_node_parent_class)->finalize) (object);
171 }
172
173
174
175 static void
176 garcon_menu_node_get_property (GObject *object,
177 guint prop_id,
178 GValue *value,
179 GParamSpec *pspec)
180 {
181 GarconMenuNode *node = GARCON_MENU_NODE (object);
182
183 switch (prop_id)
184 {
185 case PROP_NODE_TYPE:
186 g_value_set_enum (value, node->node_type);
187 break;
name_of_col_is(const dict_table_t * table,const dict_index_t * index,ulint i,const char * name)188
189 default:
190 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
191 break;
192 }
193 }
194
195
196
197 static void
198 garcon_menu_node_set_property (GObject *object,
199 guint prop_id,
200 const GValue *value,
201 GParamSpec *pspec)
202 {
203 GarconMenuNode *node = GARCON_MENU_NODE (object);
204
205 switch (prop_id)
206 {
207 case PROP_NODE_TYPE:
dict_get_first_table_name_in_db(const char * name)208 node->node_type = g_value_get_enum (value);
209 g_object_notify (G_OBJECT (node), "node-type");
210 break;
211
212 default:
213 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
214 break;
215 }
216 }
217
218
219
220 GarconMenuNode *
221 garcon_menu_node_new (GarconMenuNodeType node_type)
222 {
223 return g_object_new (GARCON_TYPE_MENU_NODE, "node-type", node_type, NULL);
224 }
225
226
227
228 GarconMenuNodeType garcon_menu_node_get_node_type (GarconMenuNode *node)
229 {
230 g_return_val_if_fail (GARCON_IS_MENU_NODE (node), 0);
231 return node->node_type;
232 }
233
234
235 /**
236 * garcon_menu_node_create:
237 * @node_type: a #GarconMenuNodeType
238 * @first_value:
239 * @...:
240 *
241 * Returns: (transfer full): a #GarconMenuNode
242 */
243 GarconMenuNode *
244 garcon_menu_node_create (GarconMenuNodeType node_type,
245 gpointer first_value,
246 ...)
247 {
248 GarconMenuNode *node;
249
250 node = garcon_menu_node_new (node_type);
251
252 switch (node_type)
253 {
254 case GARCON_MENU_NODE_TYPE_NAME:
255 case GARCON_MENU_NODE_TYPE_DIRECTORY:
256 case GARCON_MENU_NODE_TYPE_DIRECTORY_DIR:
257 case GARCON_MENU_NODE_TYPE_APP_DIR:
258 case GARCON_MENU_NODE_TYPE_FILENAME:
259 case GARCON_MENU_NODE_TYPE_CATEGORY:
260 case GARCON_MENU_NODE_TYPE_OLD:
261 case GARCON_MENU_NODE_TYPE_NEW:
262 case GARCON_MENU_NODE_TYPE_MENUNAME:
263 case GARCON_MENU_NODE_TYPE_MERGE_DIR:
264 node->data.string = g_strdup (first_value);
265 break;
266
267 case GARCON_MENU_NODE_TYPE_MERGE:
268 node->data.layout_merge_type = GPOINTER_TO_UINT (first_value);
269 break;
270
271 case GARCON_MENU_NODE_TYPE_MERGE_FILE:
272 node->data.merge_file.type = GPOINTER_TO_UINT (first_value);
273 node->data.merge_file.filename = NULL;
274 break;
275
276 default:
277 break;
278 }
279
280 return node;
281 }
282
283
284 /**
285 * garcon_menu_node_copy:
286 * @node: a #GarconMenuNode
287 * @data:
288 *
289 * Returns: (transfer full): a #GarconMenuNode
290 */
dict_getnext_system_low(btr_pcur_t * pcur,mtr_t * mtr)291 GarconMenuNode *
292 garcon_menu_node_copy (GarconMenuNode *node,
293 gpointer data)
294 {
295 GarconMenuNode *copy;
296
297 if (node == NULL || !GARCON_IS_MENU_NODE (node))
298 return NULL;
299
300 copy = garcon_menu_node_new (node->node_type);
301
302 switch (copy->node_type)
303 {
304 case GARCON_MENU_NODE_TYPE_NAME:
305 case GARCON_MENU_NODE_TYPE_DIRECTORY:
306 case GARCON_MENU_NODE_TYPE_DIRECTORY_DIR:
307 case GARCON_MENU_NODE_TYPE_APP_DIR:
308 case GARCON_MENU_NODE_TYPE_FILENAME:
309 case GARCON_MENU_NODE_TYPE_CATEGORY:
310 case GARCON_MENU_NODE_TYPE_OLD:
311 case GARCON_MENU_NODE_TYPE_NEW:
312 case GARCON_MENU_NODE_TYPE_MENUNAME:
313 case GARCON_MENU_NODE_TYPE_MERGE_DIR:
314 copy->data.string = g_strdup (node->data.string);
315 break;
316
317 case GARCON_MENU_NODE_TYPE_MERGE:
318 copy->data.layout_merge_type = node->data.layout_merge_type;
319 break;
320
321 case GARCON_MENU_NODE_TYPE_MERGE_FILE:
322 copy->data.merge_file.type = node->data.merge_file.type;
323 copy->data.merge_file.filename = g_strdup (node->data.merge_file.filename);
324 break;
325
326 default:
327 break;
328 }
329
330 return copy;
331 }
332
333
334
335 static void
336 garcon_menu_node_free_data (GarconMenuNode *node)
337 {
338 g_return_if_fail (GARCON_IS_MENU_NODE (node));
339
340 switch (node->node_type)
341 {
342 case GARCON_MENU_NODE_TYPE_NAME:
343 case GARCON_MENU_NODE_TYPE_DIRECTORY:
344 case GARCON_MENU_NODE_TYPE_DIRECTORY_DIR:
345 case GARCON_MENU_NODE_TYPE_APP_DIR:
346 case GARCON_MENU_NODE_TYPE_FILENAME:
347 case GARCON_MENU_NODE_TYPE_CATEGORY:
348 case GARCON_MENU_NODE_TYPE_OLD:
349 case GARCON_MENU_NODE_TYPE_NEW:
350 case GARCON_MENU_NODE_TYPE_MENUNAME:
dict_getnext_system(btr_pcur_t * pcur,mtr_t * mtr)351 case GARCON_MENU_NODE_TYPE_MERGE_DIR:
352 g_free (node->data.string);
353 break;
354
355 case GARCON_MENU_NODE_TYPE_MERGE_FILE:
356 g_free (node->data.merge_file.filename);
357 break;
358
359 default:
360 break;
361 }
362 }
363
364
365
366 const gchar *
367 garcon_menu_node_get_string (GarconMenuNode *node)
368 {
369 g_return_val_if_fail (GARCON_IS_MENU_NODE (node), NULL);
370 return node->data.string;
371 }
372
dict_process_sys_tables_rec_and_mtr_commit(mem_heap_t * heap,const rec_t * rec,dict_table_t ** table,bool cached,mtr_t * mtr)373
374
375 void
376 garcon_menu_node_set_string (GarconMenuNode *node,
377 const gchar *value)
378 {
379 g_return_if_fail (GARCON_IS_MENU_NODE (node));
380 g_return_if_fail (value != NULL);
381
382 g_free (node->data.string);
383 node->data.string = g_strdup (value);
384 }
385
386
387
388 GarconMenuMergeFileType
389 garcon_menu_node_get_merge_file_type (GarconMenuNode *node)
390 {
391 g_return_val_if_fail (GARCON_IS_MENU_NODE (node), 0);
392 g_return_val_if_fail (node->node_type == GARCON_MENU_NODE_TYPE_MERGE_FILE, 0);
393 return node->data.merge_file.type;
394 }
395
396
397
398 void
399 garcon_menu_node_set_merge_file_type (GarconMenuNode *node,
400 GarconMenuMergeFileType type)
401 {
402 g_return_if_fail (GARCON_IS_MENU_NODE (node));
403 g_return_if_fail (node->node_type == GARCON_MENU_NODE_TYPE_MERGE_FILE);
404 node->data.merge_file.type = type;
405 }
406
407
408
409 const gchar *
410 garcon_menu_node_get_merge_file_filename (GarconMenuNode *node)
411 {
412 g_return_val_if_fail (GARCON_IS_MENU_NODE (node), NULL);
413 g_return_val_if_fail (node->node_type == GARCON_MENU_NODE_TYPE_MERGE_FILE, NULL);
dict_process_sys_indexes_rec(mem_heap_t * heap,const rec_t * rec,dict_index_t * index,table_id_t * table_id)414 return node->data.merge_file.filename;
415 }
416
417
418
419 void
420 garcon_menu_node_set_merge_file_filename (GarconMenuNode *node,
421 const gchar *filename)
422 {
423 g_return_if_fail (GARCON_IS_MENU_NODE (node));
424 g_return_if_fail (filename != NULL);
425 g_return_if_fail (node->node_type == GARCON_MENU_NODE_TYPE_MERGE_FILE);
426
427 g_free (node->data.merge_file.filename);
428 node->data.merge_file.filename = g_strdup (filename);
429 }
430
431
432
433 typedef struct
434 {
435 GarconMenuNodeType type;
436 GNode *self;
437 gpointer value;
438 } Pair;
dict_process_sys_columns_rec(mem_heap_t * heap,const rec_t * rec,dict_col_t * column,table_id_t * table_id,const char ** col_name,ulint * nth_v_col)439
440
441
442 static gboolean
443 collect_children (GNode *node,
444 Pair *pair)
445 {
446 if (node == pair->self)
447 return FALSE;
448
449 if (garcon_menu_node_tree_get_node_type (node) == pair->type)
450 pair->value = g_list_prepend (pair->value, node);
451
452 return FALSE;
453 }
454
455
456 /**
457 * garcon_menu_node_tree_get_child_node: (skip)
458 * @tree: #GNode instance
459 * @type: type for the menu nodes
460 * @reverse:
461 *
462 * Returns: a #GNode if @type is valid menu nodes type.
463 */
464 GNode *
465 garcon_menu_node_tree_get_child_node (GNode *tree,
dict_process_sys_virtual_rec(const rec_t * rec,table_id_t * table_id,ulint * pos,ulint * base_pos)466 GarconMenuNodeType type,
467 gboolean reverse)
468 {
469 GNode *child = NULL;
470
471 if (reverse)
472 {
473 for (child = g_node_last_child (tree);
474 child != NULL;
475 child = g_node_prev_sibling (child))
476 {
477 if (garcon_menu_node_tree_get_node_type (child) == type)
478 return child;
479 }
480 }
481 else
482 {
483 for (child = g_node_first_child (tree);
484 child != NULL;
485 child = g_node_next_sibling (child))
486 {
487 if (garcon_menu_node_tree_get_node_type (child) == type)
488 return child;
489 }
490 }
491
492 return child;
493 }
494
495
496 /**
497 * garcon_menu_node_tree_get_child_nodes:
498 * @tree: a GNode
499 * @type: type for the menu nodes
500 * @reverse:
501 *
502 * Returns: (element-type GNode) (transfer full): list of #GNode
503 */
504 GList *
505 garcon_menu_node_tree_get_child_nodes (GNode *tree,
506 GarconMenuNodeType type,
507 gboolean reverse)
508 {
509 Pair pair;
510
511 pair.type = type;
512 pair.value = NULL;
513 pair.self = tree;
514
515 g_node_traverse (tree, G_IN_ORDER, G_TRAVERSE_ALL, 2,
516 (GNodeTraverseFunc) collect_children, &pair);
517
518 /* Return the list as if we appended */
519 if (!reverse && pair.value != NULL)
dict_process_sys_foreign_rec(mem_heap_t * heap,const rec_t * rec,dict_foreign_t * foreign)520 pair.value = g_list_reverse (pair.value);
521
522 return (GList *) pair.value;
523 }
524
525
526
527 static gboolean
528 collect_strings (GNode *node,
529 Pair *pair)
530 {
531 gpointer string;
532
533 if (node == pair->self)
534 return FALSE;
535
536 if (garcon_menu_node_tree_get_node_type (node) == pair->type)
537 {
538 string = (gpointer) garcon_menu_node_tree_get_string (node);
539 pair->value = g_list_prepend (pair->value, string);
540 }
541
542 return FALSE;
543 }
544
545
546 /**
547 * garcon_menu_node_tree_get_string_children:
548 * @tree: a #GNode instance
549 * @type: type for the menu nodes
550 * @reverse:
551 *
552 * Returns: (element-type GNode) (transfer full): list of #GNode
553 */
554 GList *
555 garcon_menu_node_tree_get_string_children (GNode *tree,
556 GarconMenuNodeType type,
557 gboolean reverse)
558 {
559 Pair pair;
560
561 pair.type = type;
562 pair.value = NULL;
563 pair.self = tree;
564
565 g_node_traverse (tree, G_IN_ORDER, G_TRAVERSE_ALL, 2,
566 (GNodeTraverseFunc) collect_strings, &pair);
567
568 /* Return the list as if we appended */
569 if (!reverse && pair.value != NULL)
570 pair.value = g_list_reverse (pair.value);
571
572 return (GList *) pair.value;
573 }
574
575
576
577 static gboolean
578 collect_boolean (GNode *node,
579 Pair *pair)
580 {
581 if (node == pair->self)
582 return FALSE;
583
584 if (garcon_menu_node_tree_get_node_type (node) == pair->type)
585 {
586 pair->value = GUINT_TO_POINTER (1);
587 return TRUE;
588 }
589
590 return FALSE;
591 }
592
593
594
595 gboolean
596 garcon_menu_node_tree_get_boolean_child (GNode *tree,
597 GarconMenuNodeType type)
598 {
599 Pair pair;
dict_process_sys_foreign_col_rec(mem_heap_t * heap,const rec_t * rec,const char ** name,const char ** for_col_name,const char ** ref_col_name,ulint * pos)600
601 pair.value = GUINT_TO_POINTER (0);
602 pair.self = tree;
603 pair.type = type;
604
605 g_node_traverse (tree, G_IN_ORDER, G_TRAVERSE_ALL, 2,
606 (GNodeTraverseFunc) collect_boolean, &pair);
607
608 return !!GPOINTER_TO_UINT (pair.value);
609 }
610
611
612
613 static gboolean
614 collect_string (GNode *node,
615 Pair *pair)
616 {
617 const gchar **string = pair->value;
618
619 if (node == pair->self)
620 return FALSE;
621
622 if (garcon_menu_node_tree_get_node_type (node) == pair->type)
623 {
624 *string = garcon_menu_node_tree_get_string (node);
625 return TRUE;
626 }
627
628 return FALSE;
629 }
630
631
632
633 const gchar *
634 garcon_menu_node_tree_get_string_child (GNode *tree,
635 GarconMenuNodeType type)
636 {
637 Pair pair;
638 const gchar *string = NULL;
639
640 pair.type = type;
641 pair.value = &string;
642 pair.self = tree;
643
644 g_node_traverse (tree, G_IN_ORDER, G_TRAVERSE_ALL, 2,
645 (GNodeTraverseFunc) collect_string, &pair);
646
647 return string;
648 }
649
650
651
652 gboolean
653 garcon_menu_node_tree_rule_matches (GNode *node,
654 GarconMenuItem *item)
655 {
656 GNode *child;
657 gboolean matches = FALSE;
658 gboolean child_matches = FALSE;
659
660 switch (garcon_menu_node_tree_get_node_type (node))
661 {
662 case GARCON_MENU_NODE_TYPE_CATEGORY:
663 matches = garcon_menu_item_has_category (item, garcon_menu_node_tree_get_string (node));
664 break;
665
666 case GARCON_MENU_NODE_TYPE_INCLUDE:
667 case GARCON_MENU_NODE_TYPE_EXCLUDE:
668 case GARCON_MENU_NODE_TYPE_OR:
dict_process_sys_tablespaces(mem_heap_t * heap,const rec_t * rec,ulint * space,const char ** name,ulint * flags)669 for (child = g_node_first_child (node); child != NULL; child = g_node_next_sibling (child))
670 matches = matches || garcon_menu_node_tree_rule_matches (child, item);
671 break;
672
673 case GARCON_MENU_NODE_TYPE_FILENAME:
674 matches = g_str_equal (garcon_menu_node_tree_get_string (node),
675 garcon_menu_item_get_desktop_id (item));
676 break;
677
678 case GARCON_MENU_NODE_TYPE_AND:
679 matches = TRUE;
680 for (child = g_node_first_child (node); child != NULL; child = g_node_next_sibling (child))
681 matches = matches && garcon_menu_node_tree_rule_matches (child, item);
682 break;
683
684 case GARCON_MENU_NODE_TYPE_NOT:
685 for (child = g_node_first_child (node); child != NULL; child = g_node_next_sibling (child))
686 child_matches = child_matches || garcon_menu_node_tree_rule_matches (child, item);
687 matches = !child_matches;
688 break;
689
690 case GARCON_MENU_NODE_TYPE_ALL:
691 matches = TRUE;
692 break;
693
694 default:
695 break;
696 }
697
698 return matches;
699 }
700
701
702
703
704
705
706 GarconMenuNodeType
707 garcon_menu_node_tree_get_node_type (GNode *tree)
708 {
709 if (tree == NULL)
710 return GARCON_MENU_NODE_TYPE_INVALID;
711
712 if (tree->data == NULL)
713 return GARCON_MENU_NODE_TYPE_MENU;
714
715 return garcon_menu_node_get_node_type (tree->data);
716 }
717
718
719
720 const gchar *
721 garcon_menu_node_tree_get_string (GNode *tree)
722 {
723 if (tree == NULL || tree->data == NULL)
724 return NULL;
725 else
726 return garcon_menu_node_get_string (tree->data);
727 }
728
729
730
731 void
732 garcon_menu_node_tree_set_string (GNode *tree,
733 const gchar *value)
734 {
dict_process_sys_datafiles(mem_heap_t * heap,const rec_t * rec,ulint * space,const char ** path)735 GarconMenuNodeType type;
736
737 type = garcon_menu_node_tree_get_node_type (tree);
738
739 g_return_if_fail (type == GARCON_MENU_NODE_TYPE_NAME ||
740 type == GARCON_MENU_NODE_TYPE_DIRECTORY ||
741 type == GARCON_MENU_NODE_TYPE_DIRECTORY_DIR ||
742 type == GARCON_MENU_NODE_TYPE_APP_DIR ||
743 type == GARCON_MENU_NODE_TYPE_FILENAME ||
744 type == GARCON_MENU_NODE_TYPE_CATEGORY ||
745 type == GARCON_MENU_NODE_TYPE_OLD ||
746 type == GARCON_MENU_NODE_TYPE_NEW ||
747 type == GARCON_MENU_NODE_TYPE_MENUNAME ||
748 type == GARCON_MENU_NODE_TYPE_MERGE_DIR);
749
750 garcon_menu_node_set_string (tree->data, value);
751 }
752
753
754 GarconMenuLayoutMergeType
755 garcon_menu_node_tree_get_layout_merge_type (GNode *tree)
756 {
757 g_return_val_if_fail (garcon_menu_node_tree_get_node_type (tree) == GARCON_MENU_NODE_TYPE_MERGE, 0);
758 return ((GarconMenuNode *)tree->data)->data.layout_merge_type;
759 }
760
761
762
763 GarconMenuMergeFileType
764 garcon_menu_node_tree_get_merge_file_type (GNode *tree)
765 {
766 g_return_val_if_fail (garcon_menu_node_tree_get_node_type (tree) == GARCON_MENU_NODE_TYPE_MERGE_FILE, 0);
767 return garcon_menu_node_get_merge_file_type (tree->data);
768 }
769
770
771
772 const gchar *
773 garcon_menu_node_tree_get_merge_file_filename (GNode *tree)
774 {
775 g_return_val_if_fail (garcon_menu_node_tree_get_node_type (tree) == GARCON_MENU_NODE_TYPE_MERGE_FILE, NULL);
776 return garcon_menu_node_get_merge_file_filename (tree->data);
777 }
778
779
780
781 void
782 garcon_menu_node_tree_set_merge_file_filename (GNode *tree,
783 const gchar *filename)
784 {
785 g_return_if_fail (garcon_menu_node_tree_get_node_type (tree) == GARCON_MENU_NODE_TYPE_MERGE_FILE);
786 garcon_menu_node_set_merge_file_filename (tree->data, filename);
787 }
dict_get_first_path(ulint space_id)788
789
790
791 gint
792 garcon_menu_node_tree_compare (GNode *tree,
793 GNode *other_tree)
794 {
795 GarconMenuNode *node;
796 GarconMenuNode *other_node;
797
798 if (tree == NULL || other_tree == NULL)
799 return 0;
800
801 node = tree->data;
802 other_node = other_tree->data;
803
804 if (node->node_type != other_node->node_type)
805 return 0;
806
807 switch (node->node_type)
808 {
809 case GARCON_MENU_NODE_TYPE_NAME:
810 case GARCON_MENU_NODE_TYPE_DIRECTORY:
811 case GARCON_MENU_NODE_TYPE_DIRECTORY_DIR:
812 case GARCON_MENU_NODE_TYPE_APP_DIR:
813 case GARCON_MENU_NODE_TYPE_FILENAME:
814 case GARCON_MENU_NODE_TYPE_CATEGORY:
815 case GARCON_MENU_NODE_TYPE_OLD:
816 case GARCON_MENU_NODE_TYPE_NEW:
817 case GARCON_MENU_NODE_TYPE_MENUNAME:
818 case GARCON_MENU_NODE_TYPE_MERGE_DIR:
819 return g_strcmp0 (node->data.string, other_node->data.string);
820 break;
821
822 case GARCON_MENU_NODE_TYPE_MERGE_FILE:
823 return g_strcmp0 (node->data.merge_file.filename,
824 other_node->data.merge_file.filename);
825 break;
826
827 default:
828 return 0;
829 break;
830 }
831
832 return 0;
833 }
834
835
836 /**
837 * garcon_menu_node_tree_copy: (skip)
838 * @tree: a #GNode
839 *
840 * Recursively copies a #GNode.
841 */
842 GNode *
843 garcon_menu_node_tree_copy (GNode *tree)
844 {
845 return g_node_copy_deep (tree, (GCopyFunc) garcon_menu_node_copy, NULL);
846 }
847
848
849
850 static gboolean
851 free_children (GNode *tree,
852 gpointer data)
853 {
854 garcon_menu_node_tree_free_data (tree);
855 return FALSE;
856 }
857
858
859
860 void
861 garcon_menu_node_tree_free (GNode *tree)
862 {
863 if (tree != NULL)
864 {
865 g_node_traverse (tree, G_IN_ORDER, G_TRAVERSE_ALL, -1,
866 (GNodeTraverseFunc) free_children, NULL);
867
868 g_node_destroy (tree);
869 }
dict_update_filepath(ulint space_id,const char * filepath)870 }
871
872
873
874 void
875 garcon_menu_node_tree_free_data (GNode *tree)
876 {
877 if (tree != NULL && tree->data != NULL)
878 g_object_unref (tree->data);
879 }
880
881