am-project: Avoid a crash when adding a target to an invalid group
[anjuta.git] / plugins / am-project / amp-node.c
blob7fbcc5acdaa758d4435163c7e49fb3f215f27c01
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4; coding: utf-8 -*- */
2 /* amp-node.c
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.
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
27 #include "amp-node.h"
29 #include "am-properties.h"
31 #include "amp-root.h"
32 #include "amp-module.h"
33 #include "amp-package.h"
34 #include "amp-group.h"
35 #include "amp-target.h"
36 #include "amp-object.h"
37 #include "amp-source.h"
39 #include <libanjuta/anjuta-debug.h>
40 #include <libanjuta/interfaces/ianjuta-project.h>
42 #include <glib/gi18n.h>
44 #include <memory.h>
45 #include <string.h>
46 #include <ctype.h>
49 /* Helper functions
50 *---------------------------------------------------------------------------*/
52 void
53 amp_set_error (GError **error, gint code, const gchar *message)
55 if (error != NULL) {
56 if (*error != NULL) {
57 gchar *tmp;
59 /* error already created, just change the code
60 * and prepend the string */
61 (*error)->code = code;
62 tmp = (*error)->message;
63 (*error)->message = g_strconcat (message, "\n\n", tmp, NULL);
64 g_free (tmp);
66 } else {
67 *error = g_error_new_literal (IANJUTA_PROJECT_ERROR,
68 code,
69 message);
75 /* Public functions
76 *---------------------------------------------------------------------------*/
78 AnjutaProjectNode *
79 amp_node_new_valid(AnjutaProjectNode *parent, AnjutaProjectNodeType type, GFile *file, const gchar *name, GError **error)
81 AnjutaProjectNode *node = NULL;
82 AnjutaProjectNode *group = NULL;
83 GFile *new_file = NULL;
85 switch (type & ANJUTA_PROJECT_TYPE_MASK) {
86 case ANJUTA_PROJECT_GROUP:
87 if ((file == NULL) && (name != NULL))
89 if (g_path_is_absolute (name))
91 new_file = g_file_new_for_path (name);
93 else
95 new_file = g_file_get_child (anjuta_project_node_get_file (parent), name);
97 file = new_file;
99 node = ANJUTA_PROJECT_NODE (amp_group_node_new_valid (file, FALSE, error));
100 break;
101 case ANJUTA_PROJECT_TARGET:
102 node = ANJUTA_PROJECT_NODE (amp_target_node_new_valid (name, type, NULL, 0, parent, error));
103 break;
104 case ANJUTA_PROJECT_OBJECT:
105 node = ANJUTA_PROJECT_NODE (amp_object_node_new_valid (file, type, error));
106 break;
107 case ANJUTA_PROJECT_SOURCE:
108 /* Look for parent */
109 group = anjuta_project_node_parent_type (parent, ANJUTA_PROJECT_GROUP);
111 if ((file == NULL) && (name != NULL))
113 /* Find file from name */
114 if (anjuta_project_node_get_node_type (group) == ANJUTA_PROJECT_GROUP)
116 if (g_path_is_absolute (name))
118 new_file = g_file_new_for_path (name);
120 else
122 new_file = g_file_get_child (anjuta_project_node_get_file (group), name);
125 else
127 new_file = g_file_new_for_commandline_arg (name);
129 file = new_file;
132 /* Check that source file is inside the project if it is not belonging to a package */
133 if ((anjuta_project_node_get_node_type (group) == ANJUTA_PROJECT_GROUP) && (anjuta_project_node_get_node_type (parent) != ANJUTA_PROJECT_MODULE))
135 AnjutaProjectNode *root;
136 gchar *relative;
138 root = anjuta_project_node_root (group);
139 relative = g_file_get_relative_path (anjuta_project_node_get_file (root), file);
140 g_free (relative);
141 if (relative == NULL)
143 /* Source outside the project directory, so copy the file */
144 GFile *dest;
145 gchar *basename;
147 basename = g_file_get_basename (file);
148 dest = g_file_get_child (anjuta_project_node_get_file (group), basename);
149 g_free (basename);
151 g_file_copy_async (file, dest, G_FILE_COPY_BACKUP, G_PRIORITY_DEFAULT, NULL, NULL, NULL, NULL, NULL);
152 if (new_file != NULL) g_object_unref (new_file);
153 new_file = dest;
154 file = dest;
158 node = ANJUTA_PROJECT_NODE (amp_source_node_new_valid (file, type, error));
159 break;
160 case ANJUTA_PROJECT_MODULE:
161 node = ANJUTA_PROJECT_NODE (amp_module_node_new_valid (name, error));
162 break;
163 case ANJUTA_PROJECT_PACKAGE:
164 node = ANJUTA_PROJECT_NODE (amp_package_node_new_valid (name, error));
165 break;
166 default:
167 g_assert_not_reached ();
168 break;
170 if (node != NULL) node->type = type;
171 if (new_file != NULL) g_object_unref (new_file);
173 return node;
176 gboolean
177 amp_node_load (AmpNode *node,
178 AmpNode *parent,
179 AmpProject *project,
180 GError **error)
182 g_return_val_if_fail (AMP_IS_NODE (node), FALSE);
184 return AMP_NODE_GET_CLASS (node)->load (node, parent, project, error);
187 gboolean
188 amp_node_save (AmpNode *node,
189 AmpNode *parent,
190 AmpProject *project,
191 GError **error)
193 g_return_val_if_fail (AMP_IS_NODE (node), FALSE);
195 return AMP_NODE_GET_CLASS (node)->save (node, parent, project, error);
198 gboolean
199 amp_node_update (AmpNode *node,
200 AmpNode *new_node)
202 g_return_val_if_fail (AMP_IS_NODE (node), FALSE);
204 return AMP_NODE_GET_CLASS (node)->update (node, new_node);
207 gboolean
208 amp_node_write (AmpNode *node,
209 AmpNode *parent,
210 AmpProject *project,
211 GError **error)
213 g_return_val_if_fail (AMP_IS_NODE (node), FALSE);
215 return AMP_NODE_GET_CLASS (node)->write (node, parent, project, error);
218 gboolean
219 amp_node_erase (AmpNode *node,
220 AmpNode *parent,
221 AmpProject *project,
222 GError **error)
224 g_return_val_if_fail (AMP_IS_NODE (node), FALSE);
226 return AMP_NODE_GET_CLASS (node)->erase (node, parent, project, error);
229 /* AmpNode implementation
230 *---------------------------------------------------------------------------*/
232 static gboolean
233 amp_node_real_load (AmpNode *node,
234 AmpNode *parent,
235 AmpProject *project,
236 GError **error)
238 return FALSE;
241 static gboolean
242 amp_node_real_save (AmpNode *node,
243 AmpNode *parent,
244 AmpProject *project,
245 GError **error)
247 /* Save nothing by default */
248 return TRUE;
251 static gboolean
252 amp_node_real_update (AmpNode *node,
253 AmpNode *new_node)
255 return FALSE;
258 static gboolean
259 amp_node_real_write (AmpNode *node,
260 AmpNode *parent,
261 AmpProject *project,
262 GError **error)
264 return FALSE;
267 static gboolean
268 amp_node_real_erase (AmpNode *node,
269 AmpNode *parent,
270 AmpProject *project,
271 GError **error)
273 return FALSE;
277 /* GObjet implementation
278 *---------------------------------------------------------------------------*/
280 G_DEFINE_DYNAMIC_TYPE (AmpNode, amp_node, ANJUTA_TYPE_PROJECT_NODE);
282 static void
283 amp_node_init (AmpNode *node)
287 static void
288 amp_node_finalize (GObject *object)
290 AmpNode *node = AMP_NODE (object);
292 /* Subclasses set this directly and it should not be freed. */
293 node->parent.properties_info = NULL;
295 g_list_foreach (node->parent.properties, (GFunc)amp_property_free, NULL);
296 g_list_free (node->parent.properties);
297 node->parent.properties = NULL;
299 G_OBJECT_CLASS (amp_node_parent_class)->finalize (object);
302 static void
303 amp_node_class_init (AmpNodeClass *klass)
305 GObjectClass* object_class = G_OBJECT_CLASS (klass);
307 object_class->finalize = amp_node_finalize;
309 klass->load = amp_node_real_load;
310 klass->save = amp_node_real_save;
311 klass->update = amp_node_real_update;
312 klass->write = amp_node_real_write;
313 klass->erase = amp_node_real_erase;
316 static void
317 amp_node_class_finalize (AmpNodeClass *klass)
323 /* Register function
324 *---------------------------------------------------------------------------*/
326 void
327 amp_node_register (GTypeModule *module)
329 amp_node_register_type (module);
330 amp_group_node_register (module);
331 amp_root_node_register (module);
332 amp_module_node_register (module);
333 amp_package_node_register (module);
334 amp_target_node_register (module);
335 amp_object_node_register (module);
336 amp_source_node_register (module);