1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4; coding: utf-8 -*- */
4 * Copyright (C) 2009 Sébastien Granjoux
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 of the
9 * License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public
17 * License along with this program; if not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
27 #include "mk-project.h"
30 #include "mk-project-private.h"
32 #include <libanjuta/interfaces/ianjuta-project.h>
33 #include <libanjuta/anjuta-debug.h>
34 #include <libanjuta/anjuta-utils.h>
35 #include <libanjuta/anjuta-pkg-config.h>
43 #include <sys/types.h>
45 #include <glib/gi18n.h>
48 #include "mk-scanner.h"
51 #define UNIMPLEMENTED G_STMT_START { g_warning (G_STRLOC": unimplemented"); } G_STMT_END
53 /* Constant strings for parsing perl script error output */
54 #define ERROR_PREFIX "ERROR("
55 #define WARNING_PREFIX "WARNING("
56 #define MESSAGE_DELIMITER ": "
58 static const gchar
*valid_makefiles
[] = {"GNUmakefile", "makefile", "Makefile", NULL
};
62 *---------------------------------------------------------------------------*/
64 static MkpNodeInfo MkpNodeInformation
[] = {
65 {{ANJUTA_PROJECT_GROUP
,
69 {{ANJUTA_PROJECT_SOURCE
,
73 {{ANJUTA_PROJECT_TARGET
,
77 {{ANJUTA_PROJECT_UNKNOWN
,
83 /* ----- Standard GObject types and variables ----- */
90 static GObject
*parent_class
;
93 *---------------------------------------------------------------------------*/
97 error_set (GError
**error
, gint code
, const gchar
*message
)
100 if (*error
!= NULL
) {
103 /* error already created, just change the code
104 * and prepend the string */
105 (*error
)->code
= code
;
106 tmp
= (*error
)->message
;
107 (*error
)->message
= g_strconcat (message
, "\n\n", tmp
, NULL
);
111 *error
= g_error_new_literal (IANJUTA_PROJECT_ERROR
,
119 /* Work even if file is not a descendant of parent */
121 get_relative_path (GFile
*parent
, GFile
*file
)
125 relative
= g_file_get_relative_path (parent
, file
);
126 if (relative
== NULL
)
128 if (g_file_equal (parent
, file
))
130 relative
= g_strdup ("");
134 GFile
*grand_parent
= g_file_get_parent (parent
);
136 gchar
*grand_relative
;
141 for (level
= 1; !g_file_has_prefix (file
, grand_parent
); level
++)
143 GFile
*next
= g_file_get_parent (grand_parent
);
145 g_object_unref (grand_parent
);
149 grand_relative
= g_file_get_relative_path (grand_parent
, file
);
150 g_object_unref (grand_parent
);
152 len
= strlen (grand_relative
);
153 relative
= g_new (gchar
, len
+ level
* 3 + 1);
155 for (; level
; level
--)
157 memcpy(ptr
, ".." G_DIR_SEPARATOR_S
, 3);
160 memcpy (ptr
, grand_relative
, len
+ 1);
161 g_free (grand_relative
);
169 file_type (GFile
*file
, const gchar
*filename
)
175 child
= filename
!= NULL
? g_file_get_child (file
, filename
) : g_object_ref (file
);
177 //g_message ("check file %s", g_file_get_path (child));
179 info
= g_file_query_info (child
,
180 G_FILE_ATTRIBUTE_STANDARD_TYPE
,
181 G_FILE_QUERY_INFO_NONE
,
186 type
= g_file_info_get_file_type (info
);
187 g_object_unref (info
);
191 type
= G_FILE_TYPE_UNKNOWN
;
194 g_object_unref (child
);
200 *---------------------------------------------------------------------------*/
202 static AnjutaProjectNode
*
203 mkp_group_new (GFile
*file
)
205 MkpGroup
*group
= g_object_new (MKP_TYPE_GROUP
, NULL
);;
206 group
->base
.file
= g_object_ref (file
);
208 group
->base
.type
= ANJUTA_PROJECT_GROUP
;
209 group
->base
.native_properties
= NULL
;
210 group
->base
.custom_properties
= NULL
;
211 group
->base
.name
= NULL
;
212 group
->base
.state
= 0;
215 return ANJUTA_PROJECT_NODE(group
);
219 mkp_group_class_init (MkpGroupClass
*klass
)
225 mkp_group_init (MkpGroup
*obj
)
230 G_DEFINE_TYPE (MkpGroup
, mkp_group
, ANJUTA_TYPE_PROJECT_NODE
);
233 *---------------------------------------------------------------------------*/
236 mkp_target_add_token (MkpTarget
*target
, AnjutaToken
*token
)
238 target
->tokens
= g_list_prepend (target
->tokens
, token
);
243 mkp_target_get_token (MkpTarget
*target
)
245 return target
->tokens
;
249 mkp_target_new (const gchar
*name
, AnjutaProjectNodeType type
)
251 MkpTarget
*target
= NULL
;
253 target
= g_object_new (MKP_TYPE_TARGET
, NULL
);
254 target
->base
.name
= g_strdup (name
);
255 target
->base
.type
= ANJUTA_PROJECT_TARGET
;
256 target
->base
.state
= 0;
258 return ANJUTA_PROJECT_NODE(target
);
262 mkp_target_class_init (MkpTargetClass
*klass
)
268 mkp_target_init (MkpTarget
*obj
)
273 G_DEFINE_TYPE (MkpTarget
, mkp_target
, ANJUTA_TYPE_PROJECT_NODE
);
276 *---------------------------------------------------------------------------*/
279 mkp_object_new (const gchar
*name
)
281 MkpObject
*node
= NULL
;
283 node
= g_object_new (MKP_TYPE_OBJECT
, NULL
);
284 node
->base
.name
= g_strdup (name
);
285 node
->base
.type
= ANJUTA_PROJECT_OBJECT
;
286 node
->base
.state
= 0;
288 return ANJUTA_PROJECT_NODE(node
);
292 mkp_object_class_init (MkpObjectClass
*klass
)
298 mkp_object_init (MkpObject
*obj
)
303 G_DEFINE_TYPE (MkpObject
, mkp_object
, ANJUTA_TYPE_PROJECT_NODE
);
307 *---------------------------------------------------------------------------*/
310 mkp_source_new (GFile
*file
)
312 MkpSource
*source
= NULL
;
314 source
= g_object_new (MKP_TYPE_SOURCE
, NULL
);
315 source
->base
.file
= g_object_ref (file
);
316 source
->base
.type
= ANJUTA_PROJECT_SOURCE
;
317 source
->base
.native_properties
= NULL
;
318 source
->base
.custom_properties
= NULL
;
319 source
->base
.name
= NULL
;
320 source
->base
.state
= 0;
322 return ANJUTA_PROJECT_NODE (source
);
326 mkp_source_class_init (MkpSourceClass
*klass
)
332 mkp_source_init (MkpSource
*obj
)
337 G_DEFINE_TYPE (MkpSource
, mkp_source
, ANJUTA_TYPE_PROJECT_NODE
);
340 * File monitoring support --------------------------------
341 * FIXME: review these
344 monitor_cb (GFileMonitor
*monitor
,
347 GFileMonitorEvent event_type
,
350 MkpProject
*project
= data
;
352 g_return_if_fail (project
!= NULL
&& MKP_IS_PROJECT (project
));
354 switch (event_type
) {
355 case G_FILE_MONITOR_EVENT_CHANGED
:
356 case G_FILE_MONITOR_EVENT_CREATED
:
357 g_signal_emit_by_name (G_OBJECT (project
), "file-changed", data
);
366 monitor_add (MkpProject
*project
, GFile
*file
)
368 GFileMonitor
*monitor
= NULL
;
370 g_return_if_fail (project
!= NULL
);
371 g_return_if_fail (project
->monitors
!= NULL
);
376 monitor
= g_hash_table_lookup (project
->monitors
, file
);
380 /* FIXME clarify if uri is uri, path or both */
381 exists
= g_file_query_exists (file
, NULL
);
384 monitor
= g_file_monitor_file (file
,
390 g_signal_connect (G_OBJECT (monitor
),
392 G_CALLBACK (monitor_cb
),
394 g_hash_table_insert (project
->monitors
,
403 monitors_remove (MkpProject
*project
)
405 g_return_if_fail (project
!= NULL
);
407 if (project
->monitors
)
408 g_hash_table_destroy (project
->monitors
);
409 project
->monitors
= NULL
;
413 files_hash_foreach_monitor (gpointer key
,
417 GFile
*makefile
= (GFile
*)key
;
418 MkpProject
*project
= user_data
;
420 monitor_add (project
, makefile
);
424 monitors_setup (MkpProject
*project
)
426 g_return_if_fail (project
!= NULL
);
428 monitors_remove (project
);
430 /* setup monitors hash */
431 project
->monitors
= g_hash_table_new_full (g_direct_hash
, g_direct_equal
, NULL
,
432 (GDestroyNotify
) g_file_monitor_cancel
);
435 g_hash_table_foreach (project
->files
, files_hash_foreach_monitor
, project
);
440 * ---------------- Data structures managment
443 static AnjutaProjectNode
*
444 project_node_new (MkpProject
*project
, AnjutaProjectNode
*parent
, AnjutaProjectNodeType type
, GFile
*file
, const gchar
*name
, GError
**error
)
446 AnjutaProjectNode
*node
= NULL
;
448 switch (type
& ANJUTA_PROJECT_TYPE_MASK
) {
449 case ANJUTA_PROJECT_ROOT
:
450 case ANJUTA_PROJECT_GROUP
:
451 node
= ANJUTA_PROJECT_NODE (mkp_group_new (file
));
453 case ANJUTA_PROJECT_TARGET
:
454 node
= ANJUTA_PROJECT_NODE (mkp_target_new (name
, 0));
456 case ANJUTA_PROJECT_SOURCE
:
457 node
= ANJUTA_PROJECT_NODE (mkp_source_new (file
));
460 g_assert_not_reached ();
463 if (node
!= NULL
) node
->type
= type
;
468 static AnjutaProjectNode
*
469 project_load_makefile (MkpProject
*project
, GFile
*file
, MkpGroup
*parent
, GError
**error
)
473 AnjutaTokenFile
*tfile
;
479 DEBUG_PRINT ("Parse: %s", g_file_get_uri (file
));
480 tfile
= anjuta_token_file_new (file
);
481 g_hash_table_insert (project
->files
, g_object_ref (file
), g_object_ref (tfile
));
482 arg
= anjuta_token_file_load (tfile
, NULL
);
483 scanner
= mkp_scanner_new (project
);
484 parse
= mkp_scanner_parse_token (scanner
, arg
, &err
);
486 mkp_scanner_free (scanner
);
491 g_set_error_literal (error
, IANJUTA_PROJECT_ERROR
,
492 IANJUTA_PROJECT_ERROR_PROJECT_MALFORMED
,
498 g_set_error (error
, IANJUTA_PROJECT_ERROR
,
499 IANJUTA_PROJECT_ERROR_PROJECT_MALFORMED
,
500 _("Unable to parse make file"));
507 mkp_project_enumerate_targets (project
, ANJUTA_PROJECT_NODE(parent
));
509 return ANJUTA_PROJECT_NODE(parent
);
512 /* Project access functions
513 *---------------------------------------------------------------------------*/
516 mkp_project_get_root (MkpProject
*project
)
518 return MKP_PROJECT(project
);
522 mkp_project_get_node_info (MkpProject
*project
, GError
**error
)
524 static GList
*info_list
= NULL
;
526 if (info_list
== NULL
)
530 for (node
= MkpNodeInformation
; node
->base
.type
!= 0; node
++)
532 info_list
= g_list_prepend (info_list
, node
);
535 info_list
= g_list_reverse (info_list
);
542 mkp_project_get_token_location (MkpProject
*project
, AnjutaTokenFileLocation
*location
, AnjutaToken
*token
)
548 g_hash_table_iter_init (&iter
, project
->files
);
549 while (g_hash_table_iter_next (&iter
, &key
, &value
))
551 if (anjuta_token_file_get_token_location ((AnjutaTokenFile
*)value
, location
, token
))
560 /* Variable access functions
561 *---------------------------------------------------------------------------*/
564 mkp_variable_get_name (MkpVariable
*variable
)
566 return variable
->name
;
570 mkp_variable_evaluate (MkpVariable
*variable
, MkpProject
*project
)
572 return anjuta_token_evaluate (variable
->value
);
576 mkp_variable_new (gchar
*name
, AnjutaTokenType assign
, AnjutaToken
*value
)
578 MkpVariable
*variable
= NULL
;
580 g_return_val_if_fail (name
!= NULL
, NULL
);
582 variable
= g_slice_new0(MkpVariable
);
583 variable
->name
= g_strdup (name
);
584 variable
->assign
= assign
;
585 variable
->value
= value
;
591 mkp_variable_free (MkpVariable
*variable
)
593 g_free (variable
->name
);
595 g_slice_free (MkpVariable
, variable
);
599 *---------------------------------------------------------------------------*/
602 mkp_project_update_variable (MkpProject
*project
, AnjutaToken
*variable
)
606 MakeTokenType assign
= 0;
607 AnjutaToken
*value
= NULL
;
609 //fprintf(stdout, "update variable");
610 //anjuta_token_dump (variable);
612 arg
= anjuta_token_first_item (variable
);
613 name
= g_strstrip (anjuta_token_evaluate (arg
));
614 arg
= anjuta_token_next_item (arg
);
616 //g_message ("new variable %s", name);
617 switch (anjuta_token_get_type (arg
))
620 case MK_TOKEN_IMMEDIATE_EQUAL
:
621 case MK_TOKEN_CONDITIONAL_EQUAL
:
622 case MK_TOKEN_APPEND
:
623 assign
= anjuta_token_get_type (arg
);
629 value
= anjuta_token_next_item (arg
);
635 //g_message ("assign %d name %s value %s\n", assign, name, anjuta_token_evaluate (value));
636 var
= (MkpVariable
*)g_hash_table_lookup (project
->variables
, name
);
639 var
->assign
= assign
;
644 var
= mkp_variable_new (name
, assign
, value
);
645 g_hash_table_insert (project
->variables
, var
->name
, var
);
650 //g_message ("update variable %s", name);
652 if (name
) g_free (name
);
656 mkp_project_get_variable_token (MkpProject
*project
, AnjutaToken
*variable
)
663 length
= anjuta_token_get_length (variable
);
664 string
= anjuta_token_get_string (variable
);
665 if (string
[1] == '(')
667 name
= g_strndup (string
+ 2, length
- 3);
671 name
= g_strndup (string
+ 1, 1);
673 var
= g_hash_table_lookup (project
->variables
, name
);
676 return var
!= NULL
? var
->value
: NULL
;
679 static AnjutaProjectNode
*
680 mkp_project_load_root (MkpProject
*project
, AnjutaProjectNode
*node
, GError
**error
)
683 GFile
*make_file
= NULL
;
684 const gchar
**makefile
;
687 /* Unload current project */
688 root_file
= g_object_ref (anjuta_project_node_get_file (node
));
689 mkp_project_unload (project
);
690 project
->root_file
= root_file
;
691 DEBUG_PRINT ("reload project %p root file %p", project
, project
->root_file
);
693 /* shortcut hash tables */
694 project
->groups
= g_hash_table_new_full (g_str_hash
, g_str_equal
, g_free
, NULL
);
695 project
->files
= g_hash_table_new_full (g_file_hash
, (GEqualFunc
)g_file_equal
, g_object_unref
, g_object_unref
);
696 project
->variables
= g_hash_table_new_full (g_str_hash
, g_str_equal
, NULL
, (GDestroyNotify
)mkp_variable_free
);
698 /* Initialize rules data */
699 mkp_project_init_rules (project
);
701 /* Initialize list styles */
702 project
->space_list
= anjuta_token_style_new (NULL
, " ", "\n", NULL
, 0);
703 project
->arg_list
= anjuta_token_style_new (NULL
, ", ", ",\n ", ")", 0);
706 for (makefile
= valid_makefiles
; *makefile
!= NULL
; makefile
++)
708 if (file_type (root_file
, *makefile
) == G_FILE_TYPE_REGULAR
)
710 make_file
= g_file_get_child (root_file
, *makefile
);
714 if (make_file
== NULL
)
716 g_set_error (error
, IANJUTA_PROJECT_ERROR
,
717 IANJUTA_PROJECT_ERROR_DOESNT_EXIST
,
718 _("Project doesn't exist or invalid path"));
724 group
= MKP_GROUP(mkp_group_new (root_file
));
725 anjuta_project_node_append (node
, ANJUTA_PROJECT_NODE(group
));
726 g_hash_table_insert (project
->groups
, g_file_get_uri (root_file
), group
);
729 /* Parse make file */
730 project_load_makefile (project
, make_file
, group
, error
);
731 g_object_unref (make_file
);
733 monitors_setup (project
);
739 mkp_project_load_node (MkpProject
*project
, AnjutaProjectNode
*node
, GError
**error
)
741 switch (anjuta_project_node_get_node_type (node
))
743 case ANJUTA_PROJECT_ROOT
:
745 DEBUG_PRINT("*** Loading project: %p root file: %p\n", project
, project
->root_file
);
746 return mkp_project_load_root (project
, node
, error
);
747 case ANJUTA_PROJECT_GROUP
:
749 return project_load_makefile (project
, node
->file
, MKP_GROUP(node
), error
);
756 mkp_project_reload (MkpProject
*project
, GError
**error
)
760 const gchar
**makefile
;
764 /* Unload current project */
765 root_file
= g_object_ref (project
->root_file
);
766 mkp_project_unload (project
);
767 project
->root_file
= root_file
;
768 DEBUG_PRINT ("reload project %p root file %p", project
, project
->root_file
);
770 /* shortcut hash tables */
771 project
->groups
= g_hash_table_new_full (g_str_hash
, g_str_equal
, g_free
, NULL
);
772 project
->files
= g_hash_table_new_full (g_file_hash
, (GEqualFunc
)g_file_equal
, g_object_unref
, g_object_unref
);
773 project
->variables
= g_hash_table_new_full (g_str_hash
, g_str_equal
, NULL
, (GDestroyNotify
)mkp_variable_free
);
775 /* Initialize rules data */
776 mkp_project_init_rules (project
);
778 /* Initialize list styles */
779 project
->space_list
= anjuta_token_style_new (NULL
, " ", "\n", NULL
, 0);
780 project
->arg_list
= anjuta_token_style_new (NULL
, ", ", ",\n ", ")", 0);
783 for (makefile
= valid_makefiles
; *makefile
!= NULL
; makefile
++)
785 if (file_type (root_file
, *makefile
) == G_FILE_TYPE_REGULAR
)
787 make_file
= g_file_get_child (root_file
, *makefile
);
791 if (make_file
== NULL
)
793 g_set_error (error
, IANJUTA_PROJECT_ERROR
,
794 IANJUTA_PROJECT_ERROR_DOESNT_EXIST
,
795 _("Project doesn't exist or invalid path"));
801 group
= MKP_GROUP(mkp_group_new (root_file
));
802 anjuta_project_node_append (ANJUTA_PROJECT_NODE(project
), ANJUTA_PROJECT_NODE(group
));
803 g_hash_table_insert (project
->groups
, g_file_get_uri (root_file
), group
);
805 /* Parse make file */
806 project_load_makefile (project
, make_file
, group
, error
);
807 g_object_unref (make_file
);
809 monitors_setup (project
);
816 mkp_project_load (MkpProject
*project
,
820 g_return_val_if_fail (directory
!= NULL
, FALSE
);
822 return mkp_project_load_root (project
, ANJUTA_PROJECT_NODE(project
), error
) != NULL
;
826 mkp_project_unload (MkpProject
*project
)
828 AnjutaProjectNode
*node
;
830 monitors_remove (project
);
833 if (project
->root_file
) g_object_unref (project
->root_file
);
834 project
->root_file
= NULL
;
836 /* Remove all children */
837 while ((node
= anjuta_project_node_first_child (ANJUTA_PROJECT_NODE (project
))) != NULL
)
839 g_object_unref (node
);
842 /* shortcut hash tables */
843 if (project
->groups
) g_hash_table_destroy (project
->groups
);
844 project
->groups
= NULL
;
845 if (project
->files
) g_hash_table_destroy (project
->files
);
846 project
->files
= NULL
;
847 if (project
->variables
) g_hash_table_destroy (project
->variables
);
848 project
->variables
= NULL
;
850 mkp_project_free_rules (project
);
853 if (project
->space_list
) anjuta_token_style_free (project
->space_list
);
854 if (project
->arg_list
) anjuta_token_style_free (project
->arg_list
);
858 mkp_project_probe (GFile
*directory
,
864 dir
= (file_type (directory
, NULL
) == G_FILE_TYPE_DIRECTORY
);
867 g_set_error (error
, IANJUTA_PROJECT_ERROR
,
868 IANJUTA_PROJECT_ERROR_DOESNT_EXIST
,
869 _("Project doesn't exist or invalid path"));
875 const gchar
**makefile
;
877 /* Look for makefiles */
879 for (makefile
= valid_makefiles
; *makefile
!= NULL
; makefile
++)
881 if (file_type (directory
, *makefile
) == G_FILE_TYPE_REGULAR
)
889 return probe
? IANJUTA_PROJECT_PROBE_MAKE_FILES
: 0;
893 mkp_project_save (MkpProject
*project
, GError
**error
)
899 g_return_val_if_fail (project
!= NULL
, FALSE
);
901 g_hash_table_iter_init (&iter
, project
->files
);
902 while (g_hash_table_iter_next (&iter
, &key
, &value
))
904 GError
*error
= NULL
;
905 AnjutaTokenFile
*tfile
= (AnjutaTokenFile
*)value
;
906 anjuta_token_file_save (tfile
, &error
);
913 mkp_project_move (MkpProject
*project
, const gchar
*path
)
915 GFile
*old_root_file
;
921 AnjutaTokenFile
*tfile
;
922 GHashTable
* old_hash
;
924 /* Change project root directory */
925 old_root_file
= project
->root_file
;
926 project
->root_file
= g_file_new_for_path (path
);
928 /* Change project root directory in groups */
929 old_hash
= project
->groups
;
930 project
->groups
= g_hash_table_new_full (g_str_hash
, g_str_equal
, g_free
, NULL
);
931 g_hash_table_iter_init (&iter
, old_hash
);
932 while (g_hash_table_iter_next (&iter
, &key
, &value
))
934 MkpGroup
*group
= (MkpGroup
*)value
;
936 relative
= get_relative_path (old_root_file
, group
->base
.file
);
937 new_file
= g_file_resolve_relative_path (project
->root_file
, relative
);
939 g_object_unref (group
->base
.file
);
940 group
->base
.file
= new_file
;
942 g_hash_table_insert (project
->groups
, g_file_get_uri (new_file
), group
);
944 g_hash_table_destroy (old_hash
);
946 /* Change all files */
947 old_hash
= project
->files
;
948 project
->files
= g_hash_table_new_full (g_file_hash
, (GEqualFunc
)g_file_equal
, g_object_unref
, g_object_unref
);
949 g_hash_table_iter_init (&iter
, old_hash
);
950 while (g_hash_table_iter_next (&iter
, &key
, (gpointer
*)&tfile
))
952 relative
= get_relative_path (old_root_file
, anjuta_token_file_get_file (tfile
));
953 new_file
= g_file_resolve_relative_path (project
->root_file
, relative
);
955 anjuta_token_file_move (tfile
, new_file
);
957 g_hash_table_insert (project
->files
, new_file
, tfile
);
958 g_object_unref (key
);
960 g_hash_table_steal_all (old_hash
);
961 g_hash_table_destroy (old_hash
);
963 g_object_unref (old_root_file
);
969 mkp_project_new (GFile
*file
, GError
**error
)
973 project
= MKP_PROJECT (g_object_new (MKP_TYPE_PROJECT
, NULL
));
974 project
->parent
.file
= (file
!= NULL
) ? g_file_dup (file
) : NULL
;
975 project
->parent
.type
= ANJUTA_PROJECT_ROOT
;
981 mkp_project_is_loaded (MkpProject
*project
)
983 return project
->loading
== 0;
987 /* Implement IAnjutaProject
988 *---------------------------------------------------------------------------*/
991 iproject_load_node (IAnjutaProject
*obj
, AnjutaProjectNode
*node
, GError
**err
)
993 if (node
== NULL
) node
= ANJUTA_PROJECT_NODE (obj
);
996 if (mkp_project_load_node (MKP_PROJECT (obj
), node
, err
) != NULL
) {
997 (MKP_PROJECT(obj
))->loading
--;
998 g_signal_emit_by_name (MKP_PROJECT(obj
), "node-loaded", node
, err
);
1007 iproject_save_node (IAnjutaProject
*obj
, AnjutaProjectNode
*node
, GError
**err
)
1009 return mkp_project_save (MKP_PROJECT(node
), err
);
1012 static AnjutaProjectProperty
*
1013 iproject_set_property (IAnjutaProject
*obj
, AnjutaProjectNode
*node
, AnjutaProjectProperty
*property
, const gchar
*value
, GError
**error
)
1015 g_set_error (error
, IANJUTA_PROJECT_ERROR
,
1016 IANJUTA_PROJECT_ERROR_NOT_SUPPORTED
,
1017 _("Project doesn't allow to set properties"));
1023 iproject_remove_property (IAnjutaProject
*obj
, AnjutaProjectNode
*node
, AnjutaProjectProperty
*property
, GError
**error
)
1025 g_set_error (error
, IANJUTA_PROJECT_ERROR
,
1026 IANJUTA_PROJECT_ERROR_NOT_SUPPORTED
,
1027 _("Project doesn't allow to set properties"));
1033 iproject_get_node_info (IAnjutaProject
*obj
, GError
**err
)
1035 return mkp_project_get_node_info (MKP_PROJECT (obj
), err
);
1038 static AnjutaProjectNode
*
1039 iproject_get_root (IAnjutaProject
*obj
, GError
**err
)
1041 return ANJUTA_PROJECT_NODE(mkp_project_get_root (MKP_PROJECT(obj
)));
1045 iproject_is_loaded (IAnjutaProject
*obj
, GError
**err
)
1047 return mkp_project_is_loaded (MKP_PROJECT (obj
));
1051 iproject_remove_node (IAnjutaProject
*obj
, AnjutaProjectNode
*node
, GError
**err
)
1053 anjuta_project_node_set_state (node
, ANJUTA_PROJECT_REMOVED
);
1054 g_signal_emit_by_name (obj
, "node-modified", node
, NULL
);
1059 static AnjutaProjectNode
*
1060 iproject_add_node_before (IAnjutaProject
*obj
, AnjutaProjectNode
*parent
, AnjutaProjectNode
*sibling
, AnjutaProjectNodeType type
, GFile
*file
, const gchar
*name
, GError
**error
)
1062 AnjutaProjectNode
*node
;
1064 node
= project_node_new (MKP_PROJECT (obj
), parent
, type
, file
, name
, error
);
1065 anjuta_project_node_set_state (node
, ANJUTA_PROJECT_MODIFIED
);
1066 anjuta_project_node_insert_before (parent
, sibling
, node
);
1068 g_signal_emit_by_name (obj
, "node-changed", node
, NULL
);
1073 static AnjutaProjectNode
*
1074 iproject_add_node_after (IAnjutaProject
*obj
, AnjutaProjectNode
*parent
, AnjutaProjectNode
*sibling
, AnjutaProjectNodeType type
, GFile
*file
, const gchar
*name
, GError
**error
)
1076 AnjutaProjectNode
*node
;
1078 node
= project_node_new (MKP_PROJECT (obj
), parent
, type
, file
, name
, error
);
1079 anjuta_project_node_set_state (node
, ANJUTA_PROJECT_MODIFIED
);
1080 anjuta_project_node_insert_after (parent
, sibling
, node
);
1082 g_signal_emit_by_name (obj
, "node-modified", node
, NULL
);
1088 iproject_iface_init(IAnjutaProjectIface
* iface
)
1090 iface
->load_node
= iproject_load_node
;
1091 iface
->save_node
= iproject_save_node
;
1092 iface
->set_property
= iproject_set_property
;
1093 iface
->remove_property
= iproject_remove_property
;
1094 iface
->get_node_info
= iproject_get_node_info
;
1095 iface
->get_root
= iproject_get_root
;
1097 iface
->is_loaded
= iproject_is_loaded
;
1099 iface
->remove_node
= iproject_remove_node
;
1101 iface
->add_node_before
= iproject_add_node_before
;
1102 iface
->add_node_after
= iproject_add_node_after
;
1106 /* GObject implementation
1107 *---------------------------------------------------------------------------*/
1110 mkp_project_dispose (GObject
*object
)
1112 g_return_if_fail (MKP_IS_PROJECT (object
));
1114 mkp_project_unload (MKP_PROJECT (object
));
1116 G_OBJECT_CLASS (parent_class
)->dispose (object
);
1120 mkp_project_instance_init (MkpProject
*project
)
1122 g_return_if_fail (project
!= NULL
);
1123 g_return_if_fail (MKP_IS_PROJECT (project
));
1126 project
->root_file
= NULL
;
1127 project
->suffix
= NULL
;
1128 project
->rules
= NULL
;
1130 project
->space_list
= NULL
;
1131 project
->arg_list
= NULL
;
1135 mkp_project_class_init (MkpProjectClass
*klass
)
1137 GObjectClass
*object_class
;
1139 parent_class
= g_type_class_peek_parent (klass
);
1141 object_class
= G_OBJECT_CLASS (klass
);
1142 object_class
->dispose
= mkp_project_dispose
;
1146 ANJUTA_TYPE_BEGIN(MkpProject
, mkp_project
, ANJUTA_TYPE_PROJECT_NODE
);
1147 ANJUTA_TYPE_ADD_INTERFACE(iproject
, IANJUTA_TYPE_PROJECT
);