project-wizard: Display only useful page on the sidebar
[anjuta.git] / libanjuta / anjuta-project.c
blob0b092a1ebb4f9224ef84bd9305ed5490029e295a
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>
5 *
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.
59 */
61 /* Node properties
62 *---------------------------------------------------------------------------*/
64 /* Implement Boxed type
65 *---------------------------------------------------------------------------*/
67 /**
68 * anjuta_project_property_new:
69 * @id: (transfer none):
70 * @name: (transfer none):
71 * @value: (transfer none):
72 * @native: (allow-none) (transfer none):
74 * Returns: (transfer full):
76 AnjutaProjectProperty *
77 anjuta_project_property_new (const gchar* id, const gchar *name, AnjutaProjectValueType type,
78 const gchar *value, AnjutaProjectProperty *native)
80 AnjutaProjectProperty *prop = g_slice_new0(AnjutaProjectProperty);
81 prop->id = g_strdup (id);
82 prop->name = g_strdup (name);
83 prop->type = type;
84 prop->value = g_strdup (value);
86 if (native != NULL) {
87 prop->native = native;
88 prop->flags = native->flags;
89 prop->detail = native->detail;
92 return prop;
95 AnjutaProjectProperty *
96 anjuta_project_property_copy (AnjutaProjectProperty *prop)
98 return anjuta_project_property_new (prop->id, prop->name, prop->type,
99 prop->value, prop->native);
102 void
103 anjuta_project_property_free (AnjutaProjectProperty *prop)
105 g_free (prop->name);
106 g_free (prop->value);
107 g_slice_free (AnjutaProjectProperty, prop);
110 GType
111 anjuta_project_property_get_type (void)
113 static GType type_id = 0;
115 if (!type_id)
116 type_id = g_boxed_type_register_static ("AnjutaProjectProperty",
117 (GBoxedCopyFunc) anjuta_project_property_copy,
118 (GBoxedFreeFunc) anjuta_project_property_free);
120 return type_id;
125 /* Node
126 *---------------------------------------------------------------------------*/
129 /* Moving in tree functions
130 *---------------------------------------------------------------------------*/
133 * anjuta_project_node_parent:
135 * Returns: (transfer none):
137 AnjutaProjectNode *
138 anjuta_project_node_parent(AnjutaProjectNode *node)
140 g_return_val_if_fail (node != NULL, NULL);
142 return node->parent;
146 * anjuta_project_node_root:
148 * Returns: (transfer none):
150 AnjutaProjectNode *
151 anjuta_project_node_root (AnjutaProjectNode *node)
153 g_return_val_if_fail (node != NULL, NULL);
155 while (node->parent != NULL)
157 node = node->parent;
160 return node;
164 * anjuta_project_node_first_child:
166 * Returns: (transfer none):
169 AnjutaProjectNode *
170 anjuta_project_node_first_child(AnjutaProjectNode *node)
172 g_return_val_if_fail (node != NULL, NULL);
174 return node->children;
178 * anjuta_project_node_last_child:
180 * Returns: (transfer none):
183 AnjutaProjectNode *
184 anjuta_project_node_last_child(AnjutaProjectNode *node)
186 g_return_val_if_fail (node != NULL, NULL);
188 node = node->children;
189 if (node)
190 while (node->next)
191 node = node->next;
193 return node;
197 * anjuta_project_node_next_sibling:
199 * Returns: (transfer none):
201 AnjutaProjectNode *
202 anjuta_project_node_next_sibling (AnjutaProjectNode *node)
204 g_return_val_if_fail (node != NULL, NULL);
206 return node->next;
210 * anjuta_project_node_prev_sibling:
212 * Returns: (transfer none):
214 AnjutaProjectNode *
215 anjuta_project_node_prev_sibling (AnjutaProjectNode *node)
217 g_return_val_if_fail (node != NULL, NULL);
219 return node->prev;
223 * anjuta_project_node_nth_child:
225 * Returns: (transfer none):
227 AnjutaProjectNode *anjuta_project_node_nth_child (AnjutaProjectNode *node, guint n)
229 g_return_val_if_fail (node != NULL, NULL);
231 node = node->children;
232 if (node)
233 while ((n-- > 0) && node)
234 node = node->next;
236 return node;
239 static AnjutaProjectNode *
240 anjuta_project_node_post_order_traverse (AnjutaProjectNode *node, AnjutaProjectNodeTraverseFunc func, gpointer data)
242 AnjutaProjectNode *child;
244 child = node->children;
245 while (child != NULL)
247 AnjutaProjectNode *current;
249 current = child;
250 child = current->next;
251 current = anjuta_project_node_post_order_traverse (current, func, data);
252 if (current != NULL)
254 return current;
258 return func (node, data) ? node : NULL;
261 static AnjutaProjectNode *
262 anjuta_project_node_pre_order_traverse (AnjutaProjectNode *node, AnjutaProjectNodeTraverseFunc func, gpointer data)
264 AnjutaProjectNode *child;
266 if (func (node, data))
268 return node;
271 child = node->children;
272 while (child != NULL)
274 AnjutaProjectNode *current;
276 current = child;
277 child = current->next;
278 current = anjuta_project_node_pre_order_traverse (current, func, data);
279 if (current != NULL)
281 return current;
285 return NULL;
290 * anjuta_project_node_traverse:
291 * @func: (scope call):
293 * Returns: (transfer none):
295 AnjutaProjectNode *
296 anjuta_project_node_traverse (AnjutaProjectNode *node, GTraverseType order, AnjutaProjectNodeTraverseFunc func, gpointer data)
298 g_return_val_if_fail (node != NULL, NULL);
299 g_return_val_if_fail (func != NULL, NULL);
300 g_return_val_if_fail ((order != G_PRE_ORDER) || (order != G_POST_ORDER), NULL);
302 switch (order)
304 case G_PRE_ORDER:
305 return anjuta_project_node_pre_order_traverse (node, func, data);
306 case G_POST_ORDER:
307 return anjuta_project_node_post_order_traverse (node, func, data);
308 default:
309 return NULL;
314 * anjuta_project_node_children_traverse:
315 * @func: (scope call):
317 * Returns: (transfer none):
319 AnjutaProjectNode *
320 anjuta_project_node_children_traverse (AnjutaProjectNode *node, AnjutaProjectNodeTraverseFunc func, gpointer data)
322 AnjutaProjectNode *child;
324 g_return_val_if_fail (node != NULL, NULL);
326 child = node->children;
327 while (child != NULL)
329 AnjutaProjectNode *current;
331 current = child;
332 child = current->next;
333 if (func (current, data))
335 return current;
339 return NULL;
342 static void
343 anjuta_project_node_post_order_foreach (AnjutaProjectNode *node, AnjutaProjectNodeForeachFunc func, gpointer data)
345 AnjutaProjectNode *child;
347 child = node->children;
348 while (child != NULL)
350 AnjutaProjectNode *current;
352 current = child;
353 child = current->next;
354 anjuta_project_node_post_order_foreach (current, func, data);
357 func (node, data);
360 static void
361 anjuta_project_node_pre_order_foreach (AnjutaProjectNode *node, AnjutaProjectNodeForeachFunc func, gpointer data)
363 AnjutaProjectNode *child;
365 func (node, data);
367 child = node->children;
368 while (child != NULL)
370 AnjutaProjectNode *current;
372 current = child;
373 child = current->next;
374 anjuta_project_node_pre_order_foreach (current, func, data);
379 * anjuta_project_node_foreach:
380 * @func: (scope call):
382 void
383 anjuta_project_node_foreach (AnjutaProjectNode *node, GTraverseType order, AnjutaProjectNodeForeachFunc func, gpointer data)
385 g_return_if_fail (node != NULL);
386 g_return_if_fail (func != NULL);
387 g_return_if_fail ((order != G_PRE_ORDER) || (order != G_POST_ORDER));
389 switch (order)
391 case G_PRE_ORDER:
392 anjuta_project_node_pre_order_foreach (node, func, data);
393 break;
394 case G_POST_ORDER:
395 anjuta_project_node_post_order_foreach (node, func, data);
396 break;
397 default:
398 break;
403 * anjuta_project_node_children_foreach:
404 * @func: (scope call):
406 void
407 anjuta_project_node_children_foreach (AnjutaProjectNode *node, AnjutaProjectNodeForeachFunc func, gpointer data)
409 AnjutaProjectNode *child;
411 g_return_if_fail (node != NULL);
413 child = node->children;
414 while (child != NULL)
416 AnjutaProjectNode *current;
418 current = child;
419 child = current->next;
420 func (current, data);
425 * anjuta_project_node_parent_type:
427 * Returns: (transfer none):
429 AnjutaProjectNode *
430 anjuta_project_node_parent_type(AnjutaProjectNode *node, AnjutaProjectNodeType type)
434 node = anjuta_project_node_parent (node);
435 if (node == NULL) break;
437 while (anjuta_project_node_get_node_type (node) != type);
439 return node;
444 /* Debugging functions
445 *---------------------------------------------------------------------------*/
447 static gboolean check_node (AnjutaProjectNode *node, gpointer data)
449 if (!ANJUTA_IS_PROJECT_NODE (node)) g_critical (" Node %p of %p is not a AnjutaProjectNode", node, data);
450 if (node->prev == NULL)
452 if ((node->parent != NULL) && (node->parent->children != node)) g_critical (" Node %p of %p has the wrong parent", node, data);
454 else
456 if (node->prev->next != node) g_critical (" Node %p of %p has the wrong predecessor", node, data);
457 if (node->prev->parent != node->parent) g_critical (" Node %p of %p has the wrong parent", node, data);
459 if (node->next != NULL)
461 if (node->next->prev != node) g_critical (" Node %p of %p has the wrong successor", node, data);
463 if (node->children != NULL)
465 if (node->children->parent != node) g_critical (" Node %p of %p has the wrong children", node, data);
468 return FALSE;
471 void
472 anjuta_project_node_check (AnjutaProjectNode *parent)
474 AnjutaProjectNode *node;
476 g_message ("Check node %p", parent);
477 node = anjuta_project_node_traverse (parent, G_POST_ORDER, check_node, parent);
478 if (node == NULL) g_message (" Node %p is valid", parent);
482 static void
483 anjuta_project_node_show (AnjutaProjectNode *node, gint indent)
485 g_message("%*s %p: %s", indent, "", node, node != NULL ? anjuta_project_node_get_name (node) : NULL);
488 static void
489 anjuta_project_node_dump_child (AnjutaProjectNode *parent, gint indent)
491 AnjutaProjectNode *child;
493 anjuta_project_node_show (parent, indent);
494 indent += 4;
496 for (child = anjuta_project_node_first_child (parent); child != NULL; child = anjuta_project_node_next_sibling (child))
498 anjuta_project_node_dump_child (child, indent);
502 void
503 anjuta_project_node_dump (AnjutaProjectNode *parent)
505 anjuta_project_node_dump_child (parent, 0);
510 /* Adding node functions
511 *---------------------------------------------------------------------------*/
514 * anjuta_project_node_insert_before:
515 * @parent:
516 * @sibling: (allow-none) (transfer none):
517 * @node: (transfer none):
519 * Returns: (transfer none):
521 AnjutaProjectNode *
522 anjuta_project_node_insert_before (AnjutaProjectNode *parent, AnjutaProjectNode *sibling, AnjutaProjectNode *node)
524 g_return_val_if_fail (node != NULL, NULL);
525 g_return_val_if_fail (parent != NULL, node);
527 /* FIXME: Try to avoid filling parent member to allow these checks
528 g_return_val_if_fail (node->parent == NULL)
529 if (sibling)
530 g_return_val_if_fail (sibling->parent == parent, node);*/
532 g_object_ref_sink (node);
534 node->parent = parent;
535 if (sibling)
537 if (sibling->prev)
539 node->prev = sibling->prev;
540 node->prev->next = node;
541 node->next = sibling;
542 sibling->prev = node;
544 else
546 node->parent->children = node;
547 node->next = sibling;
548 sibling->prev = node;
551 else
553 if (parent->children)
555 sibling = parent->children;
556 while (sibling->next)
557 sibling = sibling->next;
558 node->prev = sibling;
559 sibling->next = node;
561 else
563 node->parent->children = node;
567 return node;
571 * anjuta_project_node_insert_after:
572 * @parent:
573 * @sibling: (allow-none) (transfer none):
574 * @node: (transfer none):
576 * Returns: (transfer none):
578 AnjutaProjectNode *
579 anjuta_project_node_insert_after (AnjutaProjectNode *parent, AnjutaProjectNode *sibling, AnjutaProjectNode *node)
581 g_return_val_if_fail (node != NULL, NULL);
582 g_return_val_if_fail (parent != NULL, node);
584 /* FIXME: Try to avoid filling parent member to allow these checks
585 g_return_val_if_fail (node->parent == NULL)
586 if (sibling)
587 g_return_val_if_fail (sibling->parent == parent, node);*/
589 g_object_ref_sink (node);
591 node->parent = parent;
592 if (sibling)
594 if (sibling->next)
596 sibling->next->prev = node;
598 node->next = sibling->next;
599 node->prev = sibling;
600 sibling->next = node;
602 else
604 if (parent->children)
606 node->next = parent->children;
607 parent->children->prev = node;
609 parent->children = node;
612 return node;
616 * anjuta_project_node_remove:
617 * @node: (transfer none):
619 * Returns: (transfer full):
621 AnjutaProjectNode *
622 anjuta_project_node_remove (AnjutaProjectNode *node)
624 g_return_val_if_fail (node != NULL, NULL);
626 if (node->prev)
627 node->prev->next = node->next;
628 else if (node->parent)
629 node->parent->children = node->next;
630 node->parent = NULL;
631 if (node->next)
633 node->next->prev = node->prev;
634 node->next = NULL;
636 node->prev = NULL;
638 return node;
642 * anjuta_project_node_prepend:
644 * Returns: (transfer none):
646 AnjutaProjectNode *
647 anjuta_project_node_prepend (AnjutaProjectNode *parent, AnjutaProjectNode *node)
649 return anjuta_project_node_insert_before (parent, parent->children, node);
653 * anjuta_project_node_append:
655 * Returns: (transfer none):
657 AnjutaProjectNode *
658 anjuta_project_node_append (AnjutaProjectNode *parent, AnjutaProjectNode *node)
660 return anjuta_project_node_insert_before (parent, NULL, node);
663 /* Access functions
664 *---------------------------------------------------------------------------*/
666 AnjutaProjectNodeType
667 anjuta_project_node_get_node_type (const AnjutaProjectNode *node)
669 return node == NULL ? ANJUTA_PROJECT_UNKNOWN : (node->type & ANJUTA_PROJECT_TYPE_MASK);
672 AnjutaProjectNodeType
673 anjuta_project_node_get_full_type (const AnjutaProjectNode *node)
675 return node == NULL ? ANJUTA_PROJECT_UNKNOWN : node->type;
679 AnjutaProjectNodeState
680 anjuta_project_node_get_state (const AnjutaProjectNode *node)
682 return node == NULL ? ANJUTA_PROJECT_OK : (node->state);
685 const gchar *
686 anjuta_project_node_get_name (const AnjutaProjectNode *node)
688 if ((node->name == NULL) && (node->file != NULL))
690 ((AnjutaProjectNode *)node)->name = g_file_get_basename (node->file);
693 return node->name;
697 * anjuta_project_node_get_file:
699 * Returns: (transfer none):
701 GFile*
702 anjuta_project_node_get_file (const AnjutaProjectNode *node)
704 switch (node->type & ANJUTA_PROJECT_TYPE_MASK)
706 case ANJUTA_PROJECT_OBJECT:
707 case ANJUTA_PROJECT_TARGET:
708 if ((node->name) && (node->parent != NULL) && (node->parent->file != NULL))
710 GFile *file = g_file_get_child (node->parent->file, node->name);
712 if ((node->file != NULL) && g_file_equal (node->file, file))
714 /* Keep the same file */
715 g_object_unref (file);
717 else
719 /* Parent has been updated, update file */
720 if (node->file != NULL) g_object_unref (node->file);
721 ((AnjutaProjectNode *)node)->file = file;
724 break;
725 default:
726 break;
729 return node->file;
733 * anjuta_project_node_get_custom_properties:
735 * Returns: (transfer none) (element-type Anjuta.ProjectProperty):
737 GList *
738 anjuta_project_node_get_custom_properties (AnjutaProjectNode *node)
740 return node->custom_properties;
744 * anjuta_project_node_get_native_properties:
746 * Returns: (transfer none) (element-type Anjuta.ProjectProperty):
748 GList *
749 anjuta_project_node_get_native_properties (AnjutaProjectNode *node)
751 return node->native_properties;
754 static gint
755 find_property (gconstpointer item, gconstpointer data)
757 AnjutaProjectProperty *prop_a = (AnjutaProjectProperty *)item;
758 AnjutaProjectProperty *prop_b = (AnjutaProjectProperty *)data;
760 if (prop_a->native != NULL) prop_a = prop_a->native;
761 if (prop_b->native != NULL) prop_b = prop_b->native;
763 return prop_a != prop_b;
767 * anjuta_project_node_get_property:
769 * Returns: (transfer none):
771 AnjutaProjectProperty *
772 anjuta_project_node_get_property (AnjutaProjectNode *node, AnjutaProjectProperty *property)
774 GList *found;
776 /* Search in custom properties */
777 found = g_list_find_custom (node->custom_properties, property, find_property);
779 if (found == NULL)
781 /* Search in native properties */
782 found = g_list_find_custom (node->native_properties, property, find_property);
785 return found != NULL ? (AnjutaProjectProperty *)found->data : NULL;
788 /* If name is specified, look for a property with the same name, useful for
789 * map properties */
790 AnjutaProjectProperty *
791 anjuta_project_node_get_map_property (AnjutaProjectNode *node, AnjutaProjectProperty *property, const gchar *name)
793 GList *found = NULL;
795 /* Check if the property is already the right one */
796 if (property->native != NULL)
798 found = g_list_find (node->custom_properties, property);
801 /* Search in custom properties */
802 if (found == NULL)
804 found = g_list_find_custom (node->custom_properties, property, find_property);
805 if (name != NULL)
807 while ((found != NULL) && (strcmp (name, ((AnjutaProjectProperty *)found->data)->name) != 0))
809 found = g_list_find_custom (g_list_next (found), property, find_property);
814 if (found == NULL)
816 /* Search in native properties */
817 found = g_list_find_custom (node->native_properties, property, find_property);
820 return found != NULL ? (AnjutaProjectProperty *)found->data : NULL;
823 /* Set functions
824 *---------------------------------------------------------------------------*/
826 gboolean
827 anjuta_project_node_set_state (AnjutaProjectNode *node, AnjutaProjectNodeState state)
829 if (node == NULL) return FALSE;
830 node->state |= state;
831 return TRUE;
834 gboolean
835 anjuta_project_node_clear_state (AnjutaProjectNode *node, AnjutaProjectNodeState state)
837 if (node == NULL) return FALSE;
838 node->state &= ~state;
839 return TRUE;
843 * anjuta_project_node_insert_property:
844 * @property: (transfer full):
846 * Returns: (transfer none):
849 AnjutaProjectProperty *
850 anjuta_project_node_insert_property (AnjutaProjectNode *node, AnjutaProjectProperty *native, AnjutaProjectProperty *property)
852 /* Make sure the property is native */
853 if (native->native != NULL) native = native->native;
855 /* Fill missing information */
856 if (property->name == NULL) property->name = native->name;
857 property->type = native->type;
858 property->native = native;
859 property->flags = native->flags;
860 property->detail = native->detail;
862 /* Get properties list */
863 node->custom_properties = g_list_append (node->custom_properties, property);
865 return property;
868 AnjutaProjectProperty *
869 anjuta_project_node_remove_property (AnjutaProjectNode *node, AnjutaProjectProperty *prop)
871 GList *found;
872 AnjutaProjectProperty *removed = NULL;
874 /* Search the exact property, useful for list property */
875 found = g_list_find (node->custom_properties, prop);
876 if (found == NULL)
878 found = g_list_find_custom (node->custom_properties, prop, find_property);
881 if (found != NULL)
883 removed = (AnjutaProjectProperty *)found->data;
884 node->custom_properties = g_list_delete_link (node->custom_properties, found);
885 /* If name is not owned by the property, remove it as the
886 * property can be associated with another one, having a
887 * different name */
888 if ((removed->native != NULL) && (removed->name == removed->native->name))
890 removed->name = NULL;
895 return removed;
899 /* Get node from file functions
900 *---------------------------------------------------------------------------*/
902 static gboolean
903 anjuta_project_group_compare (AnjutaProjectNode *node, gpointer data)
905 GFile *file = (GFile *)data;
907 if (((node->type & ANJUTA_PROJECT_TYPE_MASK) == ANJUTA_PROJECT_GROUP) && g_file_equal (node->file, file))
909 return TRUE;
911 else
913 return FALSE;
918 * anjuta_project_node_get_group_from_file:
919 * @func: (scope call):
921 * Returns: (transfer none):
923 AnjutaProjectNode *
924 anjuta_project_node_get_group_from_file (const AnjutaProjectNode *root, GFile *directory)
926 AnjutaProjectNode *node;
928 node = anjuta_project_node_traverse ((AnjutaProjectNode *)root, G_PRE_ORDER, anjuta_project_group_compare, directory);
930 return node;
933 static gboolean
934 anjuta_project_target_compare (AnjutaProjectNode *node, gpointer data)
936 const gchar *name = (gchar *)data;
938 if (((node->type & ANJUTA_PROJECT_TYPE_MASK) == ANJUTA_PROJECT_TARGET) && (strcmp (node->name, name) == 0))
940 return TRUE;
942 else
944 return FALSE;
948 AnjutaProjectNode *
949 anjuta_project_target_get_node_from_name (const AnjutaProjectNode *parent, const gchar *name)
951 AnjutaProjectNode *node;
953 node = anjuta_project_node_traverse ((AnjutaProjectNode *)parent, G_PRE_ORDER, anjuta_project_target_compare, (gpointer)name);
955 return node;
958 static gboolean
959 anjuta_project_source_compare (AnjutaProjectNode *node, gpointer data)
961 GFile *file = (GFile *)data;
963 if (((node->type & ANJUTA_PROJECT_TYPE_MASK) == ANJUTA_PROJECT_SOURCE) && g_file_equal (node->file, file))
965 return TRUE;
967 else
969 return FALSE;
974 * anjuta_project_node_get_source_from_file:
975 * @func: (scope call):
977 * Returns: (transfer none):
979 AnjutaProjectNode *
980 anjuta_project_node_get_source_from_file (const AnjutaProjectNode *parent, GFile *file)
982 AnjutaProjectNode *node;
985 node = anjuta_project_node_traverse ((AnjutaProjectNode *)parent, G_PRE_ORDER, anjuta_project_source_compare, (gpointer)file);
987 return node;
991 /* Implement GObject
992 *---------------------------------------------------------------------------*/
994 enum
996 UPDATED,
997 LOADED,
998 LAST_SIGNAL
1001 enum {
1002 PROP_NONE,
1003 PROP_NAME,
1004 PROP_FILE,
1005 PROP_STATE,
1006 PROP_TYPE,
1007 PROP_NATIVE_PROPERTIES,
1008 PROP_CUSTOM_PROPERTIES
1012 static unsigned int anjuta_project_node_signals[LAST_SIGNAL] = { 0 };
1014 G_DEFINE_TYPE (AnjutaProjectNode, anjuta_project_node, G_TYPE_INITIALLY_UNOWNED);
1016 static void
1017 anjuta_project_node_init (AnjutaProjectNode *node)
1019 node->next = NULL;
1020 node->prev = NULL;
1021 node->parent = NULL;
1022 node->children = NULL;
1024 node->type = 0;
1025 node->state = 0;
1026 node->native_properties = NULL;
1027 node->custom_properties = NULL;
1028 node->file = NULL;
1029 node->name = NULL;
1032 static void
1033 anjuta_project_node_dispose (GObject *object)
1035 AnjutaProjectNode *node = ANJUTA_PROJECT_NODE(object);
1037 anjuta_project_node_remove (node);
1039 if (node->file != NULL) g_object_unref (node->file);
1040 node->file = NULL;
1042 while (node->children != NULL)
1044 AnjutaProjectNode *child;
1046 child = anjuta_project_node_remove (node->children);
1047 g_object_unref (child);
1050 G_OBJECT_CLASS (anjuta_project_node_parent_class)->dispose (object);
1053 static void
1054 anjuta_project_node_finalize (GObject *object)
1056 AnjutaProjectNode *node = ANJUTA_PROJECT_NODE(object);
1058 if (node->name != NULL) g_free (node->name);
1060 G_OBJECT_CLASS (anjuta_project_node_parent_class)->finalize (object);
1063 static void
1064 anjuta_project_node_get_gobject_property (GObject *object,
1065 guint prop_id,
1066 GValue *value,
1067 GParamSpec *pspec)
1069 AnjutaProjectNode *node = ANJUTA_PROJECT_NODE(object);
1070 switch (prop_id) {
1071 case PROP_NAME:
1072 g_value_set_string (value, anjuta_project_node_get_name (node));
1073 break;
1074 case PROP_FILE:
1075 g_value_set_object (value, node->file);
1076 break;
1077 case PROP_STATE:
1078 g_value_set_flags (value, anjuta_project_node_get_state (node));
1079 break;
1080 case PROP_TYPE:
1081 g_value_set_flags (value, anjuta_project_node_get_node_type (node));
1082 break;
1083 case PROP_NATIVE_PROPERTIES:
1084 g_value_set_pointer (value, node->native_properties);
1085 break;
1086 case PROP_CUSTOM_PROPERTIES:
1087 g_value_set_pointer (value, node->custom_properties);
1088 break;
1089 default:
1090 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1094 static void
1095 anjuta_project_node_set_gobject_property (GObject *object,
1096 guint prop_id,
1097 const GValue *value,
1098 GParamSpec *pspec)
1100 AnjutaProjectNode *node = ANJUTA_PROJECT_NODE(object);
1101 switch (prop_id) {
1102 case PROP_NAME:
1103 if (node->name != NULL)
1104 g_free (node->name);
1105 node->name = g_value_dup_string (value);
1106 break;
1107 case PROP_FILE:
1108 if (node->file != NULL)
1109 g_object_unref (node->file);
1110 node->file = g_value_dup_object (value);
1111 break;
1112 case PROP_STATE:
1113 anjuta_project_node_set_state (node, g_value_get_flags (value));
1114 break;
1115 case PROP_TYPE:
1116 node->type = g_value_get_flags (value);
1117 break;
1118 case PROP_NATIVE_PROPERTIES:
1119 node->native_properties = g_value_get_pointer (value);
1120 break;
1121 /* XXX: We may need to copy this instead */
1122 case PROP_CUSTOM_PROPERTIES:
1123 node->custom_properties = g_value_get_pointer (value);
1124 break;
1125 default:
1126 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1130 static void
1131 anjuta_project_node_class_init (AnjutaProjectNodeClass *klass)
1133 GObjectClass* object_class = G_OBJECT_CLASS (klass);
1134 GParamSpec* pspec;
1136 object_class->finalize = anjuta_project_node_finalize;
1137 object_class->dispose = anjuta_project_node_dispose;
1138 object_class->get_property = anjuta_project_node_get_gobject_property;
1139 object_class->set_property = anjuta_project_node_set_gobject_property;
1141 /*Change both signal to use marshal_VOID__POINTER_BOXED
1142 adding a AnjutaProjectNode pointer corresponding to the
1143 loaded node => done
1144 Such marshal doesn't exist as glib marshal, so look in the
1145 symbol db plugin how to add new marshal => done
1146 ToDo :
1147 This new argument can be used in the plugin object in
1148 order to add corresponding shortcut when the project
1149 is loaded and a new node is loaded.
1150 The plugin should probably get the GFile from the
1151 AnjutaProjectNode object and then use a function
1152 in project-view.c to create the corresponding shortcut*/
1154 anjuta_project_node_signals[UPDATED] = g_signal_new ("updated",
1155 G_OBJECT_CLASS_TYPE (object_class),
1156 G_SIGNAL_RUN_LAST,
1157 G_STRUCT_OFFSET (AnjutaProjectNodeClass, updated),
1158 NULL, NULL,
1159 anjuta_cclosure_marshal_VOID__STRING_BOXED,
1160 G_TYPE_NONE,
1162 G_TYPE_POINTER,
1163 G_TYPE_ERROR);
1165 anjuta_project_node_signals[LOADED] = g_signal_new ("loaded",
1166 G_OBJECT_CLASS_TYPE (object_class),
1167 G_SIGNAL_RUN_LAST,
1168 G_STRUCT_OFFSET (AnjutaProjectNodeClass, loaded),
1169 NULL, NULL,
1170 anjuta_cclosure_marshal_VOID__STRING_BOXED,
1171 G_TYPE_NONE,
1173 G_TYPE_POINTER,
1174 G_TYPE_ERROR);
1176 pspec = g_param_spec_flags ("type",
1177 "Type",
1178 "Node type",
1179 ANJUTA_TYPE_PROJECT_NODE_TYPE,
1181 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1182 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_TYPE,
1183 pspec);
1185 pspec = g_param_spec_flags ("state",
1186 "State",
1187 "Node state",
1188 ANJUTA_TYPE_PROJECT_NODE_STATE,
1190 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1191 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_STATE,
1192 pspec);
1194 pspec = g_param_spec_string ("name",
1195 "Name",
1196 "Node name",
1198 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1199 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_NAME,
1200 pspec);
1202 pspec = g_param_spec_object ("file",
1203 "File",
1204 "The GFile for the node",
1205 G_TYPE_FILE,
1206 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1207 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_FILE,
1208 pspec);
1211 * AnjutaProjectNode:native-properties:
1213 * type: GLib.List<Anjuta.ProjectProperty>
1214 * Transfer: none
1216 pspec = g_param_spec_pointer ("native-properties",
1217 "Native properties",
1218 "The list of all possible properties",
1219 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1220 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_NATIVE_PROPERTIES,
1221 pspec);
1223 * AnjutaProjectNode:custom-properties:
1225 * Type: GLib.List<Anjuta.ProjectProperty>
1226 * Transfer: none
1228 pspec = g_param_spec_pointer ("custom-properties",
1229 "Custom properties",
1230 "The list of overriden properties",
1231 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
1232 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_CUSTOM_PROPERTIES,
1233 pspec);
1239 /* Node information
1240 *---------------------------------------------------------------------------*/
1242 /* Public functions
1243 *---------------------------------------------------------------------------*/
1245 const gchar *
1246 anjuta_project_node_info_name (const AnjutaProjectNodeInfo *info)
1248 return info->name;
1251 const gchar *
1252 anjuta_project_node_info_mime (const AnjutaProjectNodeInfo *info)
1254 return info->mime_type;
1257 AnjutaProjectNodeType
1258 anjuta_project_node_info_type (const AnjutaProjectNodeInfo *info)
1260 return info->type;
1264 * anjuta_project_node_info_new:
1265 * @name: (transfer none):
1266 * @mime_type: (transfer none):
1268 * Returns: (transfer full):
1270 AnjutaProjectNodeInfo *
1271 anjuta_project_node_info_new (AnjutaProjectNodeType type,
1272 const gchar *name,
1273 const gchar *mime_type)
1275 AnjutaProjectNodeInfo *info = g_slice_new0 (AnjutaProjectNodeInfo);
1276 info->type = type;
1277 info->name = g_strdup (name);
1278 info->mime_type = g_strdup (mime_type);
1280 return info;
1283 AnjutaProjectNodeInfo *
1284 anjuta_project_node_info_copy (AnjutaProjectNodeInfo *info)
1286 return anjuta_project_node_info_new (info->type, info->name, info->mime_type);
1289 void anjuta_project_node_info_free (AnjutaProjectNodeInfo *info)
1291 g_slice_free (AnjutaProjectNodeInfo, info);
1294 /* Implement Boxed type
1295 *---------------------------------------------------------------------------*/
1297 GType
1298 anjuta_project_node_info_get_type ()
1300 static GType type_id = 0;
1302 if (!type_id)
1303 type_id = g_boxed_type_register_static ("AnjutaProjectNodeInfo",
1304 (GBoxedCopyFunc) anjuta_project_node_info_copy,
1305 (GBoxedFreeFunc) anjuta_project_node_info_free);
1307 return type_id;