Fix a Gtk warning when checking path input in the log viewer.
[anjuta-git-plugin.git] / plugins / project-wizard / header.c
bloba7d36e391552fcd58dbe0cfb028df5ca04debe6b
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
3 header.c
4 Copyright (C) 2004 Sebastien Granjoux
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (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
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 * header data read in .wiz file, used in the first page (project selection)
24 *---------------------------------------------------------------------------*/
26 #include <config.h>
27 #include <sys/wait.h>
28 #include <unistd.h>
30 #include "header.h"
32 #include <glib/gdir.h>
33 #include <libanjuta/anjuta-utils.h>
35 /*---------------------------------------------------------------------------*/
37 #define STRING_CHUNK_SIZE 256
39 /*---------------------------------------------------------------------------*/
41 struct _NPWHeaderList
43 GNode* list;
44 GStringChunk* string_pool;
45 GMemChunk* data_pool;
48 struct _NPWHeader {
49 gchar* name;
50 gchar* description;
51 gchar* iconfile;
52 gchar* category;
53 gchar* filename;
54 GList* required_programs;
55 GList* required_packages;
56 NPWHeaderList* owner;
57 GNode* node;
60 /* Header
61 *---------------------------------------------------------------------------*/
63 NPWHeader*
64 npw_header_new (NPWHeaderList* owner)
66 NPWHeader* this;
68 g_return_val_if_fail (owner, NULL);
70 this = g_chunk_new0(NPWHeader, owner->data_pool);
71 this->owner = owner;
72 this->node = g_node_append_data (owner->list, this);
74 return this;
77 void
78 npw_header_free (NPWHeader* this)
80 GNode* node;
82 /* Memory allocated in string pool and project pool is not free */
83 node = g_node_find (this->owner->list, G_IN_ORDER, G_TRAVERSE_ALL, this);
84 if (node != NULL)
85 g_node_destroy (node);
86 if (this->required_programs)
87 g_list_free (this->required_programs);
88 if (this->required_packages)
89 g_list_free (this->required_packages);
92 void
93 npw_header_set_name (NPWHeader* this, const gchar* name)
95 this->name = g_string_chunk_insert (this->owner->string_pool, name);
98 const gchar*
99 npw_header_get_name (const NPWHeader* this)
101 return this->name;
104 void
105 npw_header_set_filename (NPWHeader* this, const gchar* filename)
107 this->filename = g_string_chunk_insert (this->owner->string_pool, filename);
110 const gchar*
111 npw_header_get_filename (const NPWHeader* this)
113 return this->filename;
116 void
117 npw_header_set_category (NPWHeader* this, const gchar* category)
119 npw_header_list_organize(this->owner, category, this);
120 this->category = ((NPWHeader *)this->node->parent->data)->category;
123 const gchar*
124 npw_header_get_category (const NPWHeader* this)
126 return this->category;
129 void
130 npw_header_set_description (NPWHeader* this, const gchar* description)
132 this->description = g_string_chunk_insert (this->owner->string_pool, description);
135 const gchar*
136 npw_header_get_description (const NPWHeader* this)
138 return this->description;
141 void
142 npw_header_set_iconfile (NPWHeader* this, const gchar* iconfile)
144 this->iconfile = g_string_chunk_insert (this->owner->string_pool, iconfile);
147 const gchar*
148 npw_header_get_iconfile (const NPWHeader* this)
150 return this->iconfile;
153 void
154 npw_header_add_required_program (NPWHeader* this, const gchar* program)
156 this->required_programs =
157 g_list_prepend (this->required_programs,
158 g_string_chunk_insert (this->owner->string_pool,
159 program));
163 void
164 npw_header_add_required_package (NPWHeader* this, const gchar* package)
166 this->required_packages =
167 g_list_prepend (this->required_packages,
168 g_string_chunk_insert (this->owner->string_pool,
169 package));
172 GList*
173 npw_header_check_required_programs (NPWHeader* this)
175 GList *node = NULL;
176 GList *failed_programs = NULL;
177 for (node = this->required_programs; node; node = g_list_next (node))
179 if (!anjuta_util_prog_is_installed (node->data, FALSE))
181 failed_programs = g_list_prepend (failed_programs, node->data);
184 return failed_programs;
187 static gboolean
188 package_is_installed (const gchar *package)
190 int status;
191 int exit_status;
192 pid_t pid;
193 if ((pid = fork()) == 0)
195 execlp ("pkg-config", "pkg-config", "--exists", package, NULL);
197 waitpid (pid, &status, 0);
198 exit_status = WEXITSTATUS (status);
199 return (exit_status == 0);
202 GList*
203 npw_header_check_required_packages (NPWHeader* this)
205 GList *node = NULL;
206 GList *failed_packages = NULL;
207 for (node = this->required_packages; node; node = g_list_next (node))
209 if (!package_is_installed (node->data))
211 failed_packages = g_list_prepend (failed_packages, node->data);
214 return failed_packages;
217 gboolean
218 npw_header_is_leaf(const NPWHeader* this)
220 return G_NODE_IS_LEAF(this->node);
224 /* Header list
225 *---------------------------------------------------------------------------*/
227 static GNode*
228 npw_header_list_find_parent(NPWHeaderList* this, const gchar* category, gboolean create)
230 GNode* node;
231 gint order;
233 for (node = g_node_first_child(this->list); node != NULL; node = g_node_next_sibling(node))
235 const char* s;
237 s = ((NPWHeader *)node->data)->category;
238 if (s != NULL)
240 order = g_ascii_strcasecmp (s, category);
241 if (order == 0)
243 /* Find right category */
244 break;
246 else if (order > 0)
248 if (create == TRUE)
250 /* Category doesn't exist create a new node */
251 NPWHeader* new_parent;
253 new_parent = npw_header_new (this);
254 new_parent->category = g_string_chunk_insert (this->string_pool, category);
255 g_node_unlink (new_parent->node);
256 g_node_insert_before (this->list, node, new_parent->node);
257 node = new_parent->node;
259 else
261 node = NULL;
263 break;
268 if (create && (node == NULL))
270 NPWHeader* new_parent;
272 new_parent = npw_header_new (this);
273 new_parent->category = g_string_chunk_insert (this->string_pool, category);
274 node = new_parent->node;
277 return node;
280 typedef struct _HeaderListForeachProjectData
282 NPWHeaderForeachFunc func;
283 gpointer data;
284 } HeaderListForeachProjectData;
286 static void
287 cb_header_list_foreach_project (GNode* node, gpointer data)
289 HeaderListForeachProjectData* d = (HeaderListForeachProjectData *)data;
291 (d->func)((NPWHeader*)node->data, d->data);
294 static gboolean
295 npw_header_list_foreach_node (GNode* list, NPWHeaderForeachFunc func, gpointer data, GTraverseFlags flag)
297 HeaderListForeachProjectData d;
299 if (g_node_first_child (list) == NULL) return FALSE;
301 d.func = func;
302 d.data = data;
304 g_node_children_foreach (list, flag, cb_header_list_foreach_project, &d);
306 return TRUE;
309 /*---------------------------------------------------------------------------*/
311 NPWHeaderList*
312 npw_header_list_new (void)
314 NPWHeaderList* this;
316 this = g_new (NPWHeaderList, 1);
317 this->string_pool = g_string_chunk_new (STRING_CHUNK_SIZE);
318 this->data_pool = g_mem_chunk_new ("project pool", sizeof (NPWHeader), STRING_CHUNK_SIZE * sizeof (NPWHeader) / 4, G_ALLOC_ONLY);
319 this->list = g_node_new (NULL);
321 return this;
324 void
325 npw_header_list_free (NPWHeaderList* this)
327 g_return_if_fail (this != NULL);
329 g_string_chunk_free (this->string_pool);
330 g_mem_chunk_destroy (this->data_pool);
331 g_node_destroy (this->list);
332 g_free (this);
335 void
336 npw_header_list_organize(NPWHeaderList* this, const gchar* category, NPWHeader* header)
338 GNode* parent;
339 GNode* node;
340 const gchar* name;
342 /* node without a category stay on top */
343 if ((category == NULL) || (*category == '\0')) return;
345 /* Detach the node */
346 g_node_unlink(header->node);
348 /* Find parent */
349 parent = npw_header_list_find_parent(this, category, TRUE);
351 /* Insert node as a child in alphabetic order*/
352 name = npw_header_get_name (header);
353 for (node = g_node_first_child(parent); node != NULL; node = g_node_next_sibling(node))
355 if (g_ascii_strcasecmp (npw_header_get_name ((NPWHeader *)node->data), name) > 0)
357 g_node_insert_before (parent, node, header->node);
358 return;
361 g_node_insert(parent, -1, header->node);
364 gboolean
365 npw_header_list_foreach_project (const NPWHeaderList* this, NPWHeaderForeachFunc func, gpointer data)
367 return npw_header_list_foreach_node (this->list, func, data, G_TRAVERSE_LEAFS);
370 gboolean
371 npw_header_list_foreach_project_in (const NPWHeaderList* this, const gchar* category, NPWHeaderForeachFunc func, gpointer data)
373 GNode* node;
375 /* FIXME: const modified has been removed because the find function
376 * with TRUE as the third argument could create a parent if it
377 * doesn't exist. It could be better to split this function in two */
378 node = npw_header_list_find_parent((NPWHeaderList*)this, category, FALSE);
379 if (node == NULL) return FALSE;
381 return npw_header_list_foreach_node (node, func, data, G_TRAVERSE_LEAFS);
384 gboolean
385 npw_header_list_foreach_category (const NPWHeaderList* this, NPWHeaderForeachFunc func, gpointer data)
387 return npw_header_list_foreach_node (this->list, func, data, G_TRAVERSE_NON_LEAFS);