always store full path in memory. Transform should happend only on project load
[geanyprj.git] / project.c
blobec68b8bfc6d335deb704ac18ba152b6b64c9a9e1
1 /*
2 * geanyprj.c - 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 2 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, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24 #include <sys/time.h>
26 #include "geany.h"
27 #include "support.h"
28 #include "prefs.h"
29 #include "plugindata.h"
30 #include "document.h"
31 #include "filetypes.h"
32 #include "utils.h"
33 #include "pluginmacros.h"
35 #include "project.h"
37 #include "geanyprj.h"
39 extern GeanyData *geany_data;
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 (geany_data->filetype->detect_from_filename(file)->id == GEANY_FILETYPES_C ||
53 geany_data->filetype->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 (geany_data->filetype->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 (geany_data->filetype->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 (geany_data->filetype->detect_from_filename(file)->id != GEANY_FILETYPES_ALL)
78 return TRUE;
79 return FALSE;
82 static gboolean
83 project_filter_none(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 GeanyProject *
105 geany_project_new(const gchar * path)
107 struct GeanyProject *ret;
108 TMWorkObject *tm_obj = NULL;
109 GKeyFile *config;
110 gint i = 0;
111 gchar *file;
112 gchar *filename, *locale_filename;
113 gchar *key;
114 GSList *lst;
116 debug("%s path=%s\n", __FUNCTION__, path);
118 if (!path)
119 return NULL;
121 config = g_key_file_new();
122 if (!g_key_file_load_from_file(config, path, G_KEY_FILE_NONE, NULL))
124 g_key_file_free(config);
125 return NULL;
129 ret = (struct GeanyProject *) g_new0(struct GeanyProject, 1);
130 ret->path = g_strdup(path);
132 ret->name = p_utils->get_setting_string(config, "project", "name", GEANY_STRING_UNTITLED);
133 ret->description = p_utils->get_setting_string(config, "project", "description", "");
134 ret->base_path = p_utils->get_setting_string(config, "project", "base_path", "");
135 setptr(ret->base_path, get_full_path(path, ret->base_path));
137 ret->run_cmd = p_utils->get_setting_string(config, "project", "run_cmd", "");
138 geany_project_set_type_string(ret,
139 p_utils->get_setting_string(config, "project", "type",
140 project_type_string[0]));
141 ret->regenerate = g_key_file_get_boolean(config, "project", "regenerate", NULL);
143 ret->tags = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, free_tag_object);
145 if (ret->regenerate)
147 lst = get_file_list(ret->base_path, NULL, project_type_filter[ret->type], NULL);
148 geany_project_set_tags_from_list(ret, lst);
150 g_slist_foreach(lst, (GFunc) g_free, NULL);
151 g_slist_free(lst);
153 else
155 // Create tag files
156 key = g_strdup_printf("file%d", i);
157 while ((file = g_key_file_get_string(config, "files", key, NULL)))
159 filename = get_full_path(path, file);
161 locale_filename = p_utils->get_locale_from_utf8(filename);
162 tm_obj = p_tm->source_file_new(locale_filename, FALSE,
163 geany_data->filetype->
164 detect_from_filename(filename)->name);
165 g_free(locale_filename);
166 if (tm_obj)
168 g_hash_table_insert(ret->tags, filename, tm_obj);
169 p_tm->source_file_update(tm_obj, TRUE, FALSE, TRUE);
171 else
172 g_free(filename);
173 i++;
174 g_free(key);
175 g_free(file);
176 key = g_strdup_printf("file%d", i);
178 g_free(key);
180 g_key_file_free(config);
181 return ret;
185 void
186 geany_project_set_path(struct GeanyProject *prj, const gchar * path)
188 gchar *norm_path = normpath(path);
189 if (prj->path)
191 if (strcmp(prj->path, norm_path) == 0)
193 g_free(norm_path);
194 return;
197 if (g_file_test(prj->path, G_FILE_TEST_IS_REGULAR))
199 unlink(prj->path);
201 g_free(prj->path);
203 prj->path = norm_path;
206 void
207 geany_project_set_name(struct GeanyProject *prj, const gchar * name)
209 if (prj->name)
210 g_free(prj->name);
211 prj->name = g_strdup(name);
213 if (prj == g_current_project)
215 if (project)
217 if (project->name)
218 g_free(project->name);
219 project->name = g_strdup(name);
224 void
225 geany_project_set_type_int(struct GeanyProject *prj, gint val)
227 prj->type = val;
230 void
231 geany_project_set_type_string(struct GeanyProject *prj, const gchar * val)
233 gint i;
235 for (i = 0; i < sizeof(project_type_string) / sizeof(project_type_string[0]); i++)
237 if (strcmp(val, project_type_string[i]) == 0)
238 return geany_project_set_type_int(prj, i);
242 void
243 geany_project_set_regenerate(struct GeanyProject *prj, gboolean val)
245 prj->regenerate = val;
248 void
249 geany_project_set_description(struct GeanyProject *prj, const gchar * description)
251 if (prj->description)
252 g_free(prj->description);
253 prj->description = g_strdup(description);
255 if (prj == g_current_project)
257 if (project)
259 if (project->description)
260 g_free(project->description);
261 project->description = g_strdup(description);
266 void
267 geany_project_set_base_path(struct GeanyProject *prj, const gchar * base_path)
269 if (prj->base_path)
270 g_free(prj->base_path);
271 prj->base_path = g_strdup(base_path);
273 if (prj == g_current_project)
275 if (project)
277 if (project->base_path)
278 g_free(project->base_path);
279 if (g_path_is_absolute(base_path))
281 project->base_path = get_relative_path(prj->path, base_path);
283 else
285 project->base_path = g_strdup(base_path);
291 void
292 geany_project_set_run_cmd(struct GeanyProject *prj, const gchar * run_cmd)
294 if (prj->run_cmd)
295 g_free(prj->run_cmd);
296 prj->run_cmd = g_strdup(run_cmd);
298 if (prj == g_current_project)
300 if (project)
302 if (project->run_cmd)
303 g_free(project->run_cmd);
304 project->run_cmd = g_strdup(run_cmd);
310 // list in utf8
311 void
312 geany_project_set_tags_from_list(struct GeanyProject *prj, GSList * files)
314 GSList *tmp;
315 gchar *locale_filename;
316 TMWorkObject *tm_obj = NULL;
318 if (prj->tags)
319 g_hash_table_destroy(prj->tags);
320 prj->tags = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, free_tag_object);
322 for (tmp = files; tmp != NULL; tmp = g_slist_next(tmp))
324 locale_filename = p_utils->get_locale_from_utf8(tmp->data);
325 tm_obj = p_tm->source_file_new(locale_filename, FALSE,
326 geany_data->filetype->
327 detect_from_filename(tmp->data)->name);
328 g_free(locale_filename);
329 if (tm_obj)
331 g_hash_table_insert(prj->tags, g_strdup(tmp->data), tm_obj);
332 p_tm->source_file_update(tm_obj, TRUE, FALSE, TRUE);
338 void
339 geany_project_free(struct GeanyProject *prj)
341 debug("%s prj=%p\n", __FUNCTION__, prj);
342 g_return_if_fail(prj);
344 if (prj->path)
345 g_free(prj->path);
346 if (prj->name)
347 g_free(prj->name);
348 if (prj->description)
349 g_free(prj->description);
350 if (prj->base_path)
351 g_free(prj->base_path);
352 if (prj->run_cmd)
353 g_free(prj->run_cmd);
354 if (prj->tags)
355 g_hash_table_destroy(prj->tags);
357 g_free(prj);
360 gboolean
361 geany_project_add_file(struct GeanyProject *prj, const gchar * path)
363 gboolean ret = FALSE;
364 gchar *filename;
365 gchar *base_dir;
366 gint i = 0;
367 TMWorkObject *tm_obj = NULL;
369 GKeyFile *config;
370 gchar *key;
372 config = g_key_file_new();
373 if (!g_key_file_load_from_file(config, prj->path, G_KEY_FILE_NONE, NULL))
375 g_key_file_free(config);
376 return FALSE;
379 if (g_hash_table_lookup(prj->tags, path))
381 g_key_file_free(config);
382 return TRUE;
385 filename = p_utils->get_locale_from_utf8(path);
386 tm_obj = p_tm->source_file_new(filename, FALSE,
387 geany_data->filetype->detect_from_filename(path)->name);
388 g_free(filename);
389 if (tm_obj)
391 g_hash_table_insert(prj->tags, g_strdup(path), tm_obj);
392 p_tm->source_file_update(tm_obj, TRUE, FALSE, TRUE);
394 geany_project_save(prj);
395 return TRUE;
398 struct CFGData
400 struct GeanyProject *prj;
401 GKeyFile *config;
402 int i;
405 static void
406 geany_project_save_files(gpointer key, gpointer value, gpointer user_data)
408 gchar *fkey;
409 gchar *filename;
410 struct CFGData *data = (struct CFGData *) user_data;
412 filename = get_relative_path(data->prj->path, (const gchar *) key);
413 if (filename)
415 fkey = g_strdup_printf("file%d", data->i);
416 g_key_file_set_string(data->config, "files", fkey, filename);
417 data->i++;
418 g_free(fkey);
419 g_free(filename);
423 gboolean
424 geany_project_remove_file(struct GeanyProject *prj, const gchar * path)
426 gboolean ret = FALSE;
427 gchar *filename;
428 gchar *base_dir;
429 gint i = 0;
431 if (!g_hash_table_remove(prj->tags, path))
433 return FALSE;
436 geany_project_save(prj);
437 return TRUE;
440 void
441 geany_project_save(struct GeanyProject *prj)
443 GKeyFile *config;
444 struct CFGData data;
445 gchar *base_path;
447 base_path = get_relative_path(prj->path, prj->base_path);
449 config = g_key_file_new();
450 g_key_file_load_from_file(config, prj->path, G_KEY_FILE_NONE, NULL);
452 g_key_file_set_string(config, "project", "name", prj->name);
453 g_key_file_set_string(config, "project", "description", prj->description);
454 g_key_file_set_string(config, "project", "base_path", base_path);
455 g_key_file_set_string(config, "project", "run_cmd", prj->run_cmd);
456 g_key_file_set_boolean(config, "project", "regenerate", prj->regenerate);
457 g_key_file_set_string(config, "project", "type", project_type_string[prj->type]);
459 data.prj = prj;
460 data.config = config;
461 data.i = 0;
463 g_key_file_remove_group(config, "files", NULL);
464 if (!prj->regenerate)
466 g_hash_table_foreach(prj->tags, geany_project_save_files, &data);
468 save_config(config, prj->path);
469 g_free(base_path);