~ubuntu-branches/ubuntu/trusty/anjuta/trusty

« back to all changes in this revision

Viewing changes to libanjuta/anjuta-profile.c

  • Committer: Package Import Robot
  • Author(s): Steve Ovens
  • Date: 2014-01-03 21:06:06 UTC
  • mfrom: (1.1.55)
  • Revision ID: package-import@ubuntu.com-20140103210606-pmvzhu0s68qy6261
Tags: 2:3.10.2-0ubuntu1
* New upstream release (LP: #1266037)
- Updated Build-Depends of libgtk-3-dev (>= 3.6.0),
  libglib2.0-dev (>= 2.34.0)

Show diffs side-by-side

added added

removed removed

Lines of Context:
37
37
 *    <term>$prefix/share/anjuta/profiles/default.profile</term>
38
38
 *    <listitem>
39
39
 *    <para>
40
 
 *        This contains the system plugins. It is loaded in every profile and
41
 
 *        contains mandatory plugins for Anjuta. These plugins cannot be
42
 
 *        unloaded.
 
40
 *        This contains the system plugins. It is loaded in special system
 
41
 *        profile and contains mandatory plugins for Anjuta. These plugins
 
42
 *        cannot be unloaded. Anjuta can load a different profile using the -P
 
43
 *        command line option.
43
44
 *    </para>
44
45
 *    </listitem>
45
46
 *    </varlistentry>
84
85
        PROP_0,
85
86
        PROP_PLUGIN_MANAGER,
86
87
        PROP_PROFILE_NAME,
87
 
        PROP_PROFILE_PLUGINS,
88
88
        PROP_SYNC_FILE,
89
89
};
90
90
 
93
93
        PLUGIN_ADDED,
94
94
        PLUGIN_REMOVED,
95
95
        CHANGED,
 
96
        DESCOPED,
 
97
        SCOPED,
96
98
        LAST_SIGNAL
97
99
};
98
100
 
 
101
typedef struct _AnjutaProfileXml AnjutaProfileXml;
 
102
 
 
103
struct _AnjutaProfileXml
 
104
{
 
105
        GFile *file;
 
106
        xmlDocPtr doc;
 
107
        gboolean exclude_from_sync;
 
108
        AnjutaProfileXml *next;
 
109
};
 
110
 
 
111
 
99
112
struct _AnjutaProfilePriv
100
113
{
101
114
        gchar *name;
102
115
        AnjutaPluginManager *plugin_manager;
103
 
        GList *plugins;
104
 
        GHashTable *plugins_hash;
 
116
        GHashTable *plugins_to_load;
105
117
        GHashTable *plugins_to_exclude_from_sync;
 
118
        GList *plugins_to_disable;
 
119
        GList *configuration;
 
120
        GList *config_keys;
106
121
        GFile *sync_file;
 
122
        AnjutaProfileXml *xml;
107
123
};
108
124
 
109
125
static GObjectClass* parent_class = NULL;
125
141
anjuta_profile_init (AnjutaProfile *object)
126
142
{
127
143
        object->priv = g_new0 (AnjutaProfilePriv, 1);
128
 
        object->priv->plugins_hash = g_hash_table_new (g_direct_hash,
129
 
                                                                                                   g_direct_equal);
130
 
        object->priv->plugins_to_exclude_from_sync =
131
 
                g_hash_table_new (g_direct_hash, g_direct_equal);
 
144
        object->priv->plugins_to_load = g_hash_table_new (g_direct_hash,
 
145
                                                          g_direct_equal);
 
146
        object->priv->plugins_to_exclude_from_sync = g_hash_table_new (g_direct_hash,
 
147
                                                                       g_direct_equal);
132
148
}
133
149
 
134
150
static void
136
152
{
137
153
        AnjutaProfilePriv *priv = ANJUTA_PROFILE (object)->priv;
138
154
        g_free (priv->name);
139
 
        if (priv->plugins)
140
 
                g_list_free (priv->plugins);
141
 
        g_hash_table_destroy (priv->plugins_hash);
 
155
        g_hash_table_destroy (priv->plugins_to_load);
142
156
        g_hash_table_destroy (priv->plugins_to_exclude_from_sync);
143
 
        
 
157
        g_list_free (priv->plugins_to_disable);
 
158
        g_list_free_full (priv->config_keys, (GDestroyNotify)g_free);
 
159
        g_list_free (priv->configuration);
 
160
 
 
161
        while (priv->xml != NULL)
 
162
        {
 
163
                AnjutaProfileXml *next;
 
164
 
 
165
                next = priv->xml->next;
 
166
                g_object_unref (priv->xml->file);
 
167
                g_free (priv->xml);
 
168
                priv->xml = next;
 
169
        }
 
170
 
144
171
        G_OBJECT_CLASS (parent_class)->finalize (object);
145
172
}
146
173
 
162
189
                g_free (priv->name);
163
190
                priv->name = g_strdup (g_value_get_string (value));
164
191
                break;
165
 
        case PROP_PROFILE_PLUGINS:
166
 
                if (priv->plugins)
167
 
                        g_list_free (priv->plugins);
168
 
                if (g_value_get_pointer (value))
169
 
                        priv->plugins = g_list_copy (g_value_get_pointer (value));
170
 
                else
171
 
                        priv->plugins = NULL;
172
 
                break;
173
192
        case PROP_SYNC_FILE:
174
193
                if (priv->sync_file)
175
194
                                g_object_unref (priv->sync_file);
197
216
        case PROP_PROFILE_NAME:
198
217
                g_value_set_string (value, priv->name);
199
218
                break;
200
 
        case PROP_PROFILE_PLUGINS:
201
 
                g_value_set_pointer (value, priv->plugins);
202
 
                break;
203
219
        case PROP_SYNC_FILE:
204
220
                g_value_set_object (value, priv->sync_file);
205
221
                break;
211
227
 
212
228
static void
213
229
anjuta_profile_plugin_added (AnjutaProfile *self,
214
 
                                                         AnjutaPluginDescription *plugin)
 
230
                                                         AnjutaPluginHandle *plugin)
215
231
{
216
232
}
217
233
 
218
234
static void
219
235
anjuta_profile_plugin_removed (AnjutaProfile *self,
220
 
                                                           AnjutaPluginDescription *plugin)
 
236
                                                           AnjutaPluginHandle *plugin)
221
237
{
222
238
}
223
239
 
224
240
static void
225
 
anjuta_profile_changed (AnjutaProfile *self, GList *plugins)
 
241
anjuta_profile_changed (AnjutaProfile *self)
226
242
{
227
243
        GError *error = NULL;
228
244
        anjuta_profile_sync (self, &error);
267
283
                                                                                          G_PARAM_WRITABLE |
268
284
                                                                                          G_PARAM_CONSTRUCT));
269
285
        g_object_class_install_property (object_class,
270
 
                                         PROP_PROFILE_PLUGINS,
271
 
                                         g_param_spec_pointer ("plugins",
272
 
                                                                                          _("Profile Plugins"),
273
 
                                                                                          _("List of plugins for this profile"),
274
 
                                                                                          G_PARAM_READABLE |
275
 
                                                                                          G_PARAM_WRITABLE |
276
 
                                                                                          G_PARAM_CONSTRUCT));
277
 
        g_object_class_install_property (object_class,
278
286
                                         PROP_SYNC_FILE,
279
287
                                         g_param_spec_object ("sync-file",
280
288
                                                                                          _("Synchronization file"),
287
295
        /**
288
296
         * AnjutaProfile::plugin-added:
289
297
         * @profile: a #AnjutaProfile object.
290
 
         * @plugin: the new plugin as a #AnjutaPluginDescription.
 
298
         * @plugin: the new plugin as a #AnjutaPluginHandle.
291
299
         * 
292
300
         * Emitted when a plugin is added in the list.
293
301
         */
304
312
        /**
305
313
         * AnjutaProfile::plugin-removed:
306
314
         * @profile: a #AnjutaProfile object.
307
 
         * @plugin: the removed plugin as a #AnjutaPluginDescription.
 
315
         * @plugin: the removed plugin as a #AnjutaPluginHandle.
308
316
         * 
309
317
         * Emitted when a plugin is removed from the list.
310
318
         */
321
329
        /**
322
330
         * AnjutaProfile::changed:
323
331
         * @profile: a #AnjutaProfile object.
324
 
         * @plugin_list: the new plugins list.
325
332
         * 
326
333
         * Emitted when a plugin is added or removed from the list.
327
334
         */
332
339
                              G_STRUCT_OFFSET (AnjutaProfileClass, changed),
333
340
                              NULL, NULL,
334
341
                              anjuta_cclosure_marshal_VOID__POINTER,
335
 
                              G_TYPE_NONE, 1,
336
 
                              G_TYPE_POINTER);
 
342
                              G_TYPE_NONE, 0);
 
343
 
 
344
        /**
 
345
         * AnjutaProfile::profile-descoped:
 
346
         * @profile: the old unloaded #AnjutaProfile
 
347
         *
 
348
         * Emitted when a profile will be unloaded.
 
349
         */
 
350
        profile_signals[DESCOPED] =
 
351
                g_signal_new ("descoped",
 
352
                              G_OBJECT_CLASS_TYPE (klass),
 
353
                              G_SIGNAL_RUN_FIRST,
 
354
                              G_STRUCT_OFFSET (AnjutaProfileClass,
 
355
                                                                           descoped),
 
356
                              NULL, NULL,
 
357
                                          g_cclosure_marshal_VOID__VOID,
 
358
                              G_TYPE_NONE, 0);
 
359
 
 
360
        /**
 
361
         * AnjutaProfileManager::profile-scoped:
 
362
         * @profile_manager: a #AnjutaProfileManager object.
 
363
         * @profile: the current loaded #AnjutaProfile.
 
364
         *
 
365
         * Emitted when a new profile is loaded.
 
366
         */
 
367
        profile_signals[SCOPED] =
 
368
                g_signal_new ("scoped",
 
369
                              G_OBJECT_CLASS_TYPE (klass),
 
370
                              G_SIGNAL_RUN_FIRST,
 
371
                              G_STRUCT_OFFSET (AnjutaProfileClass,
 
372
                                                                           scoped),
 
373
                              NULL, NULL,
 
374
                                          g_cclosure_marshal_VOID__VOID,
 
375
                              G_TYPE_NONE, 0);
337
376
}
338
377
 
339
378
GType
364
403
        return our_type;
365
404
}
366
405
 
 
406
static void
 
407
on_plugin_activated (AnjutaPluginManager *plugin_manager,
 
408
                                         AnjutaPluginHandle *plugin_handle,
 
409
                                         GObject *plugin_object,
 
410
                                         AnjutaProfile *profile)
 
411
{
 
412
        /* Add it current profile */
 
413
        gboolean exclude;
 
414
        AnjutaPluginDescription *desc;
 
415
 
 
416
        desc = anjuta_plugin_handle_get_description (plugin_handle);
 
417
        if (!anjuta_plugin_description_get_boolean (desc, "Anjuta Plugin", "ExcludeFromSession", &exclude) || !exclude)
 
418
        {
 
419
                anjuta_profile_add_plugin (profile, plugin_handle);
 
420
        }
 
421
}
 
422
 
 
423
static void
 
424
on_plugin_deactivated (AnjutaPluginManager *plugin_manager,
 
425
                                           AnjutaPluginHandle *plugin_handle,
 
426
                                           GObject *plugin_object,
 
427
                                           AnjutaProfile *profile)
 
428
{
 
429
        /* Remove from current profile */
 
430
        anjuta_profile_remove_plugin (profile, plugin_handle);
 
431
}
 
432
 
367
433
/**
368
434
 * anjuta_profile_new:
369
435
 * @name: the new profile name.
402
468
/**
403
469
 * anjuta_profile_add_plugin:
404
470
 * @profile: a #AnjutaProfile object.
405
 
 * @plugin: a #AnjutaPluginDescription.
 
471
 * @plugin: a #AnjutaPluginHandle.
406
472
 * 
407
473
 * Add one plugin into the profile plugin list.
408
474
 */
409
475
void
410
476
anjuta_profile_add_plugin (AnjutaProfile *profile,
411
 
                                                   AnjutaPluginDescription *plugin)
 
477
                                                   AnjutaPluginHandle *plugin)
412
478
{
413
479
        AnjutaProfilePriv *priv;
414
480
        g_return_if_fail (ANJUTA_IS_PROFILE (profile));
415
481
        g_return_if_fail (plugin != NULL);
416
482
        priv = ANJUTA_PROFILE (profile)->priv;
417
 
        if (priv->plugins == NULL || g_list_find (priv->plugins, plugin) == NULL)
 
483
        if (g_hash_table_lookup (priv->plugins_to_load, plugin) == NULL)
418
484
        {
419
 
                priv->plugins = g_list_prepend (priv->plugins, plugin);
 
485
                g_hash_table_add (priv->plugins_to_load, plugin);
420
486
                g_signal_emit_by_name (profile, "plugin-added", plugin);
421
 
                g_signal_emit_by_name (profile, "changed", priv->plugins);
 
487
                g_signal_emit_by_name (profile, "changed");
422
488
        }
423
489
}
424
490
 
425
491
/**
426
492
 * anjuta_profile_remove_plugin:
427
493
 * @profile: a #AnjutaProfile object.
428
 
 * @plugin: a #AnjutaPluginDescription.
 
494
 * @plugin: a #AnjutaPluginHandle.
429
495
 * 
430
496
 * Remove one plugin from the profile plugin list.
431
497
 */
432
498
void
433
499
anjuta_profile_remove_plugin (AnjutaProfile *profile, 
434
 
                                                          AnjutaPluginDescription *plugin)
 
500
                                                          AnjutaPluginHandle *plugin)
435
501
{
436
502
        AnjutaProfilePriv *priv;
437
503
        g_return_if_fail (ANJUTA_IS_PROFILE (profile));
438
504
        g_return_if_fail (plugin != NULL);
439
505
        priv = ANJUTA_PROFILE (profile)->priv;
440
 
        if (priv->plugins && g_list_find (priv->plugins, plugin) != NULL)
 
506
        if (g_hash_table_remove (priv->plugins_to_load, plugin))
441
507
        {
442
 
                priv->plugins = g_list_remove (priv->plugins, plugin);
 
508
                g_hash_table_remove (priv->plugins_to_exclude_from_sync, plugin);
443
509
                g_signal_emit_by_name (profile, "plugin-removed", plugin);
444
 
                g_signal_emit_by_name (profile, "changed", priv->plugins);
 
510
                g_signal_emit_by_name (profile, "changed");
445
511
        }
446
512
}
447
513
 
448
514
/**
449
515
 * anjuta_profile_has_plugin:
450
516
 * @profile: a #AnjutaProfile object
451
 
 * @plugin: a #AnjutaPluginDescription 
 
517
 * @plugin: a #AnjutaPluginHandle
452
518
 * 
453
519
 * Check if a plugin is included in the profile plugin list.
454
520
 *
455
 
 * Return value: TRUE if the plugin is included in the list.
 
521
 * Return value: %TRUE if the plugin is included in the list.
456
522
 */
457
523
gboolean
458
524
anjuta_profile_has_plugin (AnjutaProfile *profile,
459
 
                                                   AnjutaPluginDescription *plugin)
 
525
                                                   AnjutaPluginHandle *plugin)
460
526
{
461
527
        AnjutaProfilePriv *priv;
462
528
        g_return_val_if_fail (ANJUTA_IS_PROFILE (profile), FALSE);
463
529
        g_return_val_if_fail (plugin != NULL, FALSE);
464
530
        priv = ANJUTA_PROFILE (profile)->priv;
465
 
        return (priv->plugins != NULL &&
466
 
                        g_list_find (priv->plugins, plugin) != NULL);
467
 
}
468
 
 
469
 
/**
470
 
 * anjuta_profile_get_plugins:
471
 
 * @profile: a #AnjutaProfile object.
472
 
 * 
473
 
 * Get the profile current plugins list.
474
 
 *
475
 
 * Return value: the plugins list.
476
 
 */
477
 
GList*
478
 
anjuta_profile_get_plugins (AnjutaProfile *profile)
479
 
{
480
 
        AnjutaProfilePriv *priv;
481
 
        g_return_val_if_fail (ANJUTA_IS_PROFILE (profile), FALSE);
482
 
        priv = ANJUTA_PROFILE (profile)->priv;
483
 
        return priv->plugins;
 
531
 
 
532
        return g_hash_table_lookup (priv->plugins_to_load, plugin) != NULL;
 
533
}
 
534
 
 
535
static gboolean
 
536
anjuta_profile_configure_plugins (AnjutaProfile *profile,
 
537
                                  GList *handles_list,
 
538
                                  GList *config_list)
 
539
{
 
540
        AnjutaProfilePriv *priv;
 
541
        GList *item;
 
542
        GList *config;
 
543
 
 
544
        g_return_val_if_fail (ANJUTA_IS_PROFILE (profile), FALSE);
 
545
 
 
546
        priv = ANJUTA_PROFILE (profile)->priv;
 
547
        for (config = config_list, item = handles_list; item != NULL; item = g_list_next (item), config = g_list_next (config))
 
548
        {
 
549
                GList *plugin;
 
550
                GList *set;
 
551
 
 
552
                for (plugin = g_list_first ((GList *)item->data); plugin != NULL; plugin = g_list_next (plugin))
 
553
                {
 
554
                        AnjutaPluginHandle *handle = ANJUTA_PLUGIN_HANDLE (plugin->data);
 
555
                        AnjutaPluginDescription *desc;
 
556
 
 
557
                        desc = anjuta_plugin_handle_get_description (handle);
 
558
                        for (set = g_list_first ((GList *)config->data); set != NULL; set = g_list_next (set))
 
559
                        {
 
560
                                gchar *group = (gchar *)set->data;
 
561
                                gchar *key = group + strlen (group) + 1;
 
562
                                gchar *value = key + strlen (key) + 1;
 
563
 
 
564
                                anjuta_plugin_description_override (desc, group, key, value);
 
565
                                priv->configuration = g_list_prepend (priv->configuration, group);
 
566
                                priv->configuration = g_list_prepend (priv->configuration, handle);
 
567
                        }
 
568
                }
 
569
                for (set = g_list_first ((GList *)config->data); set != NULL; set = g_list_delete_link (set, set))
 
570
                {
 
571
                        priv->config_keys = g_list_prepend (priv->config_keys, set->data);
 
572
                }
 
573
        }
 
574
        g_list_free (config_list);
 
575
 
 
576
        return TRUE;
 
577
}
 
578
 
 
579
 
 
580
static gboolean
 
581
anjuta_profile_unconfigure_plugins (AnjutaProfile *profile)
 
582
{
 
583
        AnjutaProfilePriv *priv;
 
584
        GList *item;
 
585
 
 
586
        g_return_val_if_fail (ANJUTA_IS_PROFILE (profile), FALSE);
 
587
 
 
588
        priv = ANJUTA_PROFILE (profile)->priv;
 
589
        for (item = g_list_first (priv->configuration); item != NULL; item = g_list_delete_link (item, item))
 
590
        {
 
591
                AnjutaPluginHandle *handle = ANJUTA_PLUGIN_HANDLE (item->data);
 
592
                AnjutaPluginDescription *desc;
 
593
                gchar *group;
 
594
                gchar *key;
 
595
 
 
596
                item = g_list_delete_link (item, item);
 
597
                group = (gchar *)(item->data);
 
598
                key = group + strlen (group) + 1;
 
599
 
 
600
                desc = anjuta_plugin_handle_get_description (handle);
 
601
                anjuta_plugin_description_remove (desc, group, key);
 
602
        }
 
603
        priv->configuration = NULL;
 
604
        g_list_free_full (priv->config_keys, (GDestroyNotify)g_free);
 
605
        priv->config_keys = NULL;
 
606
 
 
607
        return TRUE;
484
608
}
485
609
 
486
610
static GList*
487
611
anjuta_profile_select_plugins (AnjutaProfile *profile,
488
 
                                                           GList *descs_list)
 
612
                                                           GList *handles_list)
489
613
{
490
614
        GList *selected_plugins = NULL;
491
 
        GList *node = descs_list;
 
615
        GList *node = handles_list;
492
616
        AnjutaProfilePriv *priv;
493
617
        
494
618
        priv = profile->priv;
502
626
                }
503
627
                else
504
628
                {
505
 
                        AnjutaPluginDescription* d;
506
 
                        d = anjuta_plugin_manager_select (priv->plugin_manager,
507
 
                                                                                          _("Select a plugin"),
508
 
                                                                                          _("Please select a plugin from the list"),
509
 
                                                                                          descs);
510
 
                        if (d)
511
 
                                selected_plugins = g_list_prepend (selected_plugins, d);
 
629
                        AnjutaPluginHandle* handle;
 
630
                        handle = anjuta_plugin_manager_select (priv->plugin_manager,
 
631
                                                               _("Select a plugin"),
 
632
                                                               _("Please select a plugin from the list"),
 
633
                                                               descs);
 
634
                        if (handle)
 
635
                                selected_plugins = g_list_prepend (selected_plugins, handle);
512
636
                }
513
637
                node = g_list_next (node);
514
638
        }
515
639
        return g_list_reverse (selected_plugins);
516
640
}
517
641
 
518
 
static GList *
519
 
anjuta_profile_read_plugins_from_xml (AnjutaProfile *profile,
520
 
                                                                          GFile *file,
521
 
                                                                          GError **error)
 
642
 
 
643
/* Read profile from XML
 
644
 *---------------------------------------------------------------------------*/
 
645
 
 
646
/* Error during parsing */
 
647
static gboolean
 
648
set_parse_error (GError **error, GFile*file)
 
649
{
 
650
        gchar *uri = g_file_get_uri (file);
 
651
 
 
652
        g_error_free (*error);
 
653
        *error = g_error_new (ANJUTA_PROFILE_ERROR,
 
654
                              ANJUTA_PROFILE_ERROR_URI_READ_FAILED,
 
655
                              _("Failed to read '%s': XML parse error. "
 
656
                                "Invalid or corrupted Anjuta plugins profile."),
 
657
                              uri);
 
658
        g_free (uri);
 
659
 
 
660
        return FALSE;
 
661
}
 
662
 
 
663
static xmlDocPtr
 
664
load_profile_from_xml (GFile *file, GError **error)
522
665
{
523
666
        gchar *read_buf;
524
667
        gsize size;
525
668
        xmlDocPtr xml_doc;
526
 
        GList *descs_list = NULL;
527
 
        GList *not_found_names = NULL;
528
 
        GList *not_found_urls = NULL;
529
 
        gboolean parse_error;
530
669
 
531
670
        /* Read xml file */
532
671
        if (!g_file_load_contents (file, NULL, &read_buf, &size, NULL, error))
535
674
        }
536
675
        
537
676
        /* Parse xml file */
538
 
        parse_error = TRUE;
539
677
        xml_doc = xmlParseMemory (read_buf, size);
540
678
        g_free (read_buf);
541
679
        if (xml_doc != NULL)
543
681
                xmlNodePtr xml_root;
544
682
                
545
683
                xml_root = xmlDocGetRootElement(xml_doc);
546
 
                if (xml_root &&
547
 
                        (xml_root->name) &&
 
684
                if (xml_root ||
 
685
                        (xml_root->name) ||
548
686
                        xmlStrEqual(xml_root->name, (const xmlChar *)"anjuta"))
549
687
                {
550
 
                        xmlNodePtr xml_node;
551
 
 
552
 
                        parse_error = FALSE;
553
 
                        for (xml_node = xml_root->xmlChildrenNode; xml_node; xml_node = xml_node->next)
554
 
                        {
555
 
                                GList *groups = NULL;
556
 
                                GList *attribs = NULL;
557
 
                                GList *values = NULL;
558
 
                                xmlChar *name, *url, *mandatory_text;
559
 
                                xmlNodePtr xml_require_node;
560
 
                                gboolean mandatory;
561
 
 
562
 
                                if (!xml_node->name ||
563
 
                                        !xmlStrEqual (xml_node->name, (const xmlChar*)"plugin"))
564
 
                                {
565
 
                                        continue;
566
 
                                }
567
 
        
568
 
                                name = xmlGetProp (xml_node, (const xmlChar*)"name");
569
 
                                url = xmlGetProp (xml_node, (const xmlChar*)"url");
570
 
                
571
 
                                /* Ensure that both name is given */
572
 
                                if (!name)
573
 
                                {
574
 
                                        g_warning ("XML error: Plugin name should be present in plugin tag");
575
 
                                        parse_error = TRUE;
576
 
                                        break;
577
 
                                }
578
 
                                if (!url)
579
 
                                        url = xmlCharStrdup ("http://anjuta.org/plugins/");
580
 
                                                                         
581
 
                                /* Check if the plugin is mandatory */
582
 
                                mandatory_text = xmlGetProp (xml_node, (const xmlChar*)"mandatory");
583
 
                                mandatory = mandatory_text && (xmlStrcasecmp (mandatory_text, (const xmlChar *)"yes") == 0);
584
 
                                xmlFree(mandatory_text);
585
 
                                                                                 
586
 
                                /* For all plugin attribute conditions */
587
 
                                for (xml_require_node = xml_node->xmlChildrenNode;
588
 
                                        xml_require_node;
589
 
                                        xml_require_node = xml_require_node->next)
590
 
                                {
591
 
                                        xmlChar *group;
592
 
                                        xmlChar *attrib;
593
 
                                        xmlChar *value;
594
 
                
595
 
                                        if (!xml_require_node->name ||
596
 
                                                !xmlStrEqual (xml_require_node->name,
597
 
                                                                          (const xmlChar*)"require"))
598
 
                                        {
599
 
                                                continue;
600
 
                                        }
601
 
                                        group = xmlGetProp (xml_require_node,
602
 
                                                                                (const xmlChar *)"group");
603
 
                                        attrib = xmlGetProp(xml_require_node,
604
 
                                                                                (const xmlChar *)"attribute");
605
 
                                        value = xmlGetProp(xml_require_node,
606
 
                                                                           (const xmlChar *)"value");
607
 
                        
608
 
                                        if (group && attrib && value)
609
 
                                        {
610
 
                                                groups = g_list_prepend (groups, group);
611
 
                                                attribs = g_list_prepend (attribs, attrib);
612
 
                                                values = g_list_prepend (values, value);
613
 
                                        }
614
 
                                        else
615
 
                                        {
616
 
                                                if (group) xmlFree (group);
617
 
                                                if (attrib) xmlFree (attrib);
618
 
                                                if (value) xmlFree (value);
619
 
                                                parse_error = TRUE;
620
 
                                                g_warning ("XML parse error: group, attribute and value should be defined in require");
621
 
                                                break;
622
 
                                        }
623
 
                                }
624
 
 
625
 
                                if (!parse_error)
626
 
                                {
627
 
                                        if (g_list_length (groups) == 0)
628
 
                                        {
629
 
                                                parse_error = TRUE;
630
 
                                                g_warning ("XML Error: No attributes to match given");
631
 
                                        }
632
 
                                        else
633
 
                                        {
634
 
                                                GList *plugin_descs;
635
 
                                                
636
 
                                                plugin_descs =
637
 
                                                        anjuta_plugin_manager_list_query (profile->priv->plugin_manager,
638
 
                                                                                                                          groups,
639
 
                                                                                                                          attribs,
640
 
                                                                                                                          values);
641
 
                                                if (plugin_descs)
642
 
                                                {
643
 
                                                        descs_list = g_list_prepend (descs_list, plugin_descs);
644
 
                                                }
645
 
                                                else if (mandatory)
646
 
                                                {
647
 
                                                        not_found_names = g_list_prepend (not_found_names, g_strdup ((const gchar *)name));
648
 
                                                        not_found_urls = g_list_prepend (not_found_urls, g_strdup ((const gchar *)url));
649
 
                                                }
650
 
                                        }
651
 
                                }
652
 
                                g_list_foreach (groups, (GFunc)xmlFree, NULL);
653
 
                                g_list_foreach (attribs, (GFunc)xmlFree, NULL);
654
 
                                g_list_foreach (values, (GFunc)xmlFree, NULL);
655
 
                                g_list_free (groups);
656
 
                                g_list_free (attribs);
657
 
                                g_list_free (values);
658
 
                                xmlFree (name);
659
 
                                xmlFree (url);
660
 
                        }
 
688
                        return xml_doc;
661
689
                }
662
690
                xmlFreeDoc(xml_doc);
663
691
        }
 
692
        set_parse_error (error, file);
 
693
 
 
694
        return NULL;
 
695
}
 
696
 
 
697
static GList *
 
698
parse_set (xmlNodePtr xml_node, GFile *file, GError **error)
 
699
{
 
700
        GList *config = NULL;
 
701
        gboolean parse_error = FALSE;
 
702
        xmlNodePtr xml_require_node;
 
703
 
 
704
        /* Read attribute conditions */
 
705
        for (xml_require_node = xml_node->xmlChildrenNode;
 
706
             xml_require_node;
 
707
             xml_require_node = xml_require_node->next)
 
708
        {
 
709
                xmlChar *group;
 
710
                xmlChar *attrib;
 
711
                xmlChar *value;
 
712
 
 
713
                if (!xml_require_node->name ||
 
714
                    !xmlStrEqual (xml_require_node->name,
 
715
                                  (const xmlChar*)"set"))
 
716
                {
 
717
                        continue;
 
718
                }
 
719
                group = xmlGetProp (xml_require_node,
 
720
                                    (const xmlChar *)"group");
 
721
                attrib = xmlGetProp(xml_require_node,
 
722
                                    (const xmlChar *)"attribute");
 
723
                value = xmlGetProp(xml_require_node,
 
724
                                   (const xmlChar *)"value");
 
725
 
 
726
                if (group && attrib && value)
 
727
                {
 
728
                        GString *str;
 
729
 
 
730
                        str = g_string_new ((const gchar *)group);
 
731
                        g_string_append_c (str, '\0');
 
732
                        g_string_append (str, (const gchar *)attrib);
 
733
                        g_string_append_c (str, '\0');
 
734
                        g_string_append (str, (const gchar *)value);
 
735
 
 
736
                        config = g_list_prepend (config, g_string_free (str, FALSE));
 
737
                }
 
738
                else
 
739
                {
 
740
                        parse_error = TRUE;
 
741
                        g_warning ("XML parse error: group, attribute and value should be defined in set");
 
742
                }
 
743
                if (group) xmlFree (group);
 
744
                if (attrib) xmlFree (attrib);
 
745
                if (value) xmlFree (value);
 
746
                if (parse_error) break;
 
747
        }
 
748
 
 
749
        if (parse_error)
 
750
        {
 
751
                set_parse_error (error, file);
 
752
        }
 
753
 
 
754
        return g_list_reverse (config);
 
755
}
 
756
 
 
757
 
 
758
static GList *
 
759
parse_requires (xmlNodePtr xml_node, AnjutaPluginManager *plugin_manager, GFile *file, GError **error)
 
760
{
 
761
        GList *plugin_handles = NULL;
 
762
        GList *groups = NULL;
 
763
        GList *attribs = NULL;
 
764
        GList *values = NULL;
 
765
        gboolean parse_error = FALSE;
 
766
        xmlNodePtr xml_require_node;
 
767
 
 
768
        /* Read attribute conditions */
 
769
        for (xml_require_node = xml_node->xmlChildrenNode;
 
770
             xml_require_node;
 
771
             xml_require_node = xml_require_node->next)
 
772
        {
 
773
                xmlChar *group;
 
774
                xmlChar *attrib;
 
775
                xmlChar *value;
 
776
 
 
777
                if (!xml_require_node->name ||
 
778
                    !xmlStrEqual (xml_require_node->name,
 
779
                                  (const xmlChar*)"require"))
 
780
                {
 
781
                        continue;
 
782
                }
 
783
                group = xmlGetProp (xml_require_node,
 
784
                                    (const xmlChar *)"group");
 
785
                attrib = xmlGetProp(xml_require_node,
 
786
                                    (const xmlChar *)"attribute");
 
787
                value = xmlGetProp(xml_require_node,
 
788
                                   (const xmlChar *)"value");
 
789
 
 
790
                if (group && attrib && value)
 
791
                {
 
792
                        groups = g_list_prepend (groups, group);
 
793
                        attribs = g_list_prepend (attribs, attrib);
 
794
                        values = g_list_prepend (values, value);
 
795
                }
 
796
                else
 
797
                {
 
798
                        if (group) xmlFree (group);
 
799
                        if (attrib) xmlFree (attrib);
 
800
                        if (value) xmlFree (value);
 
801
                        parse_error = TRUE;
 
802
                        g_warning ("XML parse error: group, attribute and value should be defined in require");
 
803
                        break;
 
804
                }
 
805
        }
664
806
        
665
807
        if (parse_error)
666
808
        {
667
 
                /* Error during parsing */
668
 
                gchar *uri = g_file_get_uri (file);
669
 
 
670
 
                g_set_error (error, ANJUTA_PROFILE_ERROR,
671
 
                                         ANJUTA_PROFILE_ERROR_URI_READ_FAILED,
672
 
                                         _("Failed to read '%s': XML parse error. "
673
 
                                           "Invalid or corrupted Anjuta plugins profile."),
674
 
                                        uri);
675
 
                g_free (uri);
 
809
                set_parse_error (error, file);
 
810
        }
 
811
        else
 
812
        {
 
813
                if (g_list_length (groups) == 0)
 
814
                {
 
815
                        parse_error = TRUE;
 
816
                        g_warning ("XML Error: No attributes to match given");
 
817
                }
 
818
                else
 
819
                {
 
820
                        plugin_handles =
 
821
                                anjuta_plugin_manager_list_query (plugin_manager,
 
822
                                                                  groups,
 
823
                                                                  attribs,
 
824
                                                                  values);
 
825
                }
 
826
        }
 
827
        g_list_free_full (groups, (GDestroyNotify)xmlFree);
 
828
        g_list_free_full (attribs, (GDestroyNotify)xmlFree);
 
829
        g_list_free_full (values, (GDestroyNotify)xmlFree);
 
830
 
 
831
 
 
832
        return plugin_handles;
 
833
}
 
834
 
 
835
/* Read filter */
 
836
static GList*
 
837
parse_filter (GList **set_list, xmlNodePtr xml_root, AnjutaPluginManager *plugin_manager, GFile *file, GError **error)
 
838
{
 
839
        xmlNodePtr xml_node;
 
840
        GError *parse_error = NULL;
 
841
        GList *handles_list = NULL;
 
842
 
 
843
        for (xml_node = xml_root->xmlChildrenNode; xml_node; xml_node = xml_node->next)
 
844
        {
 
845
                GList *plugin_handles = NULL;
 
846
                GList *set;
 
847
 
 
848
                if (!xml_node->name ||
 
849
                        !xmlStrEqual (xml_node->name, (const xmlChar*)"filter"))
 
850
                {
 
851
                        continue;
 
852
                }
 
853
 
 
854
                /* Get all plugins fullfiling filter requirements */
 
855
                plugin_handles = parse_requires (xml_node, plugin_manager, file, &parse_error);
 
856
                if (parse_error != NULL)
 
857
                {
 
858
                        g_propagate_error (error, parse_error);
 
859
                        break;
 
860
                }
 
861
                handles_list = g_list_prepend (handles_list, plugin_handles);
 
862
 
 
863
                set = parse_set (xml_node, file, &parse_error);
 
864
                if (parse_error != NULL)
 
865
                {
 
866
                        g_propagate_error (error, parse_error);
 
867
                        break;
 
868
                }
 
869
                *set_list = g_list_prepend (*set_list, set);
 
870
        }
 
871
 
 
872
        return handles_list;
 
873
}
 
874
 
 
875
/* Read plugins, return a list of plugin list */
 
876
static GList *
 
877
parse_plugins (GList **set_list, xmlNodePtr xml_root, AnjutaPluginManager *plugin_manager, GFile *file, GError **error)
 
878
{
 
879
        xmlNodePtr xml_node;
 
880
        GError *parse_error = NULL;
 
881
        GList *handles_list = NULL;
 
882
        GList *not_found_names = NULL;
 
883
        GList *not_found_urls = NULL;
 
884
 
 
885
        /* Read plugin list */
 
886
        for (xml_node = xml_root->xmlChildrenNode; xml_node; xml_node = xml_node->next)
 
887
        {
 
888
                xmlChar *name, *url, *mandatory_text;
 
889
                gboolean mandatory;
 
890
                GList *plugin_handles = NULL;
 
891
 
 
892
                if (!xml_node->name ||
 
893
                    !xmlStrEqual (xml_node->name, (const xmlChar*)"plugin"))
 
894
                {
 
895
                        continue;
 
896
                }
 
897
 
 
898
                name = xmlGetProp (xml_node, (const xmlChar*)"name");
 
899
                url = xmlGetProp (xml_node, (const xmlChar*)"url");
676
900
                
677
 
                g_list_foreach (descs_list, (GFunc)g_list_free, NULL);
678
 
                g_list_free (descs_list);
679
 
                descs_list = NULL;
 
901
                /* Ensure that both name is given */
 
902
                if (!name)
 
903
                {
 
904
                        g_warning ("XML error: Plugin name should be present in plugin tag");
 
905
                        set_parse_error (&parse_error, file);
 
906
                        break;
 
907
                }
 
908
                if (!url)
 
909
                        url = xmlCharStrdup ("http://anjuta.org/plugins/");
 
910
 
 
911
                /* Check if the plugin is mandatory */
 
912
                mandatory_text = xmlGetProp (xml_node, (const xmlChar*)"mandatory");
 
913
                mandatory = mandatory_text && (xmlStrcasecmp (mandatory_text, (const xmlChar *)"yes") == 0);
 
914
                xmlFree(mandatory_text);
 
915
 
 
916
                plugin_handles = parse_requires (xml_node, plugin_manager, file, &parse_error);
 
917
                if (parse_error != NULL) break;
 
918
                if (plugin_handles)
 
919
                {
 
920
                        GList *set = parse_set (xml_node, file, &parse_error);
 
921
                        if (parse_error != NULL) break;
 
922
 
 
923
                        handles_list = g_list_prepend (handles_list, plugin_handles);
 
924
                        *set_list = g_list_prepend (*set_list, set);
 
925
                }
 
926
                else if (mandatory)
 
927
                {
 
928
                        not_found_names = g_list_prepend (not_found_names, g_strdup ((const gchar *)name));
 
929
                        not_found_urls = g_list_prepend (not_found_urls, g_strdup ((const gchar *)url));
 
930
                }
 
931
        }
 
932
 
 
933
        if (parse_error != NULL)
 
934
        {
 
935
                g_propagate_error (error, parse_error);
 
936
                g_list_free_full (handles_list, (GDestroyNotify)g_list_free);
 
937
                handles_list = NULL;
680
938
        }
681
939
        else if (not_found_names)
682
940
        {
686
944
                */      
687
945
                GList *node_name, *node_url;
688
946
                GString *mesg = g_string_new ("");
689
 
                gchar *uri = g_file_get_uri (file);
690
947
                        
691
948
                not_found_names = g_list_reverse (not_found_names);
692
949
                not_found_urls = g_list_reverse (not_found_urls);
703
960
                        node_url = g_list_next (node_url);
704
961
                }
705
962
                g_set_error (error, ANJUTA_PROFILE_ERROR,
706
 
                                         ANJUTA_PROFILE_ERROR_URI_READ_FAILED,
707
 
                                         _("Failed to read '%s': Following mandatory plugins are missing:\n%s"),
708
 
                                         uri, mesg->str);
709
 
                g_free (uri);
 
963
                                         ANJUTA_PROFILE_ERROR_PLUGIN_MISSING,
 
964
                                         _("Failed to read '%s': Following mandatory plugins are missing"),
 
965
                                         mesg->str);
710
966
                g_string_free (mesg, TRUE);
 
967
 
 
968
                g_list_foreach (not_found_names, (GFunc)g_free, NULL);
 
969
                g_list_free (not_found_names);
 
970
                g_list_foreach (not_found_urls, (GFunc)g_free, NULL);
 
971
                g_list_free (not_found_urls);
 
972
 
 
973
                g_list_free_full (handles_list, (GDestroyNotify)g_list_free);
 
974
                handles_list = NULL;
 
975
        }
 
976
 
 
977
        return handles_list;
 
978
}
 
979
 
 
980
static gboolean
 
981
anjuta_profile_read_xml (AnjutaProfile *profile,
 
982
                         GError **error)
 
983
{
 
984
        AnjutaProfilePriv *priv;
 
985
        AnjutaProfileXml *xml;
 
986
        xmlNodePtr xml_root;
 
987
        GError *parse_error = NULL;
 
988
        GList *disable_list;
 
989
        GHashTable *disable_hash;
 
990
        gboolean filter = FALSE;
 
991
 
 
992
        /* Check if there are new XML files */
 
993
        priv = profile->priv;
 
994
        if (priv->xml == NULL) return TRUE;
 
995
 
 
996
        /* Read all xml file */
 
997
        for (xml = priv->xml; xml != NULL; xml = xml->next)
 
998
        {
 
999
                xml->doc = load_profile_from_xml (xml->file, &parse_error);
 
1000
                if (parse_error != NULL)
 
1001
                {
 
1002
                        g_propagate_error (error, parse_error);
 
1003
 
 
1004
                        return FALSE;
 
1005
                }
 
1006
        }
 
1007
 
 
1008
        /* Get all plugins to load */
 
1009
        for (xml = priv->xml; xml != NULL; xml = xml->next)
 
1010
        {
 
1011
                GList *handles_list;
 
1012
                GList *plugin_list;
 
1013
                GList *set_list = NULL;
711
1014
                
712
 
                g_list_foreach (descs_list, (GFunc)g_list_free, NULL);
713
 
                g_list_free (descs_list);
714
 
                descs_list = NULL;
715
 
        }
716
 
        g_list_foreach (not_found_names, (GFunc)g_free, NULL);
717
 
        g_list_free (not_found_names);
718
 
        g_list_foreach (not_found_urls, (GFunc)g_free, NULL);
719
 
        g_list_free (not_found_urls);
720
 
 
721
 
        return descs_list;
 
1015
                /* Parse plugin in xml file */
 
1016
                xml_root = xmlDocGetRootElement(xml->doc);
 
1017
                handles_list = parse_plugins (&set_list, xml_root, priv->plugin_manager, xml->file, &parse_error);
 
1018
                if (parse_error != NULL) break;
 
1019
 
 
1020
                anjuta_profile_configure_plugins (profile, handles_list, set_list);
 
1021
 
 
1022
                plugin_list = anjuta_profile_select_plugins (profile, handles_list);
 
1023
                g_list_foreach (handles_list, (GFunc)g_list_free, NULL);
 
1024
                g_list_free (handles_list);
 
1025
                for (; plugin_list != NULL; plugin_list = g_list_delete_link (plugin_list, plugin_list))
 
1026
                {
 
1027
                        g_hash_table_add (priv->plugins_to_load, plugin_list->data);
 
1028
                        if (xml->exclude_from_sync) g_hash_table_add (priv->plugins_to_exclude_from_sync, plugin_list->data);
 
1029
                }
 
1030
        }
 
1031
 
 
1032
        /* Get all disable plugins */
 
1033
        if (priv->plugins_to_disable == NULL)
 
1034
        {
 
1035
                disable_list = anjuta_plugin_manager_list_query (priv->plugin_manager, NULL, NULL, NULL);
 
1036
        }
 
1037
        else
 
1038
        {
 
1039
                disable_list = priv->plugins_to_disable;
 
1040
        }
 
1041
        disable_hash = g_hash_table_new (g_direct_hash, g_direct_equal);
 
1042
        for (; disable_list != NULL; disable_list = g_list_delete_link (disable_list, disable_list))
 
1043
        {
 
1044
                g_hash_table_add (disable_hash, disable_list->data);
 
1045
        }
 
1046
        for (xml = priv->xml; xml != NULL; xml = xml->next)
 
1047
        {
 
1048
                GList *handles_list;
 
1049
                GList *plugin_list;
 
1050
                GList *set_list = NULL;
 
1051
 
 
1052
                /* Parse filter in xml file */
 
1053
                xml_root = xmlDocGetRootElement(xml->doc);
 
1054
                handles_list = parse_filter (&set_list, xml_root, priv->plugin_manager, xml->file, &parse_error);
 
1055
                if (parse_error != NULL) break;
 
1056
 
 
1057
                anjuta_profile_configure_plugins (profile, handles_list, set_list);
 
1058
 
 
1059
                filter = filter || (handles_list != NULL);
 
1060
                for (plugin_list = g_list_first (handles_list); plugin_list != NULL; plugin_list = g_list_next (plugin_list))
 
1061
                {
 
1062
                        GList *node;
 
1063
                        for (node = g_list_first ((GList *)plugin_list->data); node != NULL; node = g_list_next (node))
 
1064
                        {
 
1065
                                g_hash_table_remove (disable_hash, node->data);
 
1066
                        }
 
1067
                }
 
1068
                g_list_foreach (handles_list, (GFunc)g_list_free, NULL);
 
1069
                g_list_free (handles_list);
 
1070
        }
 
1071
        if (filter)
 
1072
        {
 
1073
                /* Filter some plugins */
 
1074
                priv->plugins_to_disable = g_hash_table_get_keys (disable_hash);
 
1075
                anjuta_plugin_manager_set_disable_plugins (priv->plugin_manager, priv->plugins_to_disable, TRUE);
 
1076
        }
 
1077
        else
 
1078
        {
 
1079
                /* No filter, keep all plugins */
 
1080
                priv->plugins_to_disable = NULL;
 
1081
        }
 
1082
        g_hash_table_destroy (disable_hash);
 
1083
        if (parse_error != NULL) return FALSE;
 
1084
 
 
1085
 
 
1086
        /* Remove xml object */
 
1087
        while (priv->xml != NULL)
 
1088
        {
 
1089
                AnjutaProfileXml *next;
 
1090
 
 
1091
                next = priv->xml->next;
 
1092
                g_object_unref (priv->xml->file);
 
1093
                xmlFreeDoc(priv->xml->doc);
 
1094
                g_free (priv->xml);
 
1095
                priv->xml = next;
 
1096
        }
 
1097
 
 
1098
        if (parse_error != NULL) g_propagate_error (error, parse_error);
 
1099
 
 
1100
        return parse_error == NULL;
722
1101
}
723
1102
 
 
1103
 
 
1104
 
 
1105
/* Public functions
 
1106
 *---------------------------------------------------------------------------*/
 
1107
 
724
1108
/**
725
1109
 * anjuta_profile_add_plugins_from_xml:
726
1110
 * @profile: a #AnjutaProfile object.
727
1111
 * @profile_xml_file: xml file containing plugin list.
728
 
 * @exclude_from_sync: TRUE if these plugins shouldn't be saved in user session.
 
1112
 * @exclude_from_sync: %TRUE if these plugins shouldn't be saved in user session.
729
1113
 * @error: error propagation and reporting.
730
1114
 * 
731
1115
 * Add all plugins inscribed in the xml file into the profile plugin list.
732
1116
 *
733
 
 * Return value: TRUE on success, FALSE otherwise.
 
1117
 * Return value: %TRUE on success, %FALSE otherwise.
734
1118
 */
735
1119
gboolean
736
1120
anjuta_profile_add_plugins_from_xml (AnjutaProfile *profile,
739
1123
                                                                         GError **error)
740
1124
{
741
1125
        AnjutaProfilePriv *priv;
742
 
        GList *descs_list = NULL;
 
1126
        AnjutaProfileXml *xml;
 
1127
        AnjutaProfileXml **last;
743
1128
        
744
1129
        g_return_val_if_fail (ANJUTA_IS_PROFILE (profile), FALSE);
745
1130
        
746
1131
        priv = profile->priv;
747
 
        descs_list = anjuta_profile_read_plugins_from_xml (profile, profile_xml_file, error);
748
 
        
749
 
        if (descs_list)
750
 
        {
751
 
                GList *selected_plugins = NULL;
752
 
                GList *node;
753
 
                
754
 
                /* Now everything okay. Select the plugins */
755
 
                descs_list = g_list_reverse (descs_list);
756
 
                selected_plugins =
757
 
                        anjuta_profile_select_plugins (profile, descs_list);
758
 
                g_list_foreach (descs_list, (GFunc)g_list_free, NULL);
759
 
                g_list_free (descs_list);
760
 
                
761
 
                node = selected_plugins;
762
 
                while (node)
763
 
                {
764
 
                        if (exclude_from_sync)
765
 
                        {
766
 
                                g_hash_table_insert (priv->plugins_to_exclude_from_sync,
767
 
                                                                         node->data, node->data);
768
 
                        }
769
 
                        
770
 
                        /* Insure no duplicate plugins are added */
771
 
                        if (g_hash_table_lookup (priv->plugins_hash, node->data) == NULL)
772
 
                        {
773
 
                                priv->plugins = g_list_append (priv->plugins, node->data);
774
 
                                g_hash_table_insert (priv->plugins_hash,
775
 
                                                                         node->data, node->data);
776
 
                        }
777
 
                        node = g_list_next (node);
778
 
                }
779
 
                g_list_free (selected_plugins);
780
 
        }
781
 
        
782
 
        return descs_list != NULL;
 
1132
 
 
1133
        /* Just save the file name, the xml wil be loaded later after unloading the
 
1134
         * previous profile if needed */
 
1135
 
 
1136
        xml = g_new (AnjutaProfileXml, 1);
 
1137
        xml->file = g_object_ref (profile_xml_file);
 
1138
        xml->doc = NULL;
 
1139
        xml->exclude_from_sync = exclude_from_sync;
 
1140
        xml->next = NULL;
 
1141
        for (last = &(priv->xml); *last != NULL; last = &((*last)->next));
 
1142
        *last = xml;
 
1143
 
 
1144
        return TRUE;
783
1145
}
784
1146
 
785
1147
/**
788
1150
 * 
789
1151
 * Return a string in xml format containing the list of saved plugins.
790
1152
 *
791
 
 * Return value: a newly-allocated string that must be freed with g_free().
 
1153
 * Return value: (transfer full): a newly-allocated string that must be freed with g_free().
792
1154
 */
793
1155
static gchar*
794
1156
anjuta_profile_to_xml (AnjutaProfile *profile)
801
1163
        priv = profile->priv;
802
1164
        
803
1165
        str = g_string_new ("<?xml version=\"1.0\"?>\n<anjuta>\n");
804
 
        for (node = priv->plugins; node != NULL; node = g_list_next (node))
 
1166
        for (node = g_hash_table_get_keys (priv->plugins_to_load); node != NULL; node = g_list_delete_link (node, node))
805
1167
        {
 
1168
                AnjutaPluginHandle *handle;
806
1169
                AnjutaPluginDescription *desc;
807
1170
                gboolean user_activatable = TRUE;
808
1171
                gchar *name = NULL, *plugin_id = NULL;
812
1175
                        /* Do not save plugin in the exclude list */
813
1176
                        continue;
814
1177
                }
815
 
                        
816
 
                desc = (AnjutaPluginDescription *)node->data;
 
1178
                handle = (AnjutaPluginHandle *)node->data;
 
1179
                desc = anjuta_plugin_handle_get_description(handle);
817
1180
                if (anjuta_plugin_description_get_boolean (desc, "Anjuta Plugin",
818
1181
                                                                                                  "UserActivatable", &user_activatable)
819
1182
                                && !user_activatable)
882
1245
 * 
883
1246
 * Save the current plugins list in the xml file set with anjuta_profile_set_sync_file().
884
1247
 *
885
 
 * Return value: TRUE on success, FALSE otherwise.
 
1248
 * Return value: %TRUE on success, %FALSE otherwise.
886
1249
 */
887
1250
gboolean
888
1251
anjuta_profile_sync (AnjutaProfile *profile, GError **error)
920
1283
        
921
1284
        return ok;
922
1285
}
 
1286
 
 
1287
/**
 
1288
 * anjuta_profile_load:
 
1289
 * @profile: a #AnjutaProfile object.
 
1290
 * @error: error propagation and reporting.
 
1291
 *
 
1292
 * Load the profile
 
1293
 *
 
1294
 * Return value: TRUE on success, FALSE otherwise.
 
1295
 */
 
1296
gboolean
 
1297
anjuta_profile_load (AnjutaProfile *profile, GError **error)
 
1298
{
 
1299
        AnjutaProfilePriv *priv;
 
1300
        GList *active_plugins, *node;
 
1301
        GHashTable *active_hash;
 
1302
 
 
1303
        /* Read XML file if needed */
 
1304
        if (!anjuta_profile_read_xml (profile, error)) return FALSE;
 
1305
        priv = profile->priv;
 
1306
 
 
1307
        /* Deactivate plugins that are already active, but are not requested to be
 
1308
         * active */
 
1309
        active_plugins = anjuta_plugin_manager_get_active_plugins (priv->plugin_manager);
 
1310
        for (node = active_plugins; node != NULL; node = g_list_next (node))
 
1311
        {
 
1312
                AnjutaPluginHandle *handle = (AnjutaPluginHandle *)node->data;
 
1313
 
 
1314
                if (anjuta_plugin_handle_get_can_unload (handle) &&
 
1315
                    !g_hash_table_lookup (priv->plugins_to_load, handle))
 
1316
                {
 
1317
                        anjuta_plugin_manager_unload_plugin_by_handle (priv->plugin_manager,
 
1318
                                                                       handle);
 
1319
                }
 
1320
        }
 
1321
 
 
1322
        /* Prepare active plugins hash */
 
1323
        active_hash = g_hash_table_new (g_direct_hash, g_direct_equal);
 
1324
        for (node = active_plugins; node != NULL; node = g_list_next (node))
 
1325
        {
 
1326
                g_hash_table_add (active_hash, node->data);
 
1327
        }
 
1328
        g_list_free (active_plugins);
 
1329
 
 
1330
        /* Prepare the plugins to activate */
 
1331
        active_plugins = g_hash_table_get_keys (priv->plugins_to_load);
 
1332
        for (node = active_plugins; node != NULL;)
 
1333
        {
 
1334
                AnjutaPluginHandle *handle = (AnjutaPluginHandle *)node->data;
 
1335
                GList *next = g_list_next (node);
 
1336
 
 
1337
                if (g_hash_table_lookup (active_hash, handle) != NULL)
 
1338
                {
 
1339
                        active_plugins = g_list_delete_link (active_plugins, node);
 
1340
                }
 
1341
                node = next;
 
1342
        }
 
1343
        g_hash_table_destroy (active_hash);
 
1344
 
 
1345
        /* For system profile, marks its plugin to keep them activated */
 
1346
        if (strcmp (priv->name, ANJUTA_SYSTEM_PROFILE_NAME) == 0)
 
1347
        {
 
1348
                for (node = g_list_first (active_plugins); node != NULL; node = g_list_next (node))
 
1349
                {
 
1350
                        anjuta_plugin_handle_set_can_unload (ANJUTA_PLUGIN_HANDLE (node->data), FALSE);
 
1351
                }
 
1352
        }
 
1353
 
 
1354
        /* Now activate the plugins */
 
1355
        if (active_plugins != NULL)
 
1356
        {
 
1357
                anjuta_plugin_manager_activate_plugins (priv->plugin_manager,
 
1358
                                                        active_plugins);
 
1359
                g_list_free (active_plugins);
 
1360
        }
 
1361
 
 
1362
        /* Enable profile synchronization */
 
1363
        g_signal_connect (priv->plugin_manager, "plugin-activated",
 
1364
                          G_CALLBACK (on_plugin_activated), profile);
 
1365
        g_signal_connect (priv->plugin_manager, "plugin-deactivated",
 
1366
                          G_CALLBACK (on_plugin_deactivated), profile);
 
1367
 
 
1368
        g_signal_emit_by_name (profile, "scoped");
 
1369
 
 
1370
 
 
1371
        return TRUE;
 
1372
}
 
1373
 
 
1374
/**
 
1375
 * anjuta_profile_load:
 
1376
 * @profile: a #AnjutaProfile object.
 
1377
 * @error: error propagation and reporting.
 
1378
 *
 
1379
 * Unload the profile
 
1380
 *
 
1381
 * Return value: TRUE on success, FALSE otherwise.
 
1382
 */
 
1383
gboolean
 
1384
anjuta_profile_unload (AnjutaProfile *profile, GError **error)
 
1385
{
 
1386
        AnjutaProfilePriv *priv;
 
1387
 
 
1388
        /* Disable profile synchronization while the profile is being activated */
 
1389
        priv = profile->priv;
 
1390
        g_signal_handlers_disconnect_by_func (priv->plugin_manager,
 
1391
                                              G_CALLBACK (on_plugin_activated),
 
1392
                                              profile);
 
1393
        g_signal_handlers_disconnect_by_func (priv->plugin_manager,
 
1394
                                              G_CALLBACK (on_plugin_deactivated),
 
1395
                                              profile);
 
1396
 
 
1397
        /* Do not unload system profile */
 
1398
        if (strcmp (priv->name, ANJUTA_SYSTEM_PROFILE_NAME) == 0) return TRUE;
 
1399
 
 
1400
        /* Remove profile configuration */
 
1401
        anjuta_profile_unconfigure_plugins (profile);
 
1402
 
 
1403
        /* Re-enable disabled plugins */
 
1404
        anjuta_plugin_manager_set_disable_plugins (priv->plugin_manager, priv->plugins_to_disable, FALSE);
 
1405
 
 
1406
        /* Emit pre-change for the last profile */
 
1407
        if (profile)
 
1408
        {
 
1409
                g_signal_emit_by_name (profile, "descoped");
 
1410
        }
 
1411
 
 
1412
        return TRUE;
 
1413
}