Compilation fix
[geanyprj.git] / src / project.c
blobda417d22a8c5540a9e21e9070090b310d7ba20d5
1 /*
2 * geanyprj - Alternative project support for geany light IDE.
4 * Copyright 2007 Frank Lanitz <frank(at)frank(dot)uvena(dot)de>
5 * Copyright 2007 Enrico Tröger <enrico.troeger@uvena.de>
6 * Copyright 2007 Nick Treleaven <nick.treleaven@btinternet.com>
7 * Copyright 2007,2008 Yura Siamashka <yurand2@gmail.com>
9 * This program is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include <sys/time.h>
25 #include "geany.h"
26 #include "support.h"
27 #include "prefs.h"
28 #include "plugindata.h"
29 #include "document.h"
30 #include "filetypes.h"
31 #include "utils.h"
32 #include "pluginmacros.h"
34 #include "project.h"
36 #include "geanyprj.h"
38 extern GeanyData *geany_data;
39 extern GeanyFunctions *geany_functions;
41 const gchar *project_type_string[NEW_PROJECT_TYPE_SIZE] = {
42 "All",
43 "C/C++",
44 "C",
45 "Python",
46 "None"
49 static gboolean
50 project_filter_c_cpp(const gchar * file)
52 if (p_filetypes->detect_from_filename(file)->id == GEANY_FILETYPES_C ||
53 p_filetypes->detect_from_filename(file)->id == GEANY_FILETYPES_CPP)
54 return TRUE;
55 return FALSE;
58 static gboolean
59 project_filter_c(const gchar * file)
61 if (p_filetypes->detect_from_filename(file)->id == GEANY_FILETYPES_C)
62 return TRUE;
63 return FALSE;
66 static gboolean
67 project_filter_python(const gchar * file)
69 if (p_filetypes->detect_from_filename(file)->id == GEANY_FILETYPES_PYTHON)
70 return TRUE;
71 return FALSE;
74 static gboolean
75 project_filter_all(const gchar * file)
77 if (p_filetypes->detect_from_filename(file)->id != GEANY_FILETYPES_ALL)
78 return TRUE;
79 return FALSE;
82 static gboolean
83 project_filter_none(G_GNUC_UNUSED const gchar * file)
85 return FALSE;
89 void *project_type_filter[NEW_PROJECT_TYPE_SIZE] = {
90 project_filter_all,
91 project_filter_c_cpp,
92 project_filter_c,
93 project_filter_python,
94 project_filter_none
98 static void
99 free_tag_object(gpointer obj)
101 p_tm->workspace_remove_object((TMWorkObject *) obj, TRUE, FALSE);
104 struct PluginProject *
105 geany_project_new()
107 struct PluginProject *ret;
109 ret = (struct PluginProject *) g_new0(struct PluginProject, 1);
110 ret->tags = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, free_tag_object);
112 return ret;
115 struct PluginProject *
116 geany_project_load(const gchar * path)
118 struct PluginProject *ret;
119 TMWorkObject *tm_obj = NULL;
120 GKeyFile *config;
121 gint i = 0;
122 gchar *file;
123 gchar *filename, *locale_filename;
124 gchar *key;
125 gchar *tmp;
127 debug("%s path=%s\n", __FUNCTION__, path);
129 if (!path)
130 return NULL;
132 config = g_key_file_new();
133 if (!g_key_file_load_from_file(config, path, G_KEY_FILE_NONE, NULL))
135 g_key_file_free(config);
136 return NULL;
140 ret = geany_project_new();
141 geany_project_set_path(ret, path);
143 tmp = p_utils->get_setting_string(config, "project", "name", GEANY_STRING_UNTITLED);
144 geany_project_set_name(ret, tmp);
145 g_free(tmp);
147 tmp = p_utils->get_setting_string(config, "project", "description", "");
148 geany_project_set_description(ret, tmp);
149 g_free(tmp);
151 tmp = p_utils->get_setting_string(config, "project", "base_path", "");
152 geany_project_set_base_path(ret, tmp);
153 g_free(tmp);
155 tmp = p_utils->get_setting_string(config, "project", "run_cmd", "");
156 geany_project_set_run_cmd(ret, tmp);
157 g_free(tmp);
159 geany_project_set_type_string(ret,
160 p_utils->get_setting_string(config, "project", "type",
161 project_type_string[0]));
162 geany_project_set_regenerate(ret,
163 g_key_file_get_boolean(config, "project", "regenerate", NULL));
165 if (ret->regenerate)
167 geany_project_regenerate_file_list(ret);
169 else
171 // Create tag files
172 key = g_strdup_printf("file%d", i);
173 while ((file = g_key_file_get_string(config, "files", key, NULL)))
175 filename = get_full_path(path, file);
177 locale_filename = p_utils->get_locale_from_utf8(filename);
178 tm_obj = p_tm->source_file_new(locale_filename, FALSE,
179 p_filetypes->
180 detect_from_filename(filename)->name);
181 g_free(locale_filename);
182 if (tm_obj)
184 g_hash_table_insert(ret->tags, filename, tm_obj);
185 p_tm->source_file_update(tm_obj, TRUE, FALSE, TRUE);
187 else
188 g_free(filename);
189 i++;
190 g_free(key);
191 g_free(file);
192 key = g_strdup_printf("file%d", i);
194 g_free(key);
196 g_key_file_free(config);
197 return ret;
200 void
201 geany_project_regenerate_file_list(struct PluginProject *prj)
203 GSList *lst;
205 debug("%s path=%s\n", __FUNCTION__, prj->base_path);
206 g_hash_table_remove_all(prj->tags);
208 lst = get_file_list(prj->base_path, NULL, project_type_filter[prj->type], NULL);
209 geany_project_set_tags_from_list(prj, lst);
211 g_slist_foreach(lst, (GFunc) g_free, NULL);
212 g_slist_free(lst);
215 void
216 geany_project_set_path(struct PluginProject *prj, const gchar * path)
218 gchar *norm_path = normpath(path);
219 if (prj->path)
221 if (strcmp(prj->path, norm_path) == 0)
223 g_free(norm_path);
224 return;
227 prj->path = norm_path;
230 void
231 geany_project_set_name(struct PluginProject *prj, const gchar * name)
233 if (prj->name)
234 g_free(prj->name);
235 prj->name = g_strdup(name);
237 if (prj == g_current_project)
239 if (project)
241 if (project->name)
242 g_free(project->name);
243 project->name = g_strdup(name);
248 void
249 geany_project_set_type_int(struct PluginProject *prj, gint val)
251 prj->type = val;
254 void
255 geany_project_set_type_string(struct PluginProject *prj, const gchar * val)
257 guint i;
259 for (i = 0; i < sizeof(project_type_string) / sizeof(project_type_string[0]); i++)
261 if (strcmp(val, project_type_string[i]) == 0)
262 return geany_project_set_type_int(prj, i);
266 void
267 geany_project_set_regenerate(struct PluginProject *prj, gboolean val)
269 prj->regenerate = val;
272 void
273 geany_project_set_description(struct PluginProject *prj, const gchar * description)
275 if (prj->description)
276 g_free(prj->description);
277 prj->description = g_strdup(description);
279 if (prj == g_current_project)
281 if (project)
283 if (project->description)
284 g_free(project->description);
285 project->description = g_strdup(description);
290 void
291 geany_project_set_base_path(struct PluginProject *prj, const gchar * base_path)
293 if (prj->base_path)
294 g_free(prj->base_path);
296 if (g_path_is_absolute(base_path))
298 prj->base_path = g_strdup(base_path);
300 else
302 prj->base_path = get_full_path(prj->path, base_path);
305 if (prj == g_current_project)
307 if (project)
309 if (project->base_path)
310 g_free(project->base_path);
311 project->base_path = g_strdup(base_path);
316 void
317 geany_project_set_run_cmd(struct PluginProject *prj, const gchar * run_cmd)
319 if (prj->run_cmd)
320 g_free(prj->run_cmd);
321 prj->run_cmd = g_strdup(run_cmd);
323 if (prj == g_current_project)
325 if (project)
327 if (project->run_cmd)
328 g_free(project->run_cmd);
329 project->run_cmd = g_strdup(run_cmd);
335 // list in utf8
336 void
337 geany_project_set_tags_from_list(struct PluginProject *prj, GSList * files)
339 GSList *tmp;
340 gchar *locale_filename;
341 TMWorkObject *tm_obj = NULL;
343 if (prj->tags)
344 g_hash_table_destroy(prj->tags);
345 prj->tags = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, free_tag_object);
347 for (tmp = files; tmp != NULL; tmp = g_slist_next(tmp))
349 locale_filename = p_utils->get_locale_from_utf8(tmp->data);
350 tm_obj = p_tm->source_file_new(locale_filename, FALSE,
351 p_filetypes->detect_from_filename(tmp->data)->name);
352 g_free(locale_filename);
353 if (tm_obj)
355 g_hash_table_insert(prj->tags, g_strdup(tmp->data), tm_obj);
356 p_tm->source_file_update(tm_obj, TRUE, FALSE, TRUE);
362 void
363 geany_project_free(struct PluginProject *prj)
365 debug("%s prj=%p\n", __FUNCTION__, prj);
366 g_return_if_fail(prj);
368 if (prj->path)
369 g_free(prj->path);
370 if (prj->name)
371 g_free(prj->name);
372 if (prj->description)
373 g_free(prj->description);
374 if (prj->base_path)
375 g_free(prj->base_path);
376 if (prj->run_cmd)
377 g_free(prj->run_cmd);
378 if (prj->tags)
379 g_hash_table_destroy(prj->tags);
381 g_free(prj);
384 gboolean
385 geany_project_add_file(struct PluginProject *prj, const gchar * path)
387 gchar *filename;
388 TMWorkObject *tm_obj = NULL;
390 GKeyFile *config;
392 config = g_key_file_new();
393 if (!g_key_file_load_from_file(config, prj->path, G_KEY_FILE_NONE, NULL))
395 g_key_file_free(config);
396 return FALSE;
399 if (g_hash_table_lookup(prj->tags, path))
401 g_key_file_free(config);
402 return TRUE;
405 filename = p_utils->get_locale_from_utf8(path);
406 tm_obj = p_tm->source_file_new(filename, FALSE,
407 p_filetypes->detect_from_filename(path)->name);
408 g_free(filename);
409 if (tm_obj)
411 g_hash_table_insert(prj->tags, g_strdup(path), tm_obj);
412 p_tm->source_file_update(tm_obj, TRUE, FALSE, TRUE);
414 geany_project_save(prj);
415 return TRUE;
418 struct CFGData
420 struct PluginProject *prj;
421 GKeyFile *config;
422 int i;
425 static void
426 geany_project_save_files(gpointer key, G_GNUC_UNUSED gpointer value, gpointer user_data)
428 gchar *fkey;
429 gchar *filename;
430 struct CFGData *data = (struct CFGData *) user_data;
432 filename = get_relative_path(data->prj->path, (const gchar *) key);
433 if (filename)
435 fkey = g_strdup_printf("file%d", data->i);
436 g_key_file_set_string(data->config, "files", fkey, filename);
437 data->i++;
438 g_free(fkey);
439 g_free(filename);
443 gboolean
444 geany_project_remove_file(struct PluginProject *prj, const gchar * path)
446 if (!g_hash_table_remove(prj->tags, path))
448 return FALSE;
451 geany_project_save(prj);
452 return TRUE;
455 void
456 geany_project_save(struct PluginProject *prj)
458 GKeyFile *config;
459 struct CFGData data;
460 gchar *base_path;
462 base_path = get_relative_path(prj->path, prj->base_path);
464 config = g_key_file_new();
465 g_key_file_load_from_file(config, prj->path, G_KEY_FILE_NONE, NULL);
467 g_key_file_set_string(config, "project", "name", prj->name);
468 g_key_file_set_string(config, "project", "description", prj->description);
469 g_key_file_set_string(config, "project", "base_path", base_path);
470 g_key_file_set_string(config, "project", "run_cmd", prj->run_cmd);
471 g_key_file_set_boolean(config, "project", "regenerate", prj->regenerate);
472 g_key_file_set_string(config, "project", "type", project_type_string[prj->type]);
474 data.prj = prj;
475 data.config = config;
476 data.i = 0;
478 g_key_file_remove_group(config, "files", NULL);
479 if (!prj->regenerate)
481 g_hash_table_foreach(prj->tags, geany_project_save_files, &data);
483 save_config(config, prj->path);
484 g_free(base_path);