Initial German translation of the build tutorial
[anjuta.git] / plugins / project-manager / project.c
blobd2e3b627237a262b3374b2ff77dd767ebee814b4
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /* project.c
4 * Copyright (C) 2010 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., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
26 #include "project.h"
27 #include "project-marshal.h"
28 #include <libanjuta/anjuta-debug.h>
29 #include <libanjuta/interfaces/ianjuta-project-backend.h>
30 #include <libanjuta/interfaces/ianjuta-project-manager.h>
31 #include "project-model.h"
32 #include "project-view.h"
33 #include "dialogs.h"
36 /* Types
37 *---------------------------------------------------------------------------*/
39 /* Signal
40 *---------------------------------------------------------------------------*/
42 enum
44 LOADED,
45 LAST_SIGNAL
48 static unsigned int signals[LAST_SIGNAL] = { 0 };
50 static void
51 on_pm_project_load_incomplete (AnjutaProjectNode *node, AnjutaPmProject *project)
53 gint state = anjuta_project_node_get_state (node);
55 /* Get capabilities for all existing node */
56 project->node_capabilities |= state;
58 if ((state & ANJUTA_PROJECT_INCOMPLETE) && !(state & ANJUTA_PROJECT_LOADING))
60 //g_message ("incomplete node %s", anjuta_project_node_get_name (node));
61 project->incomplete_node++;
62 anjuta_project_node_set_state (node, ANJUTA_PROJECT_LOADING);
63 //g_message ("load incomplete %p", node);
64 ianjuta_project_load_node (project->project, node, NULL);
68 static gboolean
69 pm_command_load_complete (AnjutaPmProject *project, AnjutaProjectNode *node, GError *error)
71 gboolean complete = FALSE;
73 //g_message ("pm_command_load_complete %p", node);
74 if (error == NULL)
76 if (project->root == node)
78 project->incomplete_node = 0;
81 // Check for incompletely loaded object and load them
82 if (anjuta_project_node_get_state (node) & ANJUTA_PROJECT_INCOMPLETE)
84 project->incomplete_node--;
85 //g_message ("remaining node %d", project->incomplete_node);
87 anjuta_project_node_clear_state (node, ANJUTA_PROJECT_LOADING | ANJUTA_PROJECT_INCOMPLETE);
88 anjuta_project_node_foreach (node, G_POST_ORDER, (AnjutaProjectNodeForeachFunc)on_pm_project_load_incomplete, project);
90 complete = !project->loaded && (project->incomplete_node == 0);
91 if (complete) project->loaded = TRUE;
94 //g_message ("pm_command_load_complete %d is loaded %d", complete, ianjuta_project_is_loaded (project->project, NULL));
95 g_signal_emit (G_OBJECT (project), signals[LOADED], 0, node, complete, error);
98 return TRUE;
101 static void
102 on_file_changed (IAnjutaProject *sender, AnjutaProjectNode *node, AnjutaPmProject *project)
104 ianjuta_project_load_node (project->project, node, NULL);
107 static void
108 on_node_loaded (IAnjutaProject *sender, AnjutaProjectNode *node, GError *error, AnjutaPmProject *project)
110 pm_command_load_complete (project, node, error);
113 static void
114 on_node_changed (IAnjutaProject *sender, AnjutaProjectNode *node, GError *error, AnjutaPmProject *project)
116 ianjuta_project_save_node (project->project, node, NULL);
119 /* Public functions
120 *---------------------------------------------------------------------------*/
122 gboolean
123 anjuta_pm_project_load_with_backend (AnjutaPmProject *project, GFile *file, AnjutaPluginHandle *backend, GError **error)
125 AnjutaPluginManager *plugin_manager;
126 IAnjutaProjectBackend *plugin;
127 GValue value = {0, };
129 plugin_manager = anjuta_shell_get_plugin_manager (project->plugin->shell, NULL);
130 plugin = (IAnjutaProjectBackend *)anjuta_plugin_manager_get_plugin_by_handle (plugin_manager, backend);
133 DEBUG_PRINT ("%s", "Creating new gbf project\n");
134 project->project = ianjuta_project_backend_new_project (plugin, file, NULL);
135 if (!project->project)
137 /* FIXME: Set err */
138 g_warning ("project creation failed\n");
140 return FALSE;
142 project->backend =backend;
144 g_signal_connect (G_OBJECT (project->project),
145 "file-changed",
146 G_CALLBACK (on_file_changed),
147 project);
148 g_signal_connect (G_OBJECT (project->project),
149 "node-loaded",
150 G_CALLBACK (on_node_loaded),
151 project);
152 g_signal_connect (G_OBJECT (project->project),
153 "node-changed",
154 G_CALLBACK (on_node_changed),
155 project);
157 /* Export project root shell variable */
158 g_value_init (&value, G_TYPE_OBJECT);
159 g_value_set_object (&value, project->project);
160 anjuta_shell_add_value (project->plugin->shell,
161 IANJUTA_PROJECT_MANAGER_CURRENT_PROJECT,
162 &value, NULL);
163 g_value_unset(&value);
164 g_value_init (&value, G_TYPE_STRING);
165 g_value_set_string (&value, ANJUTA_PLUGIN_PROJECT_MANAGER (project->plugin)->project_root_uri);
166 anjuta_shell_add_value (project->plugin->shell,
167 IANJUTA_PROJECT_MANAGER_PROJECT_ROOT_URI,
168 &value, NULL);
169 g_value_unset(&value);
171 project->root = ianjuta_project_get_root (project->project, NULL);
172 ianjuta_project_load_node (project->project, project->root, NULL);
174 return TRUE;
178 gboolean
179 anjuta_pm_project_load (AnjutaPmProject *project, GFile *file, GError **error)
181 AnjutaPluginManager *plugin_manager;
182 GList *desc;
183 IAnjutaProjectBackend *backend;
184 AnjutaPluginHandle *backend_handle;
185 gint found = 0;
187 g_return_val_if_fail (file != NULL, FALSE);
189 DEBUG_PRINT ("loading gbf backend…\n");
190 plugin_manager = anjuta_shell_get_plugin_manager (project->plugin->shell, NULL);
192 if (!anjuta_plugin_manager_is_active_plugin (plugin_manager, "IAnjutaProjectBackend"))
194 GList *handles = NULL;
196 handles = anjuta_plugin_manager_query (plugin_manager,
197 "Anjuta Plugin",
198 "Interfaces",
199 "IAnjutaProjectBackend",
200 NULL);
201 backend = NULL;
202 for (desc = g_list_first (handles); desc != NULL; desc = g_list_next (desc)) {
203 IAnjutaProjectBackend *plugin;
204 gint backend_val;
206 backend_handle = (AnjutaPluginHandle *)desc->data;
207 plugin = (IAnjutaProjectBackend *)anjuta_plugin_manager_get_plugin_by_handle (plugin_manager, backend_handle);
209 backend_val = ianjuta_project_backend_probe (plugin, file, NULL);
210 if (backend_val > found)
212 /* Backend found */;
213 backend = plugin;
214 found = backend_val;
217 g_list_free (handles);
219 else
221 /* A backend is already loaded, use it */
222 backend = IANJUTA_PROJECT_BACKEND (anjuta_shell_get_object (project->plugin->shell,
223 "IAnjutaProjectBackend", NULL));
225 g_object_ref (backend);
228 if (!backend)
230 /* FIXME: Set err */
231 g_warning ("no backend available for this project\n");
233 return FALSE;
236 backend_handle = anjuta_plugin_manager_get_plugin_handle (plugin_manager, G_OBJECT(backend));
238 return anjuta_pm_project_load_with_backend (project, file, backend_handle, error);
241 gboolean
242 anjuta_pm_project_unload (AnjutaPmProject *project, GError **error)
244 /* Remove value from Anjuta shell */
245 anjuta_shell_remove_value (project->plugin->shell,
246 IANJUTA_PROJECT_MANAGER_CURRENT_PROJECT,
247 NULL);
249 if (project->project) g_object_unref (project->project);
250 project->project = NULL;
251 project->backend = NULL;
252 project->root = NULL;
253 project->loaded = FALSE;
254 project->node_capabilities = 0;
256 /* Remove project properties dialogs */
257 if (project->properties_dialog != NULL) gtk_widget_destroy (project->properties_dialog);
258 project->properties_dialog = NULL;
260 return TRUE;
263 gboolean
264 anjuta_pm_project_refresh (AnjutaPmProject *project, GError **error)
266 return ianjuta_project_load_node (project->project, project->root, error);
269 gint
270 anjuta_pm_project_get_capabilities (AnjutaPmProject *project)
272 gint caps = 0;
274 if (project->project != NULL)
276 const GList *item;
278 for (item = anjuta_pm_project_get_node_info (project); item != NULL; item = g_list_next (item))
280 AnjutaProjectNodeInfo *info = (AnjutaProjectNodeInfo *)item->data;
282 switch (info->type & ANJUTA_PROJECT_TYPE_MASK)
284 case ANJUTA_PROJECT_GROUP:
285 caps |= ANJUTA_PROJECT_CAN_ADD_GROUP;
286 break;
287 case ANJUTA_PROJECT_TARGET:
288 caps |= ANJUTA_PROJECT_CAN_ADD_TARGET;
289 break;
290 case ANJUTA_PROJECT_SOURCE:
291 caps |= ANJUTA_PROJECT_CAN_ADD_SOURCE;
292 break;
293 case ANJUTA_PROJECT_MODULE:
294 caps |= ANJUTA_PROJECT_CAN_ADD_MODULE;
295 break;
296 case ANJUTA_PROJECT_PACKAGE:
297 caps |= ANJUTA_PROJECT_CAN_ADD_PACKAGE;
298 break;
299 default:
300 break;
305 /* Make sure that at least one node can do it */
306 caps &= project->node_capabilities;
308 return caps;
311 const GList *
312 anjuta_pm_project_get_node_info (AnjutaPmProject *project)
314 g_return_val_if_fail (project->project != NULL, NULL);
316 return ianjuta_project_get_node_info (project->project, NULL);
319 AnjutaProjectNode *
320 anjuta_pm_project_get_root (AnjutaPmProject *project)
322 return project->root;
325 GList *
326 anjuta_pm_project_get_packages (AnjutaPmProject *project)
328 AnjutaProjectNode *module;
329 GHashTable *all;
330 GList *packages;
332 g_return_val_if_fail (project != NULL, NULL);
334 all = g_hash_table_new (g_str_hash, g_str_equal);
336 for (module = anjuta_project_node_first_child (project->root); module != NULL; module = anjuta_project_node_next_sibling (module))
338 if (anjuta_project_node_get_node_type(module) == ANJUTA_PROJECT_MODULE)
340 AnjutaProjectNode *package;
342 for (package = anjuta_project_node_first_child (module); package != NULL; package = anjuta_project_node_next_sibling (package))
344 if (anjuta_project_node_get_node_type (package) == ANJUTA_PROJECT_PACKAGE)
346 g_hash_table_replace (all, (gpointer)anjuta_project_node_get_name (package), NULL);
352 packages = g_hash_table_get_keys (all);
353 g_hash_table_destroy (all);
355 return packages;
358 AnjutaProjectNode *
359 anjuta_pm_project_add_group (AnjutaPmProject *project, AnjutaProjectNode *parent, AnjutaProjectNode *sibling, const gchar *name, GError **error)
361 AnjutaProjectNode *node;
363 g_return_val_if_fail (project->project != NULL, NULL);
365 node = ianjuta_project_add_node_before (project->project, parent, sibling, ANJUTA_PROJECT_GROUP, NULL, name, error);
367 return node;
370 AnjutaProjectNode *
371 anjuta_pm_project_add_target (AnjutaPmProject *project, AnjutaProjectNode *parent, AnjutaProjectNode *sibling, const gchar *name, AnjutaProjectNodeType type, GError **error)
373 AnjutaProjectNode *node;
375 g_return_val_if_fail (project->project != NULL, NULL);
377 node = ianjuta_project_add_node_before (project->project, parent, sibling, ANJUTA_PROJECT_TARGET | type, NULL, name, error);
379 return node;
382 AnjutaProjectNode *
383 anjuta_pm_project_add_source (AnjutaPmProject *project, AnjutaProjectNode *parent, AnjutaProjectNode *sibling, const gchar *name, GError **error)
385 AnjutaProjectNode *node;
386 gchar *scheme;
387 GFile *file = NULL;
389 g_return_val_if_fail (project->project != NULL, NULL);
391 scheme = g_uri_parse_scheme (name);
392 if (scheme != NULL)
394 g_free (scheme);
395 file = g_file_new_for_uri (name);
398 node = ianjuta_project_add_node_before (project->project, parent, sibling, ANJUTA_PROJECT_SOURCE, file, file == NULL ? name : NULL, error);
400 return node;
403 gboolean
404 anjuta_pm_project_remove (AnjutaPmProject *project, AnjutaProjectNode *node, GError **error)
406 return ianjuta_project_remove_node (project->project, node, error);
409 gboolean
410 anjuta_pm_project_is_open (AnjutaPmProject *project)
412 return (project->project != NULL) && (project->root != NULL);
415 AnjutaPluginHandle *
416 anjuta_pm_project_get_backend (AnjutaPmProject *project)
418 return project->backend;
421 IAnjutaProject *
422 anjuta_pm_project_get_project (AnjutaPmProject *project)
424 return project->project;
427 static gboolean
428 find_module (AnjutaProjectNode *node, gpointer data)
430 gboolean found = FALSE;
432 if (anjuta_project_node_get_node_type (node) == ANJUTA_PROJECT_MODULE)
434 const gchar *name = anjuta_project_node_get_name (node);
436 found = g_strcmp0 (name, (const gchar *)data) == 0;
439 return found;
442 AnjutaProjectNode *
443 anjuta_pm_project_get_module (AnjutaPmProject *project, const gchar *name)
445 AnjutaProjectNode *root;
446 AnjutaProjectNode *module;
448 root = ianjuta_project_get_root (project->project, NULL);
450 module = anjuta_project_node_children_traverse (root, find_module, (gpointer)name);
452 return module;
455 /* Implement GObject
456 *---------------------------------------------------------------------------*/
458 G_DEFINE_TYPE (AnjutaPmProject, anjuta_pm_project, G_TYPE_OBJECT);
460 static void
461 anjuta_pm_project_init (AnjutaPmProject *project)
463 project->plugin = NULL;
464 project->loaded = FALSE;
466 project->properties_dialog = NULL;
469 static void
470 anjuta_pm_project_finalize (GObject *object)
472 G_OBJECT_CLASS (anjuta_pm_project_parent_class)->finalize (object);
475 static void
476 anjuta_pm_project_class_init (AnjutaPmProjectClass *klass)
478 GObjectClass* object_class = G_OBJECT_CLASS (klass);
480 object_class->finalize = anjuta_pm_project_finalize;
483 /*Change both signal to use marshal_VOID__POINTER_BOXED
484 adding a AnjutaProjectNode pointer corresponding to the
485 loaded node => done
486 Such marshal doesn't exist as glib marshal, so look in the
487 symbol db plugin how to add new marshal => done
488 ToDo :
489 This new argument can be used in the plugin object in
490 order to add corresponding shortcut when the project
491 is loaded and a new node is loaded.
492 The plugin should probably get the GFile from the
493 AnjutaProjectNode object and then use a function
494 in project-view.c to create the corresponding shortcut*/
496 signals[LOADED] = g_signal_new ("loaded",
497 G_OBJECT_CLASS_TYPE (object_class),
498 G_SIGNAL_RUN_LAST,
499 G_STRUCT_OFFSET (AnjutaPmProjectClass, loaded),
500 NULL, NULL,
501 pm_cclosure_marshal_VOID__POINTER_BOOLEAN_BOXED,
502 G_TYPE_NONE,
504 G_TYPE_POINTER,
505 G_TYPE_BOOLEAN,
506 G_TYPE_ERROR);
509 /* Constructor & Destructor
510 *---------------------------------------------------------------------------*/
512 AnjutaPmProject*
513 anjuta_pm_project_new (AnjutaPlugin *plugin)
515 AnjutaPmProject *project;
517 project = g_object_new (ANJUTA_TYPE_PM_PROJECT, NULL);
518 project->plugin = plugin;
520 return project;
523 void
524 anjuta_pm_project_free (AnjutaPmProject* project)
526 g_object_unref (project);