TODO update
[geanyprj.git] / project.c
bloba92b3327870967613064c5d45b9e87c16472c74d
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;
40 const gchar *project_type_string[NEW_PROJECT_TYPE_SIZE] = {
41 "All",
42 "C/C++",
43 "C",
44 "Python",
45 "None"
48 static gboolean
49 project_filter_c_cpp(const gchar * file)
51 if (geany_data->filetype->detect_from_filename(file)->id == GEANY_FILETYPES_C ||
52 geany_data->filetype->detect_from_filename(file)->id == GEANY_FILETYPES_CPP)
53 return TRUE;
54 return FALSE;
57 static gboolean
58 project_filter_c(const gchar * file)
60 if (geany_data->filetype->detect_from_filename(file)->id == GEANY_FILETYPES_C)
61 return TRUE;
62 return FALSE;
65 static gboolean
66 project_filter_python(const gchar * file)
68 if (geany_data->filetype->detect_from_filename(file)->id == GEANY_FILETYPES_PYTHON)
69 return TRUE;
70 return FALSE;
73 static gboolean
74 project_filter_all(const gchar * file)
76 if (geany_data->filetype->detect_from_filename(file)->id != GEANY_FILETYPES_ALL)
77 return TRUE;
78 return FALSE;
81 static gboolean
82 project_filter_none(const gchar * file)
84 return FALSE;
88 void *project_type_filter[NEW_PROJECT_TYPE_SIZE] = {
89 project_filter_all,
90 project_filter_c_cpp,
91 project_filter_c,
92 project_filter_python,
93 project_filter_none
97 static void
98 free_tag_object(gpointer obj)
100 p_tm->workspace_remove_object((TMWorkObject *) obj, TRUE, FALSE);
103 struct GeanyProject *
104 geany_project_new(const gchar * path)
106 struct GeanyProject *ret;
107 TMWorkObject *tm_obj = NULL;
108 GKeyFile *config;
109 gint i = 0;
110 gchar *file;
111 gchar *filename, *locale_filename;
112 gchar *key;
113 GSList *lst;
115 debug("%s path=%s\n", __FUNCTION__, path);
117 if (!path)
118 return NULL;
120 config = g_key_file_new();
121 if (!g_key_file_load_from_file(config, path, G_KEY_FILE_NONE, NULL))
123 g_key_file_free(config);
124 return NULL;
128 ret = (struct GeanyProject *) g_new0(struct GeanyProject, 1);
129 ret->path = g_strdup(path);
131 ret->name = p_utils->get_setting_string(config, "project", "name", GEANY_STRING_UNTITLED);
132 ret->description = p_utils->get_setting_string(config, "project", "description", "");
133 ret->base_path = p_utils->get_setting_string(config, "project", "base_path", "");
134 setptr(ret->base_path, get_full_path(path, ret->base_path));
136 ret->run_cmd = p_utils->get_setting_string(config, "project", "run_cmd", "");
137 geany_project_set_type_string(ret,
138 p_utils->get_setting_string(config, "project", "type",
139 project_type_string[0]));
140 ret->regenerate = g_key_file_get_boolean(config, "project", "regenerate", NULL);
142 ret->tags = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, free_tag_object);
144 if (ret->regenerate)
146 geany_project_regenerate_file_list(ret);
148 else
150 // Create tag files
151 key = g_strdup_printf("file%d", i);
152 while ((file = g_key_file_get_string(config, "files", key, NULL)))
154 filename = get_full_path(path, file);
156 locale_filename = p_utils->get_locale_from_utf8(filename);
157 tm_obj = p_tm->source_file_new(locale_filename, FALSE,
158 geany_data->filetype->
159 detect_from_filename(filename)->name);
160 g_free(locale_filename);
161 if (tm_obj)
163 g_hash_table_insert(ret->tags, filename, tm_obj);
164 p_tm->source_file_update(tm_obj, TRUE, FALSE, TRUE);
166 else
167 g_free(filename);
168 i++;
169 g_free(key);
170 g_free(file);
171 key = g_strdup_printf("file%d", i);
173 g_free(key);
175 g_key_file_free(config);
176 return ret;
179 void
180 geany_project_regenerate_file_list(struct GeanyProject *prj)
182 GSList *lst;
184 g_hash_table_remove_all(prj->tags);
186 lst = get_file_list(prj->base_path, NULL, project_type_filter[prj->type], NULL);
187 geany_project_set_tags_from_list(prj, lst);
189 g_slist_foreach(lst, (GFunc) g_free, NULL);
190 g_slist_free(lst);
193 void
194 geany_project_set_path(struct GeanyProject *prj, const gchar * path)
196 gchar *norm_path = normpath(path);
197 if (prj->path)
199 if (strcmp(prj->path, norm_path) == 0)
201 g_free(norm_path);
202 return;
205 if (g_file_test(prj->path, G_FILE_TEST_IS_REGULAR))
207 unlink(prj->path);
209 g_free(prj->path);
211 prj->path = norm_path;
214 void
215 geany_project_set_name(struct GeanyProject *prj, const gchar * name)
217 if (prj->name)
218 g_free(prj->name);
219 prj->name = g_strdup(name);
221 if (prj == g_current_project)
223 if (project)
225 if (project->name)
226 g_free(project->name);
227 project->name = g_strdup(name);
232 void
233 geany_project_set_type_int(struct GeanyProject *prj, gint val)
235 prj->type = val;
238 void
239 geany_project_set_type_string(struct GeanyProject *prj, const gchar * val)
241 gint i;
243 for (i = 0; i < sizeof(project_type_string) / sizeof(project_type_string[0]); i++)
245 if (strcmp(val, project_type_string[i]) == 0)
246 return geany_project_set_type_int(prj, i);
250 void
251 geany_project_set_regenerate(struct GeanyProject *prj, gboolean val)
253 prj->regenerate = val;
256 void
257 geany_project_set_description(struct GeanyProject *prj, const gchar * description)
259 if (prj->description)
260 g_free(prj->description);
261 prj->description = g_strdup(description);
263 if (prj == g_current_project)
265 if (project)
267 if (project->description)
268 g_free(project->description);
269 project->description = g_strdup(description);
274 void
275 geany_project_set_base_path(struct GeanyProject *prj, const gchar * base_path)
277 if (prj->base_path)
278 g_free(prj->base_path);
279 prj->base_path = g_strdup(base_path);
281 if (prj == g_current_project)
283 if (project)
285 if (project->base_path)
286 g_free(project->base_path);
287 if (g_path_is_absolute(base_path))
289 project->base_path = get_relative_path(prj->path, base_path);
291 else
293 project->base_path = g_strdup(base_path);
299 void
300 geany_project_set_run_cmd(struct GeanyProject *prj, const gchar * run_cmd)
302 if (prj->run_cmd)
303 g_free(prj->run_cmd);
304 prj->run_cmd = g_strdup(run_cmd);
306 if (prj == g_current_project)
308 if (project)
310 if (project->run_cmd)
311 g_free(project->run_cmd);
312 project->run_cmd = g_strdup(run_cmd);
318 // list in utf8
319 void
320 geany_project_set_tags_from_list(struct GeanyProject *prj, GSList * files)
322 GSList *tmp;
323 gchar *locale_filename;
324 TMWorkObject *tm_obj = NULL;
326 if (prj->tags)
327 g_hash_table_destroy(prj->tags);
328 prj->tags = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, free_tag_object);
330 for (tmp = files; tmp != NULL; tmp = g_slist_next(tmp))
332 locale_filename = p_utils->get_locale_from_utf8(tmp->data);
333 tm_obj = p_tm->source_file_new(locale_filename, FALSE,
334 geany_data->filetype->
335 detect_from_filename(tmp->data)->name);
336 g_free(locale_filename);
337 if (tm_obj)
339 g_hash_table_insert(prj->tags, g_strdup(tmp->data), tm_obj);
340 p_tm->source_file_update(tm_obj, TRUE, FALSE, TRUE);
346 void
347 geany_project_free(struct GeanyProject *prj)
349 debug("%s prj=%p\n", __FUNCTION__, prj);
350 g_return_if_fail(prj);
352 if (prj->path)
353 g_free(prj->path);
354 if (prj->name)
355 g_free(prj->name);
356 if (prj->description)
357 g_free(prj->description);
358 if (prj->base_path)
359 g_free(prj->base_path);
360 if (prj->run_cmd)
361 g_free(prj->run_cmd);
362 if (prj->tags)
363 g_hash_table_destroy(prj->tags);
365 g_free(prj);
368 gboolean
369 geany_project_add_file(struct GeanyProject *prj, const gchar * path)
371 gboolean ret = FALSE;
372 gchar *filename;
373 gchar *base_dir;
374 gint i = 0;
375 TMWorkObject *tm_obj = NULL;
377 GKeyFile *config;
378 gchar *key;
380 config = g_key_file_new();
381 if (!g_key_file_load_from_file(config, prj->path, G_KEY_FILE_NONE, NULL))
383 g_key_file_free(config);
384 return FALSE;
387 if (g_hash_table_lookup(prj->tags, path))
389 g_key_file_free(config);
390 return TRUE;
393 filename = p_utils->get_locale_from_utf8(path);
394 tm_obj = p_tm->source_file_new(filename, FALSE,
395 geany_data->filetype->detect_from_filename(path)->name);
396 g_free(filename);
397 if (tm_obj)
399 g_hash_table_insert(prj->tags, g_strdup(path), tm_obj);
400 p_tm->source_file_update(tm_obj, TRUE, FALSE, TRUE);
402 geany_project_save(prj);
403 return TRUE;
406 struct CFGData
408 struct GeanyProject *prj;
409 GKeyFile *config;
410 int i;
413 static void
414 geany_project_save_files(gpointer key, gpointer value, gpointer user_data)
416 gchar *fkey;
417 gchar *filename;
418 struct CFGData *data = (struct CFGData *) user_data;
420 filename = get_relative_path(data->prj->path, (const gchar *) key);
421 if (filename)
423 fkey = g_strdup_printf("file%d", data->i);
424 g_key_file_set_string(data->config, "files", fkey, filename);
425 data->i++;
426 g_free(fkey);
427 g_free(filename);
431 gboolean
432 geany_project_remove_file(struct GeanyProject *prj, const gchar * path)
434 gboolean ret = FALSE;
435 gchar *filename;
436 gchar *base_dir;
437 gint i = 0;
439 if (!g_hash_table_remove(prj->tags, path))
441 return FALSE;
444 geany_project_save(prj);
445 return TRUE;
448 void
449 geany_project_save(struct GeanyProject *prj)
451 GKeyFile *config;
452 struct CFGData data;
453 gchar *base_path;
455 base_path = get_relative_path(prj->path, prj->base_path);
457 config = g_key_file_new();
458 g_key_file_load_from_file(config, prj->path, G_KEY_FILE_NONE, NULL);
460 g_key_file_set_string(config, "project", "name", prj->name);
461 g_key_file_set_string(config, "project", "description", prj->description);
462 g_key_file_set_string(config, "project", "base_path", base_path);
463 g_key_file_set_string(config, "project", "run_cmd", prj->run_cmd);
464 g_key_file_set_boolean(config, "project", "regenerate", prj->regenerate);
465 g_key_file_set_string(config, "project", "type", project_type_string[prj->type]);
467 data.prj = prj;
468 data.config = config;
469 data.i = 0;
471 g_key_file_remove_group(config, "files", NULL);
472 if (!prj->regenerate)
474 g_hash_table_foreach(prj->tags, geany_project_save_files, &data);
476 save_config(config, prj->path);
477 g_free(base_path);