Create a to-do list with tentative dates for each milestone.
[anjuta-git-plugin.git] / libanjuta / anjuta-profile.c
blobb66e7bdf4b392f38334d62d36e996b5ea17c683e
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
3 * anjuta-profile.c
4 * Copyright (C) Naba Kumar <naba@gnome.org>
5 *
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
21 /**
22 * SECTION:anjuta-profile
23 * @short_description: Profile is a collection of plugins
24 * @see_also: #AnjutaProfileManager, #AnjutaPlugin
25 * @stability: Unstable
26 * @include: libanjuta/anjuta-profile.h
30 #include <glib/gi18n.h>
31 #include <glib/gerror.h>
32 #include <string.h>
33 #include <libxml/parser.h>
34 #include <libxml/tree.h>
35 #include <libgnomevfs/gnome-vfs.h>
37 #include "anjuta-profile.h"
38 #include "anjuta-marshal.h"
39 #include "anjuta-debug.h"
41 enum
43 PROP_0,
44 PROP_PLUGIN_MANAGER,
45 PROP_PROFILE_NAME,
46 PROP_PROFILE_PLUGINS,
47 PROP_SYNC_URI,
50 enum
52 PLUGIN_ADDED,
53 PLUGIN_REMOVED,
54 CHANGED,
55 LAST_SIGNAL
58 struct _AnjutaProfilePriv
60 gchar *name;
61 AnjutaPluginManager *plugin_manager;
62 GList *plugins;
63 GHashTable *plugins_hash;
64 GHashTable *plugins_to_exclude_from_sync;
65 gchar *sync_uri;
68 static GObjectClass* parent_class = NULL;
69 static guint profile_signals[LAST_SIGNAL] = { 0 };
71 GQuark
72 anjuta_profile_error_quark (void)
74 static GQuark quark = 0;
76 if (quark == 0) {
77 quark = g_quark_from_static_string ("anjuta-profile-quark");
80 return quark;
83 static void
84 anjuta_profile_init (AnjutaProfile *object)
86 object->priv = g_new0 (AnjutaProfilePriv, 1);
87 object->priv->plugins_hash = g_hash_table_new (g_direct_hash,
88 g_direct_equal);
89 object->priv->plugins_to_exclude_from_sync =
90 g_hash_table_new (g_direct_hash, g_direct_equal);
93 static void
94 anjuta_profile_finalize (GObject *object)
96 AnjutaProfilePriv *priv = ANJUTA_PROFILE (object)->priv;
97 g_free (priv->name);
98 if (priv->plugins)
99 g_list_free (priv->plugins);
100 g_hash_table_destroy (priv->plugins_hash);
101 g_hash_table_destroy (priv->plugins_to_exclude_from_sync);
103 G_OBJECT_CLASS (parent_class)->finalize (object);
106 static void
107 anjuta_profile_set_property (GObject *object, guint prop_id,
108 const GValue *value, GParamSpec *pspec)
110 AnjutaProfilePriv *priv = ANJUTA_PROFILE (object)->priv;
112 g_return_if_fail (ANJUTA_IS_PROFILE (object));
114 switch (prop_id)
116 case PROP_PLUGIN_MANAGER:
117 priv->plugin_manager = g_value_get_object (value);
118 break;
119 case PROP_PROFILE_NAME:
120 g_return_if_fail (g_value_get_string (value) != NULL);
121 g_free (priv->name);
122 priv->name = g_strdup (g_value_get_string (value));
123 break;
124 case PROP_PROFILE_PLUGINS:
125 if (priv->plugins)
126 g_list_free (priv->plugins);
127 if (g_value_get_pointer (value))
128 priv->plugins = g_list_copy (g_value_get_pointer (value));
129 else
130 priv->plugins = NULL;
131 break;
132 case PROP_SYNC_URI:
133 g_free (priv->sync_uri);
134 priv->sync_uri = NULL;
135 if (g_value_get_string (value) != NULL)
136 priv->sync_uri = g_value_dup_string (value);
137 break;
138 default:
139 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
140 break;
144 static void
145 anjuta_profile_get_property (GObject *object, guint prop_id,
146 GValue *value, GParamSpec *pspec)
148 AnjutaProfilePriv *priv = ANJUTA_PROFILE (object)->priv;
150 g_return_if_fail (ANJUTA_IS_PROFILE (object));
152 switch (prop_id)
154 case PROP_PLUGIN_MANAGER:
155 g_value_set_object (value, priv->plugin_manager);
156 break;
157 case PROP_PROFILE_NAME:
158 g_value_set_string (value, priv->name);
159 break;
160 case PROP_PROFILE_PLUGINS:
161 g_value_set_pointer (value, priv->plugins);
162 break;
163 case PROP_SYNC_URI:
164 g_value_set_string (value, priv->sync_uri);
165 break;
166 default:
167 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
168 break;
172 static void
173 anjuta_profile_plugin_added (AnjutaProfile *self,
174 AnjutaPluginDescription *plugin)
178 static void
179 anjuta_profile_plugin_removed (AnjutaProfile *self,
180 AnjutaPluginDescription *plugin)
184 static void
185 anjuta_profile_changed (AnjutaProfile *self, GList *plugins)
187 GError *error = NULL;
188 anjuta_profile_sync (self, &error);
189 if (error)
191 g_warning ("Failed to synchronize plugins profile '%s': %s",
192 self->priv->name, error->message);
193 g_error_free (error);
197 static void
198 anjuta_profile_class_init (AnjutaProfileClass *klass)
200 GObjectClass* object_class = G_OBJECT_CLASS (klass);
201 parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (klass));
203 object_class->finalize = anjuta_profile_finalize;
204 object_class->set_property = anjuta_profile_set_property;
205 object_class->get_property = anjuta_profile_get_property;
207 klass->plugin_added = anjuta_profile_plugin_added;
208 klass->plugin_removed = anjuta_profile_plugin_removed;
209 klass->changed = anjuta_profile_changed;
211 g_object_class_install_property (object_class,
212 PROP_PLUGIN_MANAGER,
213 g_param_spec_object ("plugin-manager",
214 _("Plugin Manager"),
215 _("The plugin manager to use for resolving plugins"),
216 ANJUTA_TYPE_PLUGIN_MANAGER,
217 G_PARAM_READABLE |
218 G_PARAM_WRITABLE |
219 G_PARAM_CONSTRUCT));
220 g_object_class_install_property (object_class,
221 PROP_PROFILE_NAME,
222 g_param_spec_string ("profile-name",
223 _("Profile Name"),
224 _("Name of the plugin profile"),
225 NULL,
226 G_PARAM_READABLE |
227 G_PARAM_WRITABLE |
228 G_PARAM_CONSTRUCT));
229 g_object_class_install_property (object_class,
230 PROP_PROFILE_PLUGINS,
231 g_param_spec_pointer ("plugins",
232 _("Profile Plugins"),
233 _("List of plugins for this profile"),
234 G_PARAM_READABLE |
235 G_PARAM_WRITABLE |
236 G_PARAM_CONSTRUCT));
237 g_object_class_install_property (object_class,
238 PROP_SYNC_URI,
239 g_param_spec_string ("sync-uri",
240 _("Synchronization URI"),
241 _("URI to sync the profile xml"),
242 NULL,
243 G_PARAM_READABLE |
244 G_PARAM_WRITABLE));
246 profile_signals[PLUGIN_ADDED] =
247 g_signal_new ("plugin-added",
248 G_OBJECT_CLASS_TYPE (klass),
249 G_SIGNAL_RUN_FIRST,
250 G_STRUCT_OFFSET (AnjutaProfileClass, plugin_added),
251 NULL, NULL,
252 anjuta_cclosure_marshal_VOID__POINTER,
253 G_TYPE_NONE, 1,
254 G_TYPE_POINTER);
256 profile_signals[PLUGIN_REMOVED] =
257 g_signal_new ("plugin-removed",
258 G_OBJECT_CLASS_TYPE (klass),
259 G_SIGNAL_RUN_FIRST,
260 G_STRUCT_OFFSET (AnjutaProfileClass, plugin_removed),
261 NULL, NULL,
262 anjuta_cclosure_marshal_VOID__POINTER,
263 G_TYPE_NONE, 1,
264 G_TYPE_POINTER);
265 profile_signals[CHANGED] =
266 g_signal_new ("changed",
267 G_OBJECT_CLASS_TYPE (klass),
268 G_SIGNAL_RUN_FIRST,
269 G_STRUCT_OFFSET (AnjutaProfileClass, changed),
270 NULL, NULL,
271 anjuta_cclosure_marshal_VOID__POINTER,
272 G_TYPE_NONE, 1,
273 G_TYPE_POINTER);
276 GType
277 anjuta_profile_get_type (void)
279 static GType our_type = 0;
281 if(our_type == 0)
283 static const GTypeInfo our_info =
285 sizeof (AnjutaProfileClass), /* class_size */
286 (GBaseInitFunc) NULL, /* base_init */
287 (GBaseFinalizeFunc) NULL, /* base_finalize */
288 (GClassInitFunc) anjuta_profile_class_init, /* class_init */
289 (GClassFinalizeFunc) NULL, /* class_finalize */
290 NULL /* class_data */,
291 sizeof (AnjutaProfile), /* instance_size */
292 0, /* n_preallocs */
293 (GInstanceInitFunc) anjuta_profile_init, /* instance_init */
294 NULL /* value_table */
297 our_type = g_type_register_static (G_TYPE_OBJECT, "AnjutaProfile",
298 &our_info, 0);
301 return our_type;
304 AnjutaProfile*
305 anjuta_profile_new (const gchar* name, AnjutaPluginManager *plugin_manager)
307 GObject *profile;
308 profile = g_object_new (ANJUTA_TYPE_PROFILE, "profile-name", name,
309 "plugin-manager", plugin_manager, NULL);
310 return ANJUTA_PROFILE (profile);
313 const gchar*
314 anjuta_profile_get_name (AnjutaProfile *profile)
316 AnjutaProfilePriv *priv;
317 g_return_val_if_fail (ANJUTA_IS_PROFILE (profile), NULL);
318 priv = ANJUTA_PROFILE (profile)->priv;
319 return priv->name;
322 void
323 anjuta_profile_add_plugin (AnjutaProfile *profile,
324 AnjutaPluginDescription *plugin)
326 AnjutaProfilePriv *priv;
327 g_return_if_fail (ANJUTA_IS_PROFILE (profile));
328 g_return_if_fail (plugin != NULL);
329 priv = ANJUTA_PROFILE (profile)->priv;
330 if (priv->plugins == NULL || g_list_find (priv->plugins, plugin) == NULL)
332 priv->plugins = g_list_prepend (priv->plugins, plugin);
333 g_signal_emit_by_name (profile, "plugin-added", plugin);
334 g_signal_emit_by_name (profile, "changed", priv->plugins);
338 void
339 anjuta_profile_remove_plugin (AnjutaProfile *profile,
340 AnjutaPluginDescription *plugin)
342 AnjutaProfilePriv *priv;
343 g_return_if_fail (ANJUTA_IS_PROFILE (profile));
344 g_return_if_fail (plugin != NULL);
345 priv = ANJUTA_PROFILE (profile)->priv;
346 if (priv->plugins && g_list_find (priv->plugins, plugin) != NULL)
348 priv->plugins = g_list_remove (priv->plugins, plugin);
349 g_signal_emit_by_name (profile, "plugin-removed", plugin);
350 g_signal_emit_by_name (profile, "changed", priv->plugins);
354 gboolean
355 anjuta_profile_has_plugin (AnjutaProfile *profile,
356 AnjutaPluginDescription *plugin)
358 AnjutaProfilePriv *priv;
359 g_return_val_if_fail (ANJUTA_IS_PROFILE (profile), FALSE);
360 g_return_val_if_fail (plugin != NULL, FALSE);
361 priv = ANJUTA_PROFILE (profile)->priv;
362 return (priv->plugins != NULL &&
363 g_list_find (priv->plugins, plugin) != NULL);
366 GList*
367 anjuta_profile_get_plugins (AnjutaProfile *profile)
369 AnjutaProfilePriv *priv;
370 g_return_val_if_fail (ANJUTA_IS_PROFILE (profile), FALSE);
371 priv = ANJUTA_PROFILE (profile)->priv;
372 return priv->plugins;
375 /* Profile processing */
376 /* Returns a list of matching plugins */
377 static GList*
378 anjuta_profile_query_plugins (AnjutaProfile *profile,
379 GList *groups, GList *attribs,
380 GList *values)
382 gchar *sec[5];
383 gchar *att[5];
384 gchar *val[5];
385 GList *sec_node, *att_node, *val_node;
386 gint length, i;
387 AnjutaProfilePriv *priv;
389 priv = profile->priv;
391 /* FIXME: How to call a variable arguments function dynamically !! */
392 length = g_list_length (groups);
394 g_return_val_if_fail ((length > 0 && length <= 5), NULL);
396 i = 0;
397 sec_node = groups;
398 att_node = attribs;
399 val_node = values;
400 while (sec_node)
402 sec[i] = sec_node->data;
403 att[i] = att_node->data;
404 val[i] = val_node->data;
406 sec_node = g_list_next (sec_node);
407 att_node = g_list_next (att_node);
408 val_node = g_list_next (val_node);
409 i++;
412 switch (length)
414 case 1:
415 return anjuta_plugin_manager_query (priv->plugin_manager,
416 sec[0], att[0], val[0], NULL);
417 case 2:
418 return anjuta_plugin_manager_query (priv->plugin_manager,
419 sec[0], att[0], val[0],
420 sec[1], att[1], val[1],
421 NULL);
422 case 3:
423 return anjuta_plugin_manager_query (priv->plugin_manager,
424 sec[0], att[0], val[0],
425 sec[1], att[1], val[1],
426 sec[2], att[2], val[2],
427 NULL);
428 case 4:
429 return anjuta_plugin_manager_query (priv->plugin_manager,
430 sec[0], att[0], val[0],
431 sec[1], att[1], val[1],
432 sec[2], att[2], val[2],
433 sec[3], att[3], val[3],
434 NULL);
435 case 5:
436 return anjuta_plugin_manager_query (priv->plugin_manager,
437 sec[0], att[0], val[0],
438 sec[1], att[1], val[1],
439 sec[2], att[2], val[2],
440 sec[3], att[3], val[3],
441 sec[4], att[4], val[4],
442 NULL);
443 default:
444 g_warning ("FIXME: How to call a variable args function dynamically !!");
446 return NULL;
449 static GList*
450 anjuta_profile_select_plugins (AnjutaProfile *profile,
451 GList *descs_list)
453 GList *selected_plugins = NULL;
454 GList *node = descs_list;
455 AnjutaProfilePriv *priv;
457 priv = profile->priv;
459 while (node)
461 GList *descs = node->data;
462 if (g_list_length (descs) == 1)
464 selected_plugins = g_list_prepend (selected_plugins, descs->data);
466 else
468 AnjutaPluginDescription* d;
469 d = anjuta_plugin_manager_select (priv->plugin_manager,
470 "Select a plugin",
471 "Please select a plugin from the list",
472 descs);
473 if (d)
474 selected_plugins = g_list_prepend (selected_plugins, d);
476 node = g_list_next (node);
478 return g_list_reverse (selected_plugins);
481 gboolean
482 anjuta_profile_add_plugins_from_xml (AnjutaProfile *profile,
483 const gchar* profile_xml_uri,
484 gboolean exclude_from_sync,
485 GError **error)
487 AnjutaProfilePriv *priv;
488 xmlDocPtr xml_doc;
489 xmlNodePtr xml_root, xml_node;
490 GnomeVFSHandle *handle;
491 GnomeVFSFileInfo info;
492 GnomeVFSResult result;
493 int perm, read;
494 GList *descs_list = NULL;
495 GList *selected_plugins = NULL;
496 GList *not_found_names = NULL;
497 GList *not_found_urls = NULL;
498 gboolean err = FALSE;
499 gchar *read_buf = NULL;
500 g_return_val_if_fail (ANJUTA_IS_PROFILE (profile), FALSE);
501 priv = profile->priv;
503 result = gnome_vfs_get_file_info (profile_xml_uri, &info,
504 GNOME_VFS_FILE_INFO_DEFAULT |
505 GNOME_VFS_FILE_INFO_GET_ACCESS_RIGHTS);
507 /* If I got the info to check it out */
508 if(result != GNOME_VFS_OK )
510 g_set_error (error, ANJUTA_PROFILE_ERROR,
511 ANJUTA_PROFILE_ERROR_URI_READ_FAILED,
512 _("Failed to read '%s': %s"),
513 profile_xml_uri,
514 gnome_vfs_result_to_string (result));
515 return FALSE;
518 /* FIXME: Fix this bit masking */
519 perm = (info.permissions-(int)(info.permissions/65536)*65536);
520 read = (int)(perm/256);
522 if(read == 0)
524 g_set_error (error, ANJUTA_PROFILE_ERROR,
525 ANJUTA_PROFILE_ERROR_URI_READ_FAILED,
526 _("No read permission for: %s"),
527 profile_xml_uri);
528 return FALSE;
530 if((result = gnome_vfs_open (&handle, profile_xml_uri,
531 GNOME_VFS_OPEN_READ)) != GNOME_VFS_OK)
533 g_set_error (error, ANJUTA_PROFILE_ERROR,
534 ANJUTA_PROFILE_ERROR_URI_READ_FAILED,
535 _("Failed to read '%s': %s"),
536 profile_xml_uri,
537 gnome_vfs_result_to_string (result));
538 return FALSE;
540 read_buf = g_new0(char, info.size + 1);
542 result = gnome_vfs_read (handle, read_buf, info.size, NULL);
543 if(!(result == GNOME_VFS_OK || result == GNOME_VFS_ERROR_EOF))
545 g_free (read_buf);
546 g_set_error (error, ANJUTA_PROFILE_ERROR,
547 ANJUTA_PROFILE_ERROR_URI_READ_FAILED,
548 _("Failed to read '%s': %s"),
549 profile_xml_uri,
550 gnome_vfs_result_to_string (result));
551 return FALSE;
553 gnome_vfs_close (handle);
554 xml_doc = xmlParseMemory (read_buf, info.size);
555 g_free(read_buf);
556 if(xml_doc == NULL)
558 g_set_error (error, ANJUTA_PROFILE_ERROR,
559 ANJUTA_PROFILE_ERROR_URI_READ_FAILED,
560 _("Failed to read '%s': XML parse error"),
561 profile_xml_uri);
562 return FALSE;
565 xml_root = xmlDocGetRootElement(xml_doc);
566 if(xml_root == NULL)
568 g_set_error (error, ANJUTA_PROFILE_ERROR,
569 ANJUTA_PROFILE_ERROR_URI_READ_FAILED,
570 _("Failed to read '%s': XML parse error"),
571 profile_xml_uri);
572 xmlFreeDoc(xml_doc);
573 return FALSE;
576 if(!xml_root->name ||
577 !xmlStrEqual(xml_root->name, (const xmlChar *)"anjuta"))
579 g_set_error (error, ANJUTA_PROFILE_ERROR,
580 ANJUTA_PROFILE_ERROR_URI_READ_FAILED,
581 _("Failed to read '%s': XML parse error. "
582 "Invalid or corrupted anjuta plugins profile."),
583 profile_xml_uri);
584 xmlFreeDoc(xml_doc);
585 return FALSE;
588 error = FALSE;
589 descs_list = NULL;
590 not_found_names = NULL;
591 not_found_urls = NULL;
593 xml_node = xml_root->xmlChildrenNode;
594 while (xml_node && !error)
596 GList *groups = NULL;
597 GList *attribs = NULL;
598 GList *values = NULL;
599 GList *plugin_descs;
600 gchar *name, *url, *mandatory_text;
601 xmlNodePtr xml_require_node;
602 gboolean mandatory;
604 if (!xml_node->name ||
605 !xmlStrEqual (xml_node->name, (const xmlChar*)"plugin"))
607 xml_node = xml_node->next;
608 continue;
611 name = (gchar*) xmlGetProp (xml_node, (const xmlChar*)"name");
612 url = (gchar*) xmlGetProp (xml_node, (const xmlChar*)"url");
614 /* Ensure that both name is given */
615 if (!name)
617 g_warning ("XML error: Plugin name should be present in plugin tag");
618 err = TRUE;
619 break;
621 if (!url)
622 url = g_strdup ("http://anjuta.org/plugins/");
624 /* Check if the plugin is mandatory */
625 mandatory_text = (gchar*) xmlGetProp (xml_node,
626 (const xmlChar*)"mandatory");
627 if (mandatory_text && strcasecmp (mandatory_text, "yes") == 0)
628 mandatory = TRUE;
629 else
630 mandatory = FALSE;
631 xmlFree(mandatory_text);
633 /* For all plugin attribute conditions */
634 xml_require_node = xml_node->xmlChildrenNode;
635 while (xml_require_node && !error)
637 gchar *group;
638 gchar *attrib;
639 gchar *value;
641 if (!xml_require_node->name ||
642 !xmlStrEqual (xml_require_node->name,
643 (const xmlChar*)"require"))
645 xml_require_node = xml_require_node->next;
646 continue;
648 group = (gchar*) xmlGetProp (xml_require_node,
649 (const xmlChar *)"group");
650 attrib = (gchar*) xmlGetProp(xml_require_node,
651 (const xmlChar *)"attribute");
652 value = (gchar*) xmlGetProp(xml_require_node,
653 (const xmlChar *)"value");
655 if (group && attrib && value)
657 groups = g_list_prepend (groups, group);
658 attribs = g_list_prepend (attribs, attrib);
659 values = g_list_prepend (values, value);
661 else
663 if (group) xmlFree (group);
664 if (attrib) xmlFree (attrib);
665 if (value) xmlFree (value);
666 err = TRUE;
667 g_warning ("XML parse error: group, attribute and value should be defined in require");
668 break;
670 xml_require_node = xml_require_node->next;
672 if (error)
674 g_list_foreach (groups, (GFunc)xmlFree, NULL);
675 g_list_foreach (attribs, (GFunc)xmlFree, NULL);
676 g_list_foreach (values, (GFunc)xmlFree, NULL);
677 g_list_free (groups);
678 g_list_free (attribs);
679 g_list_free (values);
680 xmlFree (name);
681 xmlFree (url);
682 break;
684 if (g_list_length (groups) == 0)
686 err = TRUE;
687 g_warning ("XML Error: No attributes to match given");
688 xmlFree (name);
689 xmlFree (url);
690 break;
692 if (g_list_length (groups) > 5)
694 err = TRUE;
695 g_warning ("XML Error: Maximum 5 attributes can be given (FIXME)");
696 xmlFree (name);
697 xmlFree (url);
698 break;
700 plugin_descs = anjuta_profile_query_plugins (profile,
701 groups, attribs,
702 values);
703 if (plugin_descs)
705 descs_list = g_list_prepend (descs_list, plugin_descs);
706 xmlFree (name);
707 xmlFree (url);
709 else if (mandatory)
711 not_found_names = g_list_prepend (not_found_names, name);
712 not_found_urls = g_list_prepend (not_found_urls, url);
714 else
716 xmlFree (name);
717 xmlFree (url);
719 xml_node = xml_node->next;
721 if (error)
723 g_list_foreach (not_found_names, (GFunc)xmlFree, NULL);
724 g_list_foreach (not_found_urls, (GFunc)xmlFree, NULL);
725 g_list_foreach (descs_list, (GFunc)g_list_free, NULL);
726 g_list_free (not_found_names);
727 g_list_free (not_found_urls);
728 g_list_free (descs_list);
730 g_set_error (error, ANJUTA_PROFILE_ERROR,
731 ANJUTA_PROFILE_ERROR_URI_READ_FAILED,
732 _("Failed to read '%s': XML parse error. "
733 "Invalid or corrupted anjuta plugins profile."),
734 profile_xml_uri);
735 xmlFreeDoc(xml_doc);
736 return FALSE;
738 if (not_found_names)
741 * FIXME: Present a nice dialog box to promt the user to download
742 * the plugin from corresponding URLs, install them and proceed.
744 GList *node_name, *node_url;
745 GString *mesg = g_string_new ("");
747 not_found_names = g_list_reverse (not_found_names);
748 not_found_urls = g_list_reverse (not_found_urls);
750 node_name = not_found_names;
751 node_url = not_found_urls;
752 while (node_name)
754 /* <Pluginname>: Install it from <some location on the web> */
755 g_string_append_printf (mesg, _("%s: Install it from '%s'\n"),
756 (char *)node_name->data,
757 (char*)node_url->data);
758 node_name = g_list_next (node_name);
759 node_url = g_list_next (node_url);
761 g_set_error (error, ANJUTA_PROFILE_ERROR,
762 ANJUTA_PROFILE_ERROR_URI_READ_FAILED,
763 _("Failed to read '%s': Following mandatory plugins are missing:\n%s"),
764 profile_xml_uri, mesg->str);
765 g_string_free (mesg, TRUE);
767 /* FIXME: It should not return like this ... */
768 g_list_foreach (not_found_names, (GFunc)xmlFree, NULL);
769 g_list_foreach (not_found_urls, (GFunc)xmlFree, NULL);
770 g_list_foreach (descs_list, (GFunc)g_list_free, NULL);
771 g_list_free (not_found_names);
772 g_list_free (not_found_urls);
773 g_list_free (descs_list);
775 xmlFreeDoc(xml_doc);
776 return FALSE;
778 if (descs_list)
780 GList *node;
782 /* Now everything okay. Select the plugins */
783 descs_list = g_list_reverse (descs_list);
784 selected_plugins =
785 anjuta_profile_select_plugins (profile, descs_list);
786 g_list_foreach (descs_list, (GFunc)g_list_free, NULL);
787 g_list_free (descs_list);
789 node = selected_plugins;
790 while (node)
792 if (exclude_from_sync)
794 g_hash_table_insert (priv->plugins_to_exclude_from_sync,
795 node->data, node->data);
798 /* Insure no duplicate plugins are added */
799 if (g_hash_table_lookup (priv->plugins_hash, node->data) == NULL)
801 priv->plugins = g_list_append (priv->plugins, node->data);
802 g_hash_table_insert (priv->plugins_hash,
803 node->data, node->data);
805 node = g_list_next (node);
807 g_list_free (selected_plugins);
809 xmlFreeDoc(xml_doc);
810 return TRUE;
813 gchar*
814 anjuta_profile_to_xml (AnjutaProfile *profile)
816 GList *node;
817 GString *str;
818 AnjutaProfilePriv *priv;
820 g_return_val_if_fail (ANJUTA_IS_PROFILE (profile), FALSE);
821 priv = profile->priv;
823 str = g_string_new ("<?xml version=\"1.0\"?>\n<anjuta>\n");
824 node = priv->plugins;
825 while (node)
827 AnjutaPluginDescription *desc;
828 desc = (AnjutaPluginDescription *)node->data;
829 if (!g_hash_table_lookup (priv->plugins_to_exclude_from_sync,
830 node->data))
832 gchar *user_activatable = NULL;
833 gchar *name = NULL, *plugin_id = NULL;
836 anjuta_plugin_description_get_string (desc, "Anjuta Plugin",
837 "UserActivatable",
838 &user_activatable);
839 /* Do not save plugins that are auto activated */
840 if (user_activatable && strcmp (user_activatable, "no") == 0)
842 g_free (user_activatable);
843 node = g_list_next (node);
844 continue;
846 g_free (user_activatable);
847 /* Do not use the _locale_ version because it's not in UI */
848 anjuta_plugin_description_get_string (desc, "Anjuta Plugin",
849 "Name", &name);
850 DEBUG_PRINT("Saving plugin: %s", name);
851 if (!name)
852 name = g_strdup ("Unknown");
854 if (anjuta_plugin_description_get_string (desc, "Anjuta Plugin",
855 "Location", &plugin_id))
857 g_string_append (str, " <plugin name=\"");
858 g_string_append (str, name);
859 g_string_append (str, "\" mandatory=\"no\">\n");
860 g_string_append (str, " <require group=\"Anjuta Plugin\"\n");
861 g_string_append (str, " attribute=\"Location\"\n");
862 g_string_append (str, " value=\"");
863 g_string_append (str, plugin_id);
864 g_string_append (str, "\"/>\n");
865 g_string_append (str, " </plugin>\n");
867 g_free (plugin_id);
869 g_free (name);
871 else
873 gchar* name;
874 /* Do not use the _locale_ version because it's debugging */
875 anjuta_plugin_description_get_string (desc, "Anjuta Plugin",
876 "Name", &name);
877 DEBUG_PRINT ("excluding plugin: %s", name);
878 g_free (name);
880 node = g_list_next (node);
882 g_string_append (str, "</anjuta>\n");
883 return g_string_free (str, FALSE);
886 void
887 anjuta_profile_set_sync_uri (AnjutaProfile *profile, const gchar *sync_uri)
889 AnjutaProfilePriv *priv;
891 g_return_if_fail (ANJUTA_IS_PROFILE (profile));
892 priv = profile->priv;
893 g_free (priv->sync_uri);
894 priv->sync_uri = NULL;
895 if (sync_uri)
896 priv->sync_uri = g_strdup (sync_uri);
899 gboolean
900 anjuta_profile_sync (AnjutaProfile *profile, GError **error)
902 GnomeVFSHandle* vfs_write;
903 GnomeVFSResult result;
904 GnomeVFSFileSize nchars;
905 gchar *xml_buffer;
906 AnjutaProfilePriv *priv;
908 g_return_val_if_fail (ANJUTA_IS_PROFILE (profile), FALSE);
909 priv = profile->priv;
911 if (!priv->sync_uri)
912 return FALSE;
914 xml_buffer = anjuta_profile_to_xml (profile);
915 result = gnome_vfs_create (&vfs_write, priv->sync_uri,
916 GNOME_VFS_OPEN_WRITE,
917 FALSE, 0664);
918 if (result == GNOME_VFS_OK)
920 result = gnome_vfs_write (vfs_write, xml_buffer, strlen (xml_buffer),
921 &nchars);
922 gnome_vfs_close (vfs_write);
925 if (result != GNOME_VFS_OK)
927 g_set_error (error, ANJUTA_PROFILE_ERROR,
928 ANJUTA_PROFILE_ERROR_URI_WRITE_FAILED,
929 "%s", gnome_vfs_result_to_string (result));
931 g_free (xml_buffer);
932 return (result == GNOME_VFS_OK);