Updated Czech translation
[anjuta.git] / libanjuta / anjuta-project.c
blob91c0bf8f7d72480a17b6624013c9ba166befec73
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
3 * anjuta-project.c
4 * Copyright (C) Sébastien Granjoux 2009 <seb.sfo@free.fr>
6 * This program is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 * See the GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "anjuta-project.h"
22 #include "anjuta-debug.h"
23 #include "anjuta-marshal.h"
24 #include "anjuta-enum-types.h"
26 #include <string.h>
28 /**
29 * SECTION:anjuta-project
30 * @title: Anjuta project
31 * @short_description: Anjuta project
32 * @see_also:
33 * @stability: Unstable
34 * @include: libanjuta/anjuta-project.h
36 * A project in Anjuta is represented by a tree. There are six kinds of node.
38 * The root node is the parent of all other nodes, it can implement
39 * IAnjutaProject interface and represent the project itself but it is not
40 * mandatory.
42 * A module node represents a module in autotools project, it is a group of
43 * packages.
45 * A package node represents a package in autotools project, it is library.
47 * A group node is used to group several target or source, it can represent
48 * a directory by example.
50 * A target node represents an object file defined explicitely.
51 * There are different kinds of target: program, library...
52 * A target have as children all source needed to build it.
54 * A source node represents a source file. These are lead of the tree, a source
55 * node cannot have children.
57 * All these nodes are base objects. They have derived in each project backend
58 * to provide more specific information.
61 /* Node properties
62 *---------------------------------------------------------------------------*/
64 /* Implement Boxed type
65 *---------------------------------------------------------------------------*/
67 /**
68 * anjuta_project_property_new:
69 * @value: (transfer none): Value
70 * @name: (allow-none) (transfer none): Optional name used by map properties
71 * @user_data: (allow-none) (transfer full): Optional user data
73 * Returns: (transfer full):
75 AnjutaProjectProperty *
76 anjuta_project_property_new (const gchar *value,
77 const gchar *name,
78 gpointer user_data)
80 AnjutaProjectProperty *prop = g_slice_new0(AnjutaProjectProperty);
82 prop->value = g_strdup (value);
83 prop->name = name != NULL ? g_strdup (name) : NULL;
84 prop->user_data = user_data;
85 prop->info = NULL;
87 return prop;
90 AnjutaProjectProperty *
91 anjuta_project_property_copy (AnjutaProjectProperty *prop)
93 return anjuta_project_property_new (prop->value, prop->name, prop->user_data);
96 void
97 anjuta_project_property_free (AnjutaProjectProperty *prop)
99 g_free (prop->value);
100 g_free (prop->name);
101 g_slice_free (AnjutaProjectProperty, prop);
104 GType
105 anjuta_project_property_get_type (void)
107 static GType type_id = 0;
109 if (!type_id)
110 type_id = g_boxed_type_register_static ("AnjutaProjectProperty",
111 (GBoxedCopyFunc) anjuta_project_property_copy,
112 (GBoxedFreeFunc) anjuta_project_property_free);
114 return type_id;
117 /* Node properties information
118 *---------------------------------------------------------------------------*/
120 /* Implement Boxed type
121 *---------------------------------------------------------------------------*/
124 * anjuta_project_property_info_new:
125 * @id: (transfer none): Property identifier
126 * @name: (transfer none): Translatable property name
127 * @type: Property value type
128 * @flags: Property flags
129 * @description: (transfer none): Property description
130 * @default_value: (transfer full): Default property value
131 * @user_data: (allow-none) (transfer full): Optional user data
133 * Returns: (transfer full):
135 AnjutaProjectPropertyInfo *
136 anjuta_project_property_info_new (const gchar *id,
137 const gchar *name,
138 AnjutaProjectValueType type,
139 AnjutaProjectPropertyFlags flags,
140 const gchar *description,
141 AnjutaProjectProperty *default_value,
142 gpointer user_data)
144 AnjutaProjectPropertyInfo *info = g_slice_new0(AnjutaProjectPropertyInfo);
146 info->id = g_strdup (id);
147 info->name = g_strdup (name);
148 info->type = type;
149 info->flags = flags;
150 info->description = g_strdup (description);
151 info->default_value = default_value;
152 info->user_data = user_data;
154 info->default_value->info = info;
156 return info;
159 AnjutaProjectPropertyInfo *
160 anjuta_project_property_info_copy (AnjutaProjectPropertyInfo *info)
162 return anjuta_project_property_info_new (info->id, info->name, info->type,
163 info->flags, info->description,
164 info->default_value, info->user_data);
167 void
168 anjuta_project_property_info_free (AnjutaProjectPropertyInfo *info)
170 g_free (info->id);
171 g_free (info->name);
172 g_free (info->description);
173 anjuta_project_property_free (info->default_value);
174 g_slice_free (AnjutaProjectPropertyInfo, info);
177 GType
178 anjuta_project_property_info_get_type (void)
180 static GType type_id = 0;
182 if (!type_id)
183 type_id = g_boxed_type_register_static ("AnjutaProjectPropertyInfo",
184 (GBoxedCopyFunc) anjuta_project_property_info_copy,
185 (GBoxedFreeFunc) anjuta_project_property_info_free);
187 return type_id;
190 /* Node
191 *---------------------------------------------------------------------------*/
194 /* Moving in tree functions
195 *---------------------------------------------------------------------------*/
198 * anjuta_project_node_parent:
200 * Returns: (transfer none):
202 AnjutaProjectNode *
203 anjuta_project_node_parent(AnjutaProjectNode *node)
205 g_return_val_if_fail (node != NULL, NULL);
207 return node->parent;
211 * anjuta_project_node_root:
213 * Returns: (transfer none):
215 AnjutaProjectNode *
216 anjuta_project_node_root (AnjutaProjectNode *node)
218 g_return_val_if_fail (node != NULL, NULL);
220 while (node->parent != NULL)
222 node = node->parent;
225 return node;
229 * anjuta_project_node_first_child:
231 * Returns: (transfer none):
234 AnjutaProjectNode *
235 anjuta_project_node_first_child(AnjutaProjectNode *node)
237 g_return_val_if_fail (node != NULL, NULL);
239 return node->children;
243 * anjuta_project_node_last_child:
245 * Returns: (transfer none):
248 AnjutaProjectNode *
249 anjuta_project_node_last_child(AnjutaProjectNode *node)
251 g_return_val_if_fail (node != NULL, NULL);
253 node = node->children;
254 if (node)
255 while (node->next)
256 node = node->next;
258 return node;
262 * anjuta_project_node_next_sibling:
264 * Returns: (transfer none):
266 AnjutaProjectNode *
267 anjuta_project_node_next_sibling (AnjutaProjectNode *node)
269 g_return_val_if_fail (node != NULL, NULL);
271 return node->next;
275 * anjuta_project_node_prev_sibling:
277 * Returns: (transfer none):
279 AnjutaProjectNode *
280 anjuta_project_node_prev_sibling (AnjutaProjectNode *node)
282 g_return_val_if_fail (node != NULL, NULL);
284 return node->prev;
288 * anjuta_project_node_nth_child:
290 * Returns: (transfer none):
292 AnjutaProjectNode *anjuta_project_node_nth_child (AnjutaProjectNode *node, guint n)
294 g_return_val_if_fail (node != NULL, NULL);
296 node = node->children;
297 if (node)
298 while ((n-- > 0) && node)
299 node = node->next;
301 return node;
304 static AnjutaProjectNode *
305 anjuta_project_node_post_order_traverse (AnjutaProjectNode *node, AnjutaProjectNodeTraverseFunc func, gpointer data)
307 AnjutaProjectNode *child;
309 child = node->children;
310 while (child != NULL)
312 AnjutaProjectNode *current;
314 current = child;
315 child = current->next;
316 current = anjuta_project_node_post_order_traverse (current, func, data);
317 if (current != NULL)
319 return current;
323 return func (node, data) ? node : NULL;
326 static AnjutaProjectNode *
327 anjuta_project_node_pre_order_traverse (AnjutaProjectNode *node, AnjutaProjectNodeTraverseFunc func, gpointer data)
329 AnjutaProjectNode *child;
331 if (func (node, data))
333 return node;
336 child = node->children;
337 while (child != NULL)
339 AnjutaProjectNode *current;
341 current = child;
342 child = current->next;
343 current = anjuta_project_node_pre_order_traverse (current, func, data);
344 if (current != NULL)
346 return current;
350 return NULL;
355 * anjuta_project_node_traverse:
356 * @func: (scope call):
358 * Returns: (transfer none):
360 AnjutaProjectNode *
361 anjuta_project_node_traverse (AnjutaProjectNode *node, GTraverseType order, AnjutaProjectNodeTraverseFunc func, gpointer data)
363 g_return_val_if_fail (node != NULL, NULL);
364 g_return_val_if_fail (func != NULL, NULL);
365 g_return_val_if_fail ((order != G_PRE_ORDER) || (order != G_POST_ORDER), NULL);
367 switch (order)
369 case G_PRE_ORDER:
370 return anjuta_project_node_pre_order_traverse (node, func, data);
371 case G_POST_ORDER:
372 return anjuta_project_node_post_order_traverse (node, func, data);
373 default:
374 return NULL;
379 * anjuta_project_node_children_traverse:
380 * @func: (scope call):
382 * Returns: (transfer none):
384 AnjutaProjectNode *
385 anjuta_project_node_children_traverse (AnjutaProjectNode *node, AnjutaProjectNodeTraverseFunc func, gpointer data)
387 AnjutaProjectNode *child;
389 g_return_val_if_fail (node != NULL, NULL);
391 child = node->children;
392 while (child != NULL)
394 AnjutaProjectNode *current;
396 current = child;
397 child = current->next;
398 if (func (current, data))
400 return current;
404 return NULL;
407 static void
408 anjuta_project_node_post_order_foreach (AnjutaProjectNode *node, AnjutaProjectNodeForeachFunc func, gpointer data)
410 AnjutaProjectNode *child;
412 child = node->children;
413 while (child != NULL)
415 AnjutaProjectNode *current;
417 current = child;
418 child = current->next;
419 anjuta_project_node_post_order_foreach (current, func, data);
422 func (node, data);
425 static void
426 anjuta_project_node_pre_order_foreach (AnjutaProjectNode *node, AnjutaProjectNodeForeachFunc func, gpointer data)
428 AnjutaProjectNode *child;
430 func (node, data);
432 child = node->children;
433 while (child != NULL)
435 AnjutaProjectNode *current;
437 current = child;
438 child = current->next;
439 anjuta_project_node_pre_order_foreach (current, func, data);
444 * anjuta_project_node_foreach:
445 * @func: (scope call):
447 void
448 anjuta_project_node_foreach (AnjutaProjectNode *node, GTraverseType order, AnjutaProjectNodeForeachFunc func, gpointer data)
450 g_return_if_fail (node != NULL);
451 g_return_if_fail (func != NULL);
452 g_return_if_fail ((order != G_PRE_ORDER) || (order != G_POST_ORDER));
454 switch (order)
456 case G_PRE_ORDER:
457 anjuta_project_node_pre_order_foreach (node, func, data);
458 break;
459 case G_POST_ORDER:
460 anjuta_project_node_post_order_foreach (node, func, data);
461 break;
462 default:
463 break;
468 * anjuta_project_node_children_foreach:
469 * @func: (scope call):
471 void
472 anjuta_project_node_children_foreach (AnjutaProjectNode *node, AnjutaProjectNodeForeachFunc func, gpointer data)
474 AnjutaProjectNode *child;
476 g_return_if_fail (node != NULL);
478 child = node->children;
479 while (child != NULL)
481 AnjutaProjectNode *current;
483 current = child;
484 child = current->next;
485 func (current, data);
490 * anjuta_project_node_parent_type:
492 * Returns: (transfer none):
494 AnjutaProjectNode *
495 anjuta_project_node_parent_type(AnjutaProjectNode *node, AnjutaProjectNodeType type)
499 node = anjuta_project_node_parent (node);
500 if (node == NULL) break;
502 while (anjuta_project_node_get_node_type (node) != type);
504 return node;
509 /* Debugging functions
510 *---------------------------------------------------------------------------*/
512 static gboolean check_node (AnjutaProjectNode *node, gpointer data)
514 if (!ANJUTA_IS_PROJECT_NODE (node)) g_critical (" Node %p of %p is not a AnjutaProjectNode", node, data);
515 if (node->prev == NULL)
517 if ((node->parent != NULL) && (node->parent->children != node)) g_critical (" Node %p of %p has the wrong parent", node, data);
519 else
521 if (node->prev->next != node) g_critical (" Node %p of %p has the wrong predecessor", node, data);
522 if (node->prev->parent != node->parent) g_critical (" Node %p of %p has the wrong parent", node, data);
524 if (node->next != NULL)
526 if (node->next->prev != node) g_critical (" Node %p of %p has the wrong successor", node, data);
528 if (node->children != NULL)
530 if (node->children->parent != node) g_critical (" Node %p of %p has the wrong children", node, data);
533 return FALSE;
536 void
537 anjuta_project_node_check (AnjutaProjectNode *parent)
539 AnjutaProjectNode *node;
541 g_message ("Check node %p", parent);
542 node = anjuta_project_node_traverse (parent, G_POST_ORDER, check_node, parent);
543 if (node == NULL) g_message (" Node %p is valid", parent);
547 static void
548 anjuta_project_node_show (AnjutaProjectNode *node, gint indent)
550 g_message("%*s %p: %s", indent, "", node, node != NULL ? anjuta_project_node_get_name (node) : NULL);
553 static void
554 anjuta_project_node_dump_child (AnjutaProjectNode *parent, gint indent)
556 AnjutaProjectNode *child;
558 anjuta_project_node_show (parent, indent);
559 indent += 4;
561 for (child = anjuta_project_node_first_child (parent); child != NULL; child = anjuta_project_node_next_sibling (child))
563 anjuta_project_node_dump_child (child, indent);
567 void
568 anjuta_project_node_dump (AnjutaProjectNode *parent)
570 anjuta_project_node_dump_child (parent, 0);
575 /* Adding node functions
576 *---------------------------------------------------------------------------*/
579 * anjuta_project_node_insert_before:
580 * @parent:
581 * @sibling: (allow-none) (transfer none):
582 * @node: (transfer none):
584 * Returns: (transfer none):
586 AnjutaProjectNode *
587 anjuta_project_node_insert_before (AnjutaProjectNode *parent, AnjutaProjectNode *sibling, AnjutaProjectNode *node)
589 g_return_val_if_fail (node != NULL, NULL);
590 g_return_val_if_fail (parent != NULL, node);
592 /* FIXME: Try to avoid filling parent member to allow these checks
593 g_return_val_if_fail (node->parent == NULL)
594 if (sibling)
595 g_return_val_if_fail (sibling->parent == parent, node);*/
597 g_object_ref_sink (node);
599 node->parent = parent;
600 if (sibling)
602 if (sibling->prev)
604 node->prev = sibling->prev;
605 node->prev->next = node;
606 node->next = sibling;
607 sibling->prev = node;
609 else
611 node->parent->children = node;
612 node->next = sibling;
613 sibling->prev = node;
616 else
618 if (parent->children)
620 sibling = parent->children;
621 while (sibling->next)
622 sibling = sibling->next;
623 node->prev = sibling;
624 sibling->next = node;
626 else
628 node->parent->children = node;
632 return node;
636 * anjuta_project_node_insert_after:
637 * @parent:
638 * @sibling: (allow-none) (transfer none):
639 * @node: (transfer none):
641 * Returns: (transfer none):
643 AnjutaProjectNode *
644 anjuta_project_node_insert_after (AnjutaProjectNode *parent, AnjutaProjectNode *sibling, AnjutaProjectNode *node)
646 g_return_val_if_fail (node != NULL, NULL);
647 g_return_val_if_fail (parent != NULL, node);
649 /* FIXME: Try to avoid filling parent member to allow these checks
650 g_return_val_if_fail (node->parent == NULL)
651 if (sibling)
652 g_return_val_if_fail (sibling->parent == parent, node);*/
654 g_object_ref_sink (node);
656 node->parent = parent;
657 if (sibling)
659 if (sibling->next)
661 sibling->next->prev = node;
663 node->next = sibling->next;
664 node->prev = sibling;
665 sibling->next = node;
667 else
669 if (parent->children)
671 node->next = parent->children;
672 parent->children->prev = node;
674 parent->children = node;
677 return node;
681 * anjuta_project_node_remove:
682 * @node: (transfer none):
684 * Returns: (transfer full):
686 AnjutaProjectNode *
687 anjuta_project_node_remove (AnjutaProjectNode *node)
689 g_return_val_if_fail (node != NULL, NULL);
691 if (node->prev)
692 node->prev->next = node->next;
693 else if (node->parent)
694 node->parent->children = node->next;
695 node->parent = NULL;
696 if (node->next)
698 node->next->prev = node->prev;
699 node->next = NULL;
701 node->prev = NULL;
703 return node;
707 * anjuta_project_node_prepend:
709 * Returns: (transfer none):
711 AnjutaProjectNode *
712 anjuta_project_node_prepend (AnjutaProjectNode *parent, AnjutaProjectNode *node)
714 return anjuta_project_node_insert_before (parent, parent->children, node);
718 * anjuta_project_node_append:
720 * Returns: (transfer none):
722 AnjutaProjectNode *
723 anjuta_project_node_append (AnjutaProjectNode *parent, AnjutaProjectNode *node)
725 return anjuta_project_node_insert_before (parent, NULL, node);
728 /* Access functions
729 *---------------------------------------------------------------------------*/
731 AnjutaProjectNodeType
732 anjuta_project_node_get_node_type (const AnjutaProjectNode *node)
734 return node == NULL ? ANJUTA_PROJECT_UNKNOWN : (node->type & ANJUTA_PROJECT_TYPE_MASK);
737 AnjutaProjectNodeType
738 anjuta_project_node_get_full_type (const AnjutaProjectNode *node)
740 return node == NULL ? ANJUTA_PROJECT_UNKNOWN : node->type;
744 AnjutaProjectNodeState
745 anjuta_project_node_get_state (const AnjutaProjectNode *node)
747 return node == NULL ? ANJUTA_PROJECT_OK : (node->state);
750 const gchar *
751 anjuta_project_node_get_name (const AnjutaProjectNode *node)
753 if ((node->name == NULL) && (node->file != NULL))
755 ((AnjutaProjectNode *)node)->name = g_file_get_basename (node->file);
758 return node->name;
762 * anjuta_project_node_get_file:
764 * Returns: (transfer none):
766 GFile*
767 anjuta_project_node_get_file (const AnjutaProjectNode *node)
769 switch (node->type & ANJUTA_PROJECT_TYPE_MASK)
771 case ANJUTA_PROJECT_OBJECT:
772 case ANJUTA_PROJECT_TARGET:
773 if ((node->name) && (node->parent != NULL) && (node->parent->file != NULL))
775 GFile *file = g_file_get_child (node->parent->file, node->name);
777 if ((node->file != NULL) && g_file_equal (node->file, file))
779 /* Keep the same file */
780 g_object_unref (file);
782 else
784 /* Parent has been updated, update file */
785 if (node->file != NULL) g_object_unref (node->file);
786 ((AnjutaProjectNode *)node)->file = file;
789 break;
790 default:
791 break;
794 return node->file;
798 * anjuta_project_node_get_properties_info:
800 * Returns: (transfer none) (element-type Anjuta.ProjectPropertyInfo):
802 GList *
803 anjuta_project_node_get_properties_info (AnjutaProjectNode *node)
805 return node->properties_info;
809 * anjuta_project_node_get_properties:
811 * Returns: (transfer none) (element-type Anjuta.ProjectProperty):
813 GList *
814 anjuta_project_node_get_properties (AnjutaProjectNode *node)
816 return node->properties;
819 static gint
820 find_property_info (gconstpointer item, gconstpointer data)
822 AnjutaProjectPropertyInfo *info = (AnjutaProjectPropertyInfo *)item;
823 const gchar *id = (const gchar *)data;
825 return strcmp (info->id, id);
829 * anjuta_project_node_get_property_info:
830 * @node: (transfer none):
831 * @id: (transfer none): Property identifier
833 * Returns: (transfer none):
835 AnjutaProjectPropertyInfo *
836 anjuta_project_node_get_property_info (AnjutaProjectNode *node,
837 const gchar *id)
839 GList *found;
841 /* Find property info */
842 found = g_list_find_custom (node->properties_info, id, find_property_info);
844 return found != NULL ? (AnjutaProjectPropertyInfo *)found->data : NULL;
847 static gint
848 find_property (gconstpointer item, gconstpointer data)
850 AnjutaProjectProperty *prop = (AnjutaProjectProperty *)item;
851 AnjutaProjectPropertyInfo *info = (AnjutaProjectPropertyInfo *)data;
853 return prop->info != info;
857 * anjuta_project_node_get_property:
858 * @node: (transfer none):
859 * @id: (transfer none): Property identifier
861 * Returns: (transfer none):
863 AnjutaProjectProperty *
864 anjuta_project_node_get_property (AnjutaProjectNode *node, const gchar *id)
866 AnjutaProjectPropertyInfo *info;
867 AnjutaProjectProperty *prop = NULL;
869 /* Find property info */
870 info = anjuta_project_node_get_property_info (node, id);
871 if (info != NULL)
873 GList *found;
875 /* Get default property */
876 prop = info->default_value;
878 /* Find custom property */
879 found = g_list_find_custom (node->properties, info, find_property);
880 if (found != NULL)
882 prop = (AnjutaProjectProperty *)found->data;
886 return prop;
889 /* If name is specified, look for a property with the same name, useful for
890 * map properties */
891 AnjutaProjectProperty *
892 anjuta_project_node_get_map_property (AnjutaProjectNode *node, const gchar *id, const gchar *name)
894 AnjutaProjectPropertyInfo *info;
895 AnjutaProjectProperty *prop = NULL;
897 /* Find property info */
898 info = anjuta_project_node_get_property_info (node, id);
899 if (info != NULL)
901 GList *found;
903 /* Get default property */
904 prop = info->default_value;
906 /* Find property */
907 found = node->properties;
910 found = g_list_find_custom (found, info, find_property);
911 if (found != NULL)
913 prop = (AnjutaProjectProperty *)found->data;
914 if ((info->type != ANJUTA_PROJECT_PROPERTY_MAP) || (g_strcmp0 (prop->name, name) == 0)) break;
915 prop = NULL;
916 found = g_list_next (found);
919 while (found != NULL);
922 return prop;
925 /* Set functions
926 *---------------------------------------------------------------------------*/
928 gboolean
929 anjuta_project_node_set_state (AnjutaProjectNode *node, AnjutaProjectNodeState state)
931 if (node == NULL) return FALSE;
932 node->state |= state;
933 return TRUE;
936 gboolean
937 anjuta_project_node_clear_state (AnjutaProjectNode *node, AnjutaProjectNodeState state)
939 if (node == NULL) return FALSE;
940 node->state &= ~state;
941 return TRUE;
945 * anjuta_project_node_insert_property_info:
946 * @node: (transfer none):
947 * @info: (transfer none):
949 * Returns: (transfer none):
952 AnjutaProjectPropertyInfo *
953 anjuta_project_node_insert_property_info (AnjutaProjectNode *node,
954 AnjutaProjectPropertyInfo *info)
956 node->properties_info = g_list_append (node->properties_info, info);
958 return info;
962 * anjuta_project_node_insert_property:
963 * @node: (transfer none):
964 * @info: (transfer none):
965 * @property: (transfer full):
967 * Returns: (transfer none):
970 AnjutaProjectProperty *
971 anjuta_project_node_insert_property (AnjutaProjectNode *node, AnjutaProjectPropertyInfo *info, AnjutaProjectProperty *property)
973 /* Make sure the property is native */
974 property->info = info;
976 /* Add in properties list */
977 node->properties = g_list_append (node->properties, property);
979 return property;
982 AnjutaProjectProperty *
983 anjuta_project_node_remove_property (AnjutaProjectNode *node, AnjutaProjectProperty *prop)
985 /* Search the exact property, useful for list property */
986 if (prop != prop->info->default_value)
988 node->properties = g_list_remove (node->properties, prop);
991 return prop;
995 /* Get node from file functions
996 *---------------------------------------------------------------------------*/
998 static gboolean
999 anjuta_project_group_compare (AnjutaProjectNode *node, gpointer data)
1001 GFile *file = (GFile *)data;
1003 if (((node->type & ANJUTA_PROJECT_TYPE_MASK) == ANJUTA_PROJECT_GROUP) && g_file_equal (node->file, file))
1005 return TRUE;
1007 else
1009 return FALSE;
1014 * anjuta_project_node_get_group_from_file:
1015 * @root: the root node
1016 * @directory: Directory to search in
1018 * Returns: (transfer none):
1020 AnjutaProjectNode *
1021 anjuta_project_node_get_group_from_file (const AnjutaProjectNode *root, GFile *directory)
1023 AnjutaProjectNode *node;
1025 node = anjuta_project_node_traverse ((AnjutaProjectNode *)root, G_PRE_ORDER, anjuta_project_group_compare, directory);
1027 return node;
1030 static gboolean
1031 anjuta_project_target_compare (AnjutaProjectNode *node, gpointer data)
1033 const gchar *name = (gchar *)data;
1035 if (((node->type & ANJUTA_PROJECT_TYPE_MASK) == ANJUTA_PROJECT_TARGET) && (strcmp (node->name, name) == 0))
1037 return TRUE;
1039 else
1041 return FALSE;
1045 AnjutaProjectNode *
1046 anjuta_project_target_get_node_from_name (const AnjutaProjectNode *parent, const gchar *name)
1048 AnjutaProjectNode *node;
1050 node = anjuta_project_node_traverse ((AnjutaProjectNode *)parent, G_PRE_ORDER, anjuta_project_target_compare, (gpointer)name);
1052 return node;
1055 static gboolean
1056 anjuta_project_source_compare (AnjutaProjectNode *node, gpointer data)
1058 GFile *file = (GFile *)data;
1060 if (((node->type & ANJUTA_PROJECT_TYPE_MASK) == ANJUTA_PROJECT_SOURCE) && g_file_equal (node->file, file))
1062 return TRUE;
1064 else
1066 return FALSE;
1071 * anjuta_project_node_get_source_from_file:
1072 * @parent: the parent node
1073 * @file: The file to query the source for
1075 * Returns: (transfer none):
1077 AnjutaProjectNode *
1078 anjuta_project_node_get_source_from_file (const AnjutaProjectNode *parent, GFile *file)
1080 AnjutaProjectNode *node;
1083 node = anjuta_project_node_traverse ((AnjutaProjectNode *)parent, G_PRE_ORDER, anjuta_project_source_compare, (gpointer)file);
1085 return node;
1089 /* Implement GObject
1090 *---------------------------------------------------------------------------*/
1092 enum
1094 UPDATED,
1095 LOADED,
1096 LAST_SIGNAL
1099 enum {
1100 PROP_NONE,
1101 PROP_NAME,
1102 PROP_FILE,
1103 PROP_STATE,
1104 PROP_TYPE
1108 static unsigned int anjuta_project_node_signals[LAST_SIGNAL] = { 0 };
1110 G_DEFINE_TYPE (AnjutaProjectNode, anjuta_project_node, G_TYPE_INITIALLY_UNOWNED);
1112 static void
1113 anjuta_project_node_init (AnjutaProjectNode *node)
1115 node->next = NULL;
1116 node->prev = NULL;
1117 node->parent = NULL;
1118 node->children = NULL;
1120 node->type = 0;
1121 node->state = 0;
1122 node->properties = NULL;
1123 node->properties_info = NULL;
1124 node->file = NULL;
1125 node->name = NULL;
1128 static void
1129 anjuta_project_node_dispose (GObject *object)
1131 AnjutaProjectNode *node = ANJUTA_PROJECT_NODE(object);
1133 anjuta_project_node_remove (node);
1135 if (node->file != NULL) g_object_unref (node->file);
1136 node->file = NULL;
1138 while (node->children != NULL)
1140 AnjutaProjectNode *child;
1142 child = anjuta_project_node_remove (node->children);
1143 g_object_unref (child);
1146 G_OBJECT_CLASS (anjuta_project_node_parent_class)->dispose (object);
1149 static void
1150 anjuta_project_node_finalize (GObject *object)
1152 AnjutaProjectNode *node = ANJUTA_PROJECT_NODE(object);
1154 if (node->name != NULL) g_free (node->name);
1156 g_list_free_full (node->properties, (GDestroyNotify) anjuta_project_property_free);
1157 node->properties = NULL;
1159 g_list_free (node->properties_info);
1160 node->properties_info = NULL;
1162 G_OBJECT_CLASS (anjuta_project_node_parent_class)->finalize (object);
1165 static void
1166 anjuta_project_node_get_gobject_property (GObject *object,
1167 guint prop_id,
1168 GValue *value,
1169 GParamSpec *pspec)
1171 AnjutaProjectNode *node = ANJUTA_PROJECT_NODE(object);
1172 switch (prop_id) {
1173 case PROP_NAME:
1174 g_value_set_string (value, anjuta_project_node_get_name (node));
1175 break;
1176 case PROP_FILE:
1177 g_value_set_object (value, node->file);
1178 break;
1179 case PROP_STATE:
1180 g_value_set_flags (value, anjuta_project_node_get_state (node));
1181 break;
1182 case PROP_TYPE:
1183 g_value_set_flags (value, anjuta_project_node_get_node_type (node));
1184 break;
1185 default:
1186 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1190 static void
1191 anjuta_project_node_set_gobject_property (GObject *object,
1192 guint prop_id,
1193 const GValue *value,
1194 GParamSpec *pspec)
1196 AnjutaProjectNode *node = ANJUTA_PROJECT_NODE(object);
1197 switch (prop_id) {
1198 case PROP_NAME:
1199 if (node->name != NULL)
1200 g_free (node->name);
1201 node->name = g_value_dup_string (value);
1202 break;
1203 case PROP_FILE:
1204 if (node->file != NULL)
1205 g_object_unref (node->file);
1206 node->file = g_value_dup_object (value);
1207 break;
1208 case PROP_STATE:
1209 anjuta_project_node_set_state (node, g_value_get_flags (value));
1210 break;
1211 case PROP_TYPE:
1212 node->type = g_value_get_flags (value);
1213 break;
1214 default:
1215 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1219 static void
1220 anjuta_project_node_class_init (AnjutaProjectNodeClass *klass)
1222 GObjectClass* object_class = G_OBJECT_CLASS (klass);
1223 GParamSpec* pspec;
1225 object_class->finalize = anjuta_project_node_finalize;
1226 object_class->dispose = anjuta_project_node_dispose;
1227 object_class->get_property = anjuta_project_node_get_gobject_property;
1228 object_class->set_property = anjuta_project_node_set_gobject_property;
1230 /*Change both signal to use marshal_VOID__POINTER_BOXED
1231 adding a AnjutaProjectNode pointer corresponding to the
1232 loaded node => done
1233 Such marshal doesn't exist as glib marshal, so look in the
1234 symbol db plugin how to add new marshal => done
1235 ToDo :
1236 This new argument can be used in the plugin object in
1237 order to add corresponding shortcut when the project
1238 is loaded and a new node is loaded.
1239 The plugin should probably get the GFile from the
1240 AnjutaProjectNode object and then use a function
1241 in project-view.c to create the corresponding shortcut*/
1243 anjuta_project_node_signals[UPDATED] = g_signal_new ("updated",
1244 G_OBJECT_CLASS_TYPE (object_class),
1245 G_SIGNAL_RUN_LAST,
1246 G_STRUCT_OFFSET (AnjutaProjectNodeClass, updated),
1247 NULL, NULL,
1248 anjuta_cclosure_marshal_VOID__STRING_BOXED,
1249 G_TYPE_NONE,
1251 G_TYPE_POINTER,
1252 G_TYPE_ERROR);
1254 anjuta_project_node_signals[LOADED] = g_signal_new ("loaded",
1255 G_OBJECT_CLASS_TYPE (object_class),
1256 G_SIGNAL_RUN_LAST,
1257 G_STRUCT_OFFSET (AnjutaProjectNodeClass, loaded),
1258 NULL, NULL,
1259 anjuta_cclosure_marshal_VOID__STRING_BOXED,
1260 G_TYPE_NONE,
1262 G_TYPE_POINTER,
1263 G_TYPE_ERROR);
1265 pspec = g_param_spec_flags ("type",
1266 "Type",
1267 "Node type",
1268 ANJUTA_TYPE_PROJECT_NODE_TYPE,
1270 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1271 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_TYPE,
1272 pspec);
1274 pspec = g_param_spec_flags ("state",
1275 "State",
1276 "Node state",
1277 ANJUTA_TYPE_PROJECT_NODE_STATE,
1279 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1280 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_STATE,
1281 pspec);
1283 pspec = g_param_spec_string ("name",
1284 "Name",
1285 "Node name",
1287 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1288 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_NAME,
1289 pspec);
1291 pspec = g_param_spec_object ("file",
1292 "File",
1293 "The GFile for the node",
1294 G_TYPE_FILE,
1295 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1296 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_FILE,
1297 pspec);
1303 /* Node information
1304 *---------------------------------------------------------------------------*/
1306 /* Public functions
1307 *---------------------------------------------------------------------------*/
1309 const gchar *
1310 anjuta_project_node_info_name (const AnjutaProjectNodeInfo *info)
1312 return info->name;
1315 const gchar *
1316 anjuta_project_node_info_mime (const AnjutaProjectNodeInfo *info)
1318 return info->mime_type;
1321 AnjutaProjectNodeType
1322 anjuta_project_node_info_type (const AnjutaProjectNodeInfo *info)
1324 return info->type;
1327 const gchar *
1328 anjuta_project_node_info_property_help_id (const AnjutaProjectNodeInfo *info)
1330 return info->property_help_id;
1334 * anjuta_project_node_info_new:
1335 * @name: (transfer none):
1336 * @mime_type: (transfer none):
1338 * Returns: (transfer full):
1340 AnjutaProjectNodeInfo *
1341 anjuta_project_node_info_new (AnjutaProjectNodeType type,
1342 const gchar *name,
1343 const gchar *mime_type)
1345 AnjutaProjectNodeInfo *info = g_slice_new0 (AnjutaProjectNodeInfo);
1346 info->type = type;
1347 info->name = g_strdup (name);
1348 info->mime_type = g_strdup (mime_type);
1350 return info;
1353 AnjutaProjectNodeInfo *
1354 anjuta_project_node_info_copy (AnjutaProjectNodeInfo *info)
1356 return anjuta_project_node_info_new (info->type, info->name, info->mime_type);
1359 void anjuta_project_node_info_free (AnjutaProjectNodeInfo *info)
1361 g_slice_free (AnjutaProjectNodeInfo, info);
1364 /* Implement Boxed type
1365 *---------------------------------------------------------------------------*/
1367 GType
1368 anjuta_project_node_info_get_type ()
1370 static GType type_id = 0;
1372 if (!type_id)
1373 type_id = g_boxed_type_register_static ("AnjutaProjectNodeInfo",
1374 (GBoxedCopyFunc) anjuta_project_node_info_copy,
1375 (GBoxedFreeFunc) anjuta_project_node_info_free);
1377 return type_id;