1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
3 * anjuta-plugin-manager.c
4 * Copyright (C) Naba Kumar <naba@gnome.org>
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
22 * SECTION:anjuta-plugin-manager
23 * @short_description: Plugins management and activation
24 * @see_also: #AnjutaPlugin, #AnjutaProfileManager
25 * @stability: Unstable
26 * @include: libanjuta/anjuta-plugin-manager.h
30 #include <sys/types.h>
33 #include <libgnomevfs/gnome-vfs.h>
35 #include <libanjuta/anjuta-plugin-manager.h>
36 #include <libanjuta/anjuta-marshal.h>
37 #include <libanjuta/anjuta-debug.h>
38 #include <libanjuta/anjuta-plugin-handle.h>
39 #include <libanjuta/anjuta-plugin.h>
40 #include <libanjuta/anjuta-c-plugin-factory.h>
41 #include <libanjuta/interfaces/ianjuta-plugin-factory.h>
51 PROP_AVAILABLE_PLUGINS
,
52 PROP_ACTIVATED_PLUGINS
67 struct _AnjutaPluginManagerPriv
72 GList
*available_plugins
;
74 /* Indexes => plugin handles */
75 GHashTable
*plugins_by_interfaces
;
76 GHashTable
*plugins_by_name
;
77 GHashTable
*plugins_by_description
;
79 /* Plugins that are currently activated */
80 GHashTable
*activated_plugins
;
82 /* Plugins that have been previously loaded but current deactivated */
83 GHashTable
*plugins_cache
;
85 /* Remember plugin selection */
86 GHashTable
*remember_plugins
;
89 /* Available plugins page treeview */
99 /* Remembered plugins page treeview */
107 /* Plugin class types */
109 static AnjutaCPluginFactory
*anjuta_plugin_factory
= NULL
;
111 static GObjectClass
* parent_class
= NULL
;
112 static guint plugin_manager_signals
[LAST_SIGNAL
] = { 0 };
114 static GHashTable
* plugin_set_update (AnjutaPluginManager
*plugin_manager
,
115 AnjutaPluginHandle
* selected_plugin
,
118 static IAnjutaPluginFactory
* get_plugin_factory (AnjutaPluginManager
*plugin_manager
,
119 const gchar
*language
, GError
**error
);
122 anjuta_plugin_manager_error_quark (void)
124 static GQuark quark
= 0;
127 quark
= g_quark_from_static_string ("anjuta-plugin-manager-quark");
132 /** Dependency Resolution **/
135 collect_cycle (AnjutaPluginManager
*plugin_manager
,
136 AnjutaPluginHandle
*base_plugin
, AnjutaPluginHandle
*cur_plugin
,
139 AnjutaPluginManagerPriv
*priv
;
142 priv
= plugin_manager
->priv
;
144 for (l
= anjuta_plugin_handle_get_dependency_names (cur_plugin
);
145 l
!= NULL
; l
= l
->next
)
147 AnjutaPluginHandle
*dep
= g_hash_table_lookup (priv
->plugins_by_name
,
151 if (dep
== base_plugin
)
153 *cycle
= g_list_prepend (NULL
, dep
);
154 /* DEBUG_PRINT ("%s ", anjuta_plugin_handle_get_name (dep)); */
159 if (collect_cycle (plugin_manager
, base_plugin
, dep
, cycle
))
161 *cycle
= g_list_prepend (*cycle
, dep
);
162 /* DEBUG_PRINT ("%s ", anjuta_plugin_handle_get_name (dep)); */
172 add_dependency (AnjutaPluginHandle
*dependent
, AnjutaPluginHandle
*dependency
)
174 g_hash_table_insert (anjuta_plugin_handle_get_dependents (dependency
),
175 dependent
, dependency
);
176 g_hash_table_insert (anjuta_plugin_handle_get_dependencies (dependent
),
177 dependency
, dependent
);
181 child_dep_foreach_cb (gpointer key
, gpointer value
, gpointer user_data
)
183 add_dependency (ANJUTA_PLUGIN_HANDLE (user_data
),
184 ANJUTA_PLUGIN_HANDLE (key
));
187 /* Resolves dependencies for a single module recursively. Shortcuts if
188 * the module has already been resolved. Returns a list representing
189 * any cycles found, or NULL if no cycles are found. If a cycle is found,
190 * the graph is left unresolved.
193 resolve_for_module (AnjutaPluginManager
*plugin_manager
,
194 AnjutaPluginHandle
*plugin
, int pass
)
196 AnjutaPluginManagerPriv
*priv
;
200 priv
= plugin_manager
->priv
;
202 if (anjuta_plugin_handle_get_checked (plugin
))
207 if (anjuta_plugin_handle_get_resolve_pass (plugin
) == pass
)
210 g_warning ("cycle found: %s on pass %d",
211 anjuta_plugin_handle_get_name (plugin
),
212 anjuta_plugin_handle_get_resolve_pass (plugin
));
213 collect_cycle (plugin_manager
, plugin
, plugin
, &cycle
);
217 if (anjuta_plugin_handle_get_resolve_pass (plugin
) != -1)
222 anjuta_plugin_handle_set_can_load (plugin
, TRUE
);
223 anjuta_plugin_handle_set_resolve_pass (plugin
, pass
);
225 for (l
= anjuta_plugin_handle_get_dependency_names (plugin
);
226 l
!= NULL
; l
= l
->next
)
229 AnjutaPluginHandle
*child
=
230 g_hash_table_lookup (priv
->plugins_by_name
, dep
);
233 ret
= resolve_for_module (plugin_manager
, child
, pass
);
239 /* Add the dependency's dense dependency list
240 * to the current module's dense dependency list */
241 g_hash_table_foreach (anjuta_plugin_handle_get_dependencies (child
),
242 child_dep_foreach_cb
, plugin
);
243 add_dependency (plugin
, child
);
245 /* If the child can't load due to dependency problems,
246 * the current module can't either */
247 anjuta_plugin_handle_set_can_load (plugin
,
248 anjuta_plugin_handle_get_can_load (child
));
250 g_warning ("Dependency %s not found.\n", dep
);
251 anjuta_plugin_handle_set_can_load (plugin
, FALSE
);
255 anjuta_plugin_handle_set_checked (plugin
, TRUE
);
260 /* Clean up the results of a resolving run */
262 unresolve_dependencies (AnjutaPluginManager
*plugin_manager
)
264 AnjutaPluginManagerPriv
*priv
;
267 priv
= plugin_manager
->priv
;
269 for (l
= priv
->available_plugins
; l
!= NULL
; l
= l
->next
)
271 AnjutaPluginHandle
*plugin
= l
->data
;
272 anjuta_plugin_handle_unresolve_dependencies (plugin
);
279 prune_modules (AnjutaPluginManager
*plugin_manager
, GList
*modules
)
281 AnjutaPluginManagerPriv
*priv
;
284 priv
= plugin_manager
->priv
;
286 for (l
= modules
; l
!= NULL
; l
= l
->next
) {
287 AnjutaPluginHandle
*plugin
= l
->data
;
289 g_hash_table_remove (priv
->plugins_by_name
,
290 anjuta_plugin_handle_get_id (plugin
));
291 priv
->available_plugins
= g_list_remove (priv
->available_plugins
, plugin
);
296 dependency_compare (AnjutaPluginHandle
*plugin_a
,
297 AnjutaPluginHandle
*plugin_b
)
299 int a
= g_hash_table_size (anjuta_plugin_handle_get_dependencies (plugin_a
));
300 int b
= g_hash_table_size (anjuta_plugin_handle_get_dependencies (plugin_b
));
305 /* Resolves the dependencies of the priv->available_plugins list. When this
306 * function is complete, the following will be true:
308 * 1) The dependencies and dependents hash tables of the modules will
311 * 2) Cycles in the graph will be removed.
313 * 3) Modules which cannot be loaded due to failed dependencies will
316 * 4) priv->available_plugins will be sorted such that no module depends on a
319 * If a cycle in the graph is found, it is pruned from the tree and
320 * returned as a list stored in the cycles list.
323 resolve_dependencies (AnjutaPluginManager
*plugin_manager
, GList
**cycles
)
325 AnjutaPluginManagerPriv
*priv
;
329 priv
= plugin_manager
->priv
;
332 /* Try resolving dependencies. If there is a cycle, prune the
333 * cycle and try to resolve again */
338 for (l
= priv
->available_plugins
; l
!= NULL
&& !cycle
; l
= l
->next
) {
339 cycle
= resolve_for_module (plugin_manager
, l
->data
, pass
++);
343 *cycles
= g_list_prepend (*cycles
, cycle
);
344 prune_modules (plugin_manager
, cycle
);
345 unresolve_dependencies (plugin_manager
);
349 /* Now that there is a fully resolved dependency tree, sort
350 * priv->available_plugins to create a valid load order */
351 priv
->available_plugins
= g_list_sort (priv
->available_plugins
,
352 (GCompareFunc
)dependency_compare
);
355 /* Plugins loading */
358 str_has_suffix (const char *haystack
, const char *needle
)
362 if (needle
== NULL
) {
365 if (haystack
== NULL
) {
366 return needle
[0] == '\0';
369 /* Eat one character at a time. */
370 h
= haystack
+ strlen(haystack
);
371 n
= needle
+ strlen(needle
);
379 } while (*--h
== *--n
);
384 load_plugin (AnjutaPluginManager
*plugin_manager
,
385 const gchar
*plugin_desc_path
)
387 AnjutaPluginManagerPriv
*priv
;
388 AnjutaPluginHandle
*plugin_handle
;
390 g_return_if_fail (ANJUTA_IS_PLUGIN_MANAGER (plugin_manager
));
391 priv
= plugin_manager
->priv
;
393 plugin_handle
= anjuta_plugin_handle_new (plugin_desc_path
);
396 if (g_hash_table_lookup (priv
->plugins_by_name
,
397 anjuta_plugin_handle_get_id (plugin_handle
)))
399 g_object_unref (plugin_handle
);
404 /* Available plugin */
405 priv
->available_plugins
= g_list_prepend (priv
->available_plugins
,
408 g_hash_table_insert (priv
->plugins_by_name
,
409 (gchar
*)anjuta_plugin_handle_get_id (plugin_handle
),
412 /* Index by description */
413 g_hash_table_insert (priv
->plugins_by_description
,
414 anjuta_plugin_handle_get_description (plugin_handle
),
417 /* Index by interfaces exported by this plugin */
418 node
= anjuta_plugin_handle_get_interfaces (plugin_handle
);
427 objs
= (GList
*)g_hash_table_lookup (priv
->plugins_by_interfaces
, iface
);
433 if (obj_node
->data
== plugin_handle
)
438 obj_node
= g_list_next (obj_node
);
442 g_hash_table_steal (priv
->plugins_by_interfaces
, iface
);
443 objs
= g_list_prepend (objs
, plugin_handle
);
444 g_hash_table_insert (priv
->plugins_by_interfaces
, iface
, objs
);
446 node
= g_list_next (node
);
454 load_plugins_from_directory (AnjutaPluginManager
* plugin_manager
,
455 const gchar
*dirname
)
458 struct dirent
*entry
;
460 dir
= opendir (dirname
);
467 for (entry
= readdir (dir
); entry
!= NULL
; entry
= readdir (dir
))
469 if (str_has_suffix (entry
->d_name
, ".plugin"))
472 pathname
= g_strdup_printf ("%s/%s", dirname
, entry
->d_name
);
473 load_plugin (plugin_manager
,pathname
);
480 /* Plugin activation and deactivation */
483 on_plugin_activated (AnjutaPlugin
*plugin_object
, AnjutaPluginHandle
*plugin
)
485 AnjutaPluginManager
*plugin_manager
;
486 AnjutaPluginManagerPriv
*priv
;
488 /* FIXME: Pass plugin_manager directly in signal arguments */
489 plugin_manager
= anjuta_shell_get_plugin_manager (plugin_object
->shell
, NULL
);
491 g_return_if_fail(plugin_manager
!= NULL
);
493 priv
= plugin_manager
->priv
;
495 g_hash_table_insert (priv
->activated_plugins
, plugin
,
496 G_OBJECT (plugin_object
));
497 if (g_hash_table_lookup (priv
->plugins_cache
, plugin
))
498 g_hash_table_remove (priv
->plugins_cache
, plugin
);
500 g_signal_emit_by_name (plugin_manager
, "plugin-activated",
501 anjuta_plugin_handle_get_description (plugin
),
506 on_plugin_deactivated (AnjutaPlugin
*plugin_object
, AnjutaPluginHandle
*plugin
)
508 AnjutaPluginManager
*plugin_manager
;
509 AnjutaPluginManagerPriv
*priv
;
511 /* FIXME: Pass plugin_manager directly in signal arguments */
512 plugin_manager
= anjuta_shell_get_plugin_manager (plugin_object
->shell
, NULL
);
514 g_return_if_fail (plugin_manager
!= NULL
);
516 priv
= plugin_manager
->priv
;
518 g_hash_table_insert (priv
->plugins_cache
, plugin
, G_OBJECT (plugin_object
));
519 g_hash_table_remove (priv
->activated_plugins
, plugin
);
521 g_signal_emit_by_name (plugin_manager
, "plugin-deactivated",
522 anjuta_plugin_handle_get_description (plugin
),
527 activate_plugin (AnjutaPluginManager
*plugin_manager
,
528 AnjutaPluginHandle
*handle
, GError
**error
)
530 AnjutaPluginManagerPriv
*priv
;
531 IAnjutaPluginFactory
* factory
;
532 AnjutaPlugin
*plugin
;
533 const gchar
*plugin_id
;
534 const gchar
*language
;
537 priv
= plugin_manager
->priv
;
539 plugin_id
= anjuta_plugin_handle_get_id (handle
);
541 resident
= anjuta_plugin_handle_get_resident (handle
);
542 language
= anjuta_plugin_handle_get_language (handle
);
544 factory
= get_plugin_factory (plugin_manager
, language
, error
);
545 if (factory
== NULL
) return NULL
;
547 plugin
= ianjuta_plugin_factory_new_plugin (factory
, handle
, ANJUTA_SHELL (priv
->shell
), error
);
553 g_signal_connect (plugin
, "activated",
554 G_CALLBACK (on_plugin_activated
), handle
);
555 g_signal_connect (plugin
, "deactivated",
556 G_CALLBACK (on_plugin_deactivated
), handle
);
562 g_hashtable_foreach_true (gpointer key
, gpointer value
, gpointer user_data
)
568 anjuta_plugin_manager_unload_all_plugins (AnjutaPluginManager
*plugin_manager
)
570 AnjutaPluginManagerPriv
*priv
;
572 priv
= plugin_manager
->priv
;
573 if (g_hash_table_size (priv
->activated_plugins
) > 0 ||
574 g_hash_table_size (priv
->plugins_cache
) > 0)
576 priv
->available_plugins
= g_list_reverse (priv
->available_plugins
);
577 if (g_hash_table_size (priv
->activated_plugins
) > 0)
580 node
= priv
->available_plugins
;
583 AnjutaPluginHandle
*selected_plugin
= node
->data
;
584 if (g_hash_table_lookup (priv
->activated_plugins
, selected_plugin
))
586 plugin_set_update (plugin_manager
, selected_plugin
, FALSE
);
587 /* DEBUG_PRINT ("Unloading plugin: %s",
588 anjuta_plugin_handle_get_id (selected_plugin));
591 node
= g_list_next (node
);
593 g_hash_table_foreach_remove (priv
->activated_plugins
,
594 g_hashtable_foreach_true
, NULL
);
596 if (g_hash_table_size (priv
->plugins_cache
) > 0)
599 node
= priv
->available_plugins
;
603 AnjutaPluginHandle
*selected_plugin
= node
->data
;
605 plugin_obj
= g_hash_table_lookup (priv
->plugins_cache
,
609 /* DEBUG_PRINT ("Destroying plugin: %s",
610 anjuta_plugin_handle_get_id (selected_plugin));
612 g_object_unref (plugin_obj
);
614 node
= g_list_next (node
);
616 g_hash_table_foreach_remove (priv
->plugins_cache
,
617 g_hashtable_foreach_true
, NULL
);
619 priv
->available_plugins
= g_list_reverse (priv
->available_plugins
);
624 should_unload (GHashTable
*activated_plugins
, AnjutaPluginHandle
*plugin_to_unload
,
625 AnjutaPluginHandle
*plugin
)
627 GObject
*plugin_obj
= g_hash_table_lookup (activated_plugins
, plugin
);
632 if (plugin_to_unload
== plugin
)
636 GPOINTER_TO_INT (g_hash_table_lookup (anjuta_plugin_handle_get_dependents (plugin
),
642 should_load (GHashTable
*activated_plugins
, AnjutaPluginHandle
*plugin_to_load
,
643 AnjutaPluginHandle
*plugin
)
645 GObject
*plugin_obj
= g_hash_table_lookup (activated_plugins
, plugin
);
650 if (plugin_to_load
== plugin
)
651 return anjuta_plugin_handle_get_can_load (plugin
);
653 gboolean dependency
=
654 GPOINTER_TO_INT (g_hash_table_lookup (anjuta_plugin_handle_get_dependencies (plugin_to_load
),
656 return (dependency
&& anjuta_plugin_handle_get_can_load (plugin
));
659 static AnjutaPluginHandle
*
660 plugin_for_iter (GtkListStore
*store
, GtkTreeIter
*iter
)
662 AnjutaPluginHandle
*plugin
;
664 gtk_tree_model_get (GTK_TREE_MODEL (store
), iter
, COL_PLUGIN
, &plugin
, -1);
669 update_enabled (GtkTreeModel
*model
, GHashTable
*activated_plugins
)
673 if (gtk_tree_model_get_iter_first (model
, &iter
)) {
675 AnjutaPluginHandle
*plugin
;
679 plugin
= plugin_for_iter(GTK_LIST_STORE(model
), &iter
);
680 plugin_obj
= g_hash_table_lookup (activated_plugins
, plugin
);
681 installed
= (plugin_obj
!= NULL
) ? TRUE
: FALSE
;
682 gtk_tree_model_get (model
, &iter
, COL_PLUGIN
, &plugin
, -1);
683 gtk_list_store_set (GTK_LIST_STORE (model
), &iter
,
684 COL_ENABLED
, installed
, -1);
685 } while (gtk_tree_model_iter_next (model
, &iter
));
690 plugin_set_update (AnjutaPluginManager
*plugin_manager
,
691 AnjutaPluginHandle
* selected_plugin
,
694 AnjutaPluginManagerPriv
*priv
;
698 priv
= plugin_manager
->priv
;
699 plugin_obj
= g_hash_table_lookup (priv
->activated_plugins
, selected_plugin
);
701 if (plugin_obj
&& load
)
703 g_warning ("Trying to install already installed plugin '%s'",
704 anjuta_plugin_handle_get_name (selected_plugin
));
705 return priv
->activated_plugins
;
707 if (!plugin_obj
&& !load
)
709 g_warning ("Trying to uninstall a not installed plugin '%s'",
710 anjuta_plugin_handle_get_name (selected_plugin
));
711 return priv
->activated_plugins
;
715 anjuta_status_busy_push (priv
->status
);
719 /* reverse priv->available_plugins when unloading, so that plugins are
720 * unloaded in the right order */
721 priv
->available_plugins
= g_list_reverse (priv
->available_plugins
);
723 for (l
= priv
->available_plugins
; l
!= NULL
; l
= l
->next
)
725 AnjutaPluginHandle
*plugin
= l
->data
;
726 if (should_unload (priv
->activated_plugins
, selected_plugin
, plugin
))
728 /* FIXME: Unload the class and sharedlib if possible */
729 AnjutaPlugin
*anjuta_plugin
= ANJUTA_PLUGIN (plugin_obj
);
730 if (!anjuta_plugin_deactivate (ANJUTA_PLUGIN (anjuta_plugin
)))
732 anjuta_util_dialog_info (GTK_WINDOW (priv
->shell
),
733 "Plugin '%s' do not want to be deactivated",
734 anjuta_plugin_handle_get_name (plugin
));
738 priv
->available_plugins
= g_list_reverse (priv
->available_plugins
);
742 for (l
= priv
->available_plugins
; l
!= NULL
; l
= l
->next
)
744 AnjutaPluginHandle
*plugin
= l
->data
;
745 if (should_load (priv
->activated_plugins
, selected_plugin
, plugin
))
747 AnjutaPlugin
*plugin_obj
;
748 GError
*error
= NULL
;
749 plugin_obj
= g_hash_table_lookup (priv
->plugins_cache
, plugin
);
752 plugin_obj
= activate_plugin (plugin_manager
, plugin
,
758 anjuta_plugin_activate (ANJUTA_PLUGIN (plugin_obj
));
764 gchar
* message
= g_strdup_printf (_("Could not load %s\n"
765 "This usually means that your installation is corrupted. The "
766 "error message leading to this was:\n%s"),
767 anjuta_plugin_handle_get_name (selected_plugin
),
769 anjuta_util_dialog_error (GTK_WINDOW(plugin_manager
->priv
->shell
),
771 g_error_free (error
);
779 anjuta_status_busy_pop (priv
->status
);
780 return priv
->activated_plugins
;
784 plugin_toggled (GtkCellRendererToggle
*cell
, char *path_str
, gpointer data
)
786 AnjutaPluginManager
*plugin_manager
;
787 AnjutaPluginManagerPriv
*priv
;
788 GtkListStore
*store
= GTK_LIST_STORE (data
);
791 AnjutaPluginHandle
*plugin
;
793 GHashTable
*activated_plugins
;
795 path
= gtk_tree_path_new_from_string (path_str
);
797 plugin_manager
= g_object_get_data (G_OBJECT (store
), "plugin-manager");
798 priv
= plugin_manager
->priv
;
800 gtk_tree_model_get_iter (GTK_TREE_MODEL (store
), &iter
, path
);
801 gtk_tree_model_get (GTK_TREE_MODEL (store
), &iter
,
802 COL_ENABLED
, &enabled
,
808 activated_plugins
= plugin_set_update (plugin_manager
, plugin
, enabled
);
809 update_enabled (GTK_TREE_MODEL (store
), activated_plugins
);
810 gtk_tree_path_free (path
);
815 selection_changed (GtkTreeSelection
*selection
, GtkListStore
*store
)
819 if (gtk_tree_selection_get_selected (selection
, NULL
,
821 GtkTextBuffer
*buffer
;
823 GtkWidget
*txt
= g_object_get_data (G_OBJECT (store
),
826 GtkWidget
*image
= g_object_get_data (G_OBJECT (store
),
828 AnjutaPluginHandle
*plugin
= plugin_for_iter (store
, &iter
);
830 buffer
= gtk_text_view_get_buffer (GTK_TEXT_VIEW (txt
));
831 gtk_text_buffer_set_text (buffer
, plugin
->about
, -1);
833 if (plugin
->icon_path
) {
834 gtk_image_set_from_file (GTK_IMAGE (image
),
836 gtk_widget_show (GTK_WIDGET (image
));
838 gtk_widget_hide (GTK_WIDGET (image
));
845 create_plugin_tree (void)
849 GtkCellRenderer
*renderer
;
850 GtkTreeViewColumn
*column
;
852 store
= gtk_list_store_new (N_COLS
,
858 tree
= gtk_tree_view_new_with_model (GTK_TREE_MODEL (store
));
860 renderer
= gtk_cell_renderer_toggle_new ();
861 g_signal_connect (G_OBJECT (renderer
), "toggled",
862 G_CALLBACK (plugin_toggled
), store
);
863 column
= gtk_tree_view_column_new_with_attributes (_("Load"),
870 gtk_tree_view_append_column (GTK_TREE_VIEW (tree
), column
);
871 gtk_tree_view_column_set_sizing (column
,
872 GTK_TREE_VIEW_COLUMN_AUTOSIZE
);
874 column
= gtk_tree_view_column_new ();
875 renderer
= gtk_cell_renderer_pixbuf_new ();
876 gtk_tree_view_column_pack_start (column
, renderer
, FALSE
);
877 gtk_tree_view_column_add_attribute (column
, renderer
, "pixbuf",
879 renderer
= gtk_cell_renderer_text_new ();
880 gtk_tree_view_column_pack_start (column
, renderer
, FALSE
);
881 gtk_tree_view_column_add_attribute (column
, renderer
, "markup",
883 gtk_tree_view_column_set_sizing (column
,
884 GTK_TREE_VIEW_COLUMN_AUTOSIZE
);
885 gtk_tree_view_column_set_title (column
, _("Available Plugins"));
886 gtk_tree_view_append_column (GTK_TREE_VIEW (tree
), column
);
887 gtk_tree_view_set_expander_column (GTK_TREE_VIEW (tree
), column
);
889 g_object_unref (store
);
893 /* Sort function for plugins */
895 sort_plugins(gconstpointer a
, gconstpointer b
)
897 g_return_val_if_fail (a
!= NULL
, 0);
898 g_return_val_if_fail (b
!= NULL
, 0);
900 AnjutaPluginHandle
* plugin_a
= ANJUTA_PLUGIN_HANDLE (a
);
901 AnjutaPluginHandle
* plugin_b
= ANJUTA_PLUGIN_HANDLE (b
);
903 return strcmp (anjuta_plugin_handle_get_name (plugin_a
),
904 anjuta_plugin_handle_get_name (plugin_b
));
907 /* If show_all == FALSE, show only user activatable plugins
908 * If show_all == TRUE, show all plugins
911 populate_plugin_model (AnjutaPluginManager
*plugin_manager
,
913 GHashTable
*plugins_to_show
,
914 GHashTable
*activated_plugins
,
917 AnjutaPluginManagerPriv
*priv
;
920 priv
= plugin_manager
->priv
;
921 gtk_list_store_clear (store
);
923 priv
->available_plugins
= g_list_sort (priv
->available_plugins
, sort_plugins
);
925 for (l
= priv
->available_plugins
; l
!= NULL
; l
= l
->next
)
927 AnjutaPluginHandle
*plugin
= l
->data
;
929 /* If plugins to show is NULL, show all available plugins */
930 if (plugins_to_show
== NULL
||
931 g_hash_table_lookup (plugins_to_show
, plugin
))
934 gboolean enable
= FALSE
;
935 if (g_hash_table_lookup (activated_plugins
, plugin
))
938 if (anjuta_plugin_handle_get_name (plugin
) &&
939 anjuta_plugin_handle_get_description (plugin
) &&
940 (anjuta_plugin_handle_get_user_activatable (plugin
) ||
946 text
= g_markup_printf_escaped ("<span size=\"larger\" weight=\"bold\">%s</span>\n%s",
947 anjuta_plugin_handle_get_name (plugin
),
948 anjuta_plugin_handle_get_about (plugin
));
950 gtk_list_store_append (store
, &iter
);
951 gtk_list_store_set (store
, &iter
,
953 anjuta_plugin_handle_get_user_activatable (plugin
),
958 if (anjuta_plugin_handle_get_icon_path (plugin
))
961 icon
= gdk_pixbuf_new_from_file_at_size (anjuta_plugin_handle_get_icon_path (plugin
),
964 gtk_list_store_set (store
, &iter
,
966 gdk_pixbuf_unref (icon
);
976 create_remembered_plugins_tree (void)
980 GtkCellRenderer
*renderer
;
981 GtkTreeViewColumn
*column
;
983 store
= gtk_list_store_new (N_REM_COLS
, GDK_TYPE_PIXBUF
, G_TYPE_STRING
,
985 tree
= gtk_tree_view_new_with_model (GTK_TREE_MODEL (store
));
987 column
= gtk_tree_view_column_new ();
988 renderer
= gtk_cell_renderer_pixbuf_new ();
989 gtk_tree_view_column_pack_start (column
, renderer
, FALSE
);
990 gtk_tree_view_column_add_attribute (column
, renderer
, "pixbuf",
992 renderer
= gtk_cell_renderer_text_new ();
993 gtk_tree_view_column_pack_start (column
, renderer
, FALSE
);
994 gtk_tree_view_column_add_attribute (column
, renderer
, "markup",
996 gtk_tree_view_column_set_sizing (column
,
997 GTK_TREE_VIEW_COLUMN_AUTOSIZE
);
998 gtk_tree_view_column_set_title (column
, _("Preferred plugins"));
999 gtk_tree_view_append_column (GTK_TREE_VIEW (tree
), column
);
1000 gtk_tree_view_set_expander_column (GTK_TREE_VIEW (tree
), column
);
1002 g_object_unref (store
);
1007 foreach_remembered_plugin (gpointer key
, gpointer value
, gpointer user_data
)
1009 AnjutaPluginDescription
*desc
= (AnjutaPluginDescription
*) value
;
1010 GtkListStore
*store
= GTK_LIST_STORE (user_data
);
1011 AnjutaPluginManager
*manager
= g_object_get_data (G_OBJECT (store
),
1013 AnjutaPluginHandle
*plugin
=
1014 g_hash_table_lookup (manager
->priv
->plugins_by_description
, desc
);
1015 g_return_if_fail (plugin
!= NULL
);
1017 if (anjuta_plugin_handle_get_name (plugin
) &&
1018 anjuta_plugin_handle_get_description (plugin
))
1023 text
= g_markup_printf_escaped ("<span size=\"larger\" weight=\"bold\">%s</span>\n%s",
1024 anjuta_plugin_handle_get_name (plugin
),
1025 anjuta_plugin_handle_get_about (plugin
));
1027 gtk_list_store_append (store
, &iter
);
1028 gtk_list_store_set (store
, &iter
,
1030 COL_REM_PLUGIN_KEY
, key
,
1032 if (anjuta_plugin_handle_get_icon_path (plugin
))
1035 icon
= gdk_pixbuf_new_from_file_at_size (anjuta_plugin_handle_get_icon_path (plugin
),
1038 gtk_list_store_set (store
, &iter
,
1039 COL_REM_ICON
, icon
, -1);
1040 gdk_pixbuf_unref (icon
);
1048 populate_remembered_plugins_model (AnjutaPluginManager
*plugin_manager
,
1049 GtkListStore
*store
)
1051 AnjutaPluginManagerPriv
*priv
= plugin_manager
->priv
;
1052 gtk_list_store_clear (store
);
1053 g_hash_table_foreach (priv
->remember_plugins
, foreach_remembered_plugin
,
1058 on_show_all_plugins_toggled (GtkToggleButton
*button
, GtkListStore
*store
)
1060 AnjutaPluginManager
*plugin_manager
;
1062 plugin_manager
= g_object_get_data (G_OBJECT (button
), "__plugin_manager");
1064 populate_plugin_model (plugin_manager
, store
, NULL
,
1065 plugin_manager
->priv
->activated_plugins
,
1066 !gtk_toggle_button_get_active (button
));
1070 on_forget_plugin_clicked (GtkWidget
*button
, GtkTreeView
*view
)
1073 GtkTreeModel
*model
;
1074 GtkTreeSelection
*selection
= gtk_tree_view_get_selection (view
);
1075 if (gtk_tree_selection_get_selected (selection
, &model
, &iter
))
1078 AnjutaPluginManager
*manager
= g_object_get_data (G_OBJECT (model
),
1080 gtk_tree_model_get (model
, &iter
, COL_REM_PLUGIN_KEY
, &plugin_key
, -1);
1081 g_hash_table_remove (manager
->priv
->remember_plugins
, plugin_key
);
1082 gtk_list_store_remove (GTK_LIST_STORE (model
), &iter
);
1083 g_free (plugin_key
);
1088 on_forget_plugin_sel_changed (GtkTreeSelection
*selection
,
1093 if (gtk_tree_selection_get_selected (selection
, NULL
, &iter
))
1094 gtk_widget_set_sensitive (button
, TRUE
);
1096 gtk_widget_set_sensitive (button
, FALSE
);
1100 anjuta_plugin_manager_get_plugins_page (AnjutaPluginManager
*plugin_manager
)
1103 GtkWidget
*checkbutton
;
1105 GtkWidget
*scrolled
;
1106 GtkListStore
*store
;
1109 vbox
= gtk_vbox_new (FALSE
, 0);
1110 gtk_container_set_border_width (GTK_CONTAINER (vbox
), 10);
1112 checkbutton
= gtk_check_button_new_with_label (_("Only show user activatable plugins"));
1113 gtk_container_set_border_width (GTK_CONTAINER (checkbutton
), 10);
1114 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (checkbutton
), TRUE
);
1115 gtk_box_pack_start (GTK_BOX (vbox
), checkbutton
, FALSE
, FALSE
, 0);
1117 scrolled
= gtk_scrolled_window_new (NULL
, NULL
);
1118 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled
),
1120 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled
),
1121 GTK_POLICY_AUTOMATIC
,
1122 GTK_POLICY_AUTOMATIC
);
1123 gtk_box_pack_start (GTK_BOX (vbox
), scrolled
, TRUE
, TRUE
, 0);
1125 tree
= create_plugin_tree ();
1126 store
= GTK_LIST_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (tree
)));
1128 populate_plugin_model (plugin_manager
, store
, NULL
,
1129 plugin_manager
->priv
->activated_plugins
, FALSE
);
1131 gtk_container_add (GTK_CONTAINER (scrolled
), tree
);
1132 g_object_set_data (G_OBJECT (store
), "plugin-manager", plugin_manager
);
1135 g_object_set_data (G_OBJECT (checkbutton
), "__plugin_manager", plugin_manager
);
1136 g_signal_connect (G_OBJECT (checkbutton
), "toggled",
1137 G_CALLBACK (on_show_all_plugins_toggled
),
1139 gtk_widget_show_all (vbox
);
1144 anjuta_plugin_manager_get_remembered_plugins_page (AnjutaPluginManager
*plugin_manager
)
1148 GtkWidget
*scrolled
;
1149 GtkListStore
*store
;
1151 GtkWidget
*display_label
;
1152 GtkWidget
*forget_button
;
1153 GtkTreeSelection
*selection
;
1155 /* Remembered plugin */
1156 vbox
= gtk_vbox_new (FALSE
, 10);
1157 gtk_container_set_border_width (GTK_CONTAINER (vbox
), 10);
1159 display_label
= gtk_label_new (_("These are the plugins selected by you "
1160 "when Anjuta prompted to choose one of "
1161 "many suitable plugins. Removing the "
1162 "preferred plugin will let Anjuta prompt "
1163 "you again to choose different plugin."));
1164 gtk_label_set_line_wrap (GTK_LABEL (display_label
), TRUE
);
1165 gtk_box_pack_start (GTK_BOX (vbox
), display_label
, FALSE
, FALSE
, 0);
1167 scrolled
= gtk_scrolled_window_new (NULL
, NULL
);
1168 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled
),
1170 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled
),
1171 GTK_POLICY_AUTOMATIC
,
1172 GTK_POLICY_AUTOMATIC
);
1173 gtk_box_pack_start (GTK_BOX (vbox
), scrolled
, TRUE
, TRUE
, 0);
1175 tree
= create_remembered_plugins_tree ();
1176 store
= GTK_LIST_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (tree
)));
1178 gtk_container_add (GTK_CONTAINER (scrolled
), tree
);
1179 g_object_set_data (G_OBJECT (store
), "plugin-manager", plugin_manager
);
1180 populate_remembered_plugins_model (plugin_manager
, store
);
1182 hbox
= gtk_hbox_new (FALSE
, 0);
1183 gtk_container_set_border_width (GTK_CONTAINER (hbox
), 5);
1184 gtk_box_pack_start (GTK_BOX (vbox
), hbox
, FALSE
, FALSE
, 0);
1185 forget_button
= gtk_button_new_with_label ("Forget selected plugin");
1186 gtk_widget_set_sensitive (forget_button
, FALSE
);
1187 gtk_box_pack_end (GTK_BOX (hbox
), forget_button
, FALSE
, FALSE
, 0);
1189 g_signal_connect (forget_button
, "clicked",
1190 G_CALLBACK (on_forget_plugin_clicked
),
1192 selection
= gtk_tree_view_get_selection (GTK_TREE_VIEW (tree
));
1193 g_signal_connect (selection
, "changed",
1194 G_CALLBACK (on_forget_plugin_sel_changed
),
1196 gtk_widget_show_all (vbox
);
1201 property_to_list (const char *value
)
1207 split_str
= g_strsplit (value
, ",", -1);
1208 for (p
= split_str
; *p
!= NULL
; p
++) {
1209 l
= g_list_prepend (l
, g_strdup (g_strstrip (*p
)));
1211 g_strfreev (split_str
);
1215 static IAnjutaPluginFactory
*
1216 get_plugin_factory (AnjutaPluginManager
*plugin_manager
,
1217 const gchar
*language
,
1220 AnjutaPluginManagerPriv
*priv
;
1221 AnjutaPluginHandle
*plugin
;
1222 GList
*loader_plugins
, *node
;
1223 GList
*valid_plugins
;
1224 GObject
*obj
= NULL
;
1226 g_return_val_if_fail (ANJUTA_IS_PLUGIN_MANAGER (plugin_manager
), G_TYPE_INVALID
);
1229 if ((language
== NULL
) || (g_ascii_strcasecmp (language
, "C") == 0))
1231 /* Support of C plugin is built-in */
1232 return IANJUTA_PLUGIN_FACTORY (anjuta_plugin_factory
);
1235 priv
= plugin_manager
->priv
;
1238 /* Find all plugins implementing the IAnjutaPluginLoader interface. */
1239 loader_plugins
= g_hash_table_lookup (priv
->plugins_by_interfaces
, "IAnjutaPluginLoader");
1241 /* Create a list of loader supporting this language */
1242 node
= loader_plugins
;
1243 valid_plugins
= NULL
;
1246 AnjutaPluginDescription
*desc
;
1252 plugin
= node
->data
;
1254 desc
= anjuta_plugin_handle_get_description (plugin
);
1255 if (anjuta_plugin_description_get_string (desc
, "Plugin Loader", "SupportedLanguage", &val
))
1259 vals
= property_to_list (val
);
1268 if (!found
&& (g_ascii_strcasecmp (l_node
->data
, language
) == 0))
1272 g_free (l_node
->data
);
1273 l_node
= g_list_next (l_node
);
1279 valid_plugins
= g_list_prepend (valid_plugins
, plugin
);
1282 node
= g_list_next (node
);
1285 /* Find the first installed plugin from the valid plugins */
1286 node
= valid_plugins
;
1289 plugin
= node
->data
;
1290 obj
= g_hash_table_lookup (priv
->activated_plugins
, plugin
);
1292 node
= g_list_next (node
);
1295 /* If no plugin is installed yet, do something */
1296 if ((obj
== NULL
) && valid_plugins
&& g_list_length (valid_plugins
) == 1)
1298 /* If there is just one plugin, consider it selected */
1299 plugin
= valid_plugins
->data
;
1301 /* Install and return it */
1302 plugin_set_update (plugin_manager
, plugin
, TRUE
);
1303 obj
= g_hash_table_lookup (priv
->activated_plugins
, plugin
);
1305 else if ((obj
== NULL
) && valid_plugins
)
1307 /* Prompt the user to select one of these plugins */
1309 GList
*descs
= NULL
;
1310 node
= valid_plugins
;
1313 plugin
= node
->data
;
1314 descs
= g_list_prepend (descs
, anjuta_plugin_handle_get_description (plugin
));
1315 node
= g_list_next (node
);
1317 descs
= g_list_reverse (descs
);
1318 obj
= anjuta_plugin_manager_select_and_activate (plugin_manager
,
1319 _("Select a plugin"),
1320 _("Please select a plugin to activate"),
1322 g_list_free (descs
);
1324 g_list_free (valid_plugins
);
1328 return IANJUTA_PLUGIN_FACTORY (obj
);
1331 /* No plugin implementing this interface found */
1332 g_set_error (error
, ANJUTA_PLUGIN_MANAGER_ERROR
,
1333 ANJUTA_PLUGIN_MANAGER_MISSING_FACTORY
,
1334 _("No plugin able to load other plugins in %s"), language
);
1340 * anjuta_plugin_manager_get_plugin:
1341 * @plugin_manager: A #AnjutaPluginManager object
1342 * @iface_name: The interface implemented by the object to be found
1344 * Searches the currently available plugins to find the one which
1345 * implements the given interface as primary interface and returns it. If
1346 * the plugin is not yet loaded, it will be loaded and activated.
1347 * The returned object is garanteed to be an implementor of the
1348 * interface (as exported by the plugin metafile). It only searches
1349 * from the pool of plugin objects loaded in this shell and can only search
1350 * by primary interface. If there are more objects implementing this primary
1351 * interface, user might be prompted to select one from them (and might give
1352 * the option to use it as default for future queries). A typical usage of this
1356 * anjuta_plugin_manager_get_plugin (plugin_manager, "IAnjutaDocumentManager", error);
1358 * Notice that this function takes the interface name string as string, unlike
1359 * anjuta_plugins_get_interface() which takes the type directly.
1361 * Return value: The plugin object (subclass of #AnjutaPlugin) which implements
1362 * the given interface. See #AnjutaPlugin for more detail on interfaces
1363 * implemented by plugins.
1366 anjuta_plugin_manager_get_plugin (AnjutaPluginManager
*plugin_manager
,
1367 const gchar
*iface_name
)
1369 AnjutaPluginManagerPriv
*priv
;
1370 AnjutaPluginHandle
*plugin
;
1371 GList
*valid_plugins
, *node
;
1373 g_return_val_if_fail (ANJUTA_IS_PLUGIN_MANAGER (plugin_manager
), NULL
);
1374 g_return_val_if_fail (iface_name
!= NULL
, NULL
);
1376 priv
= plugin_manager
->priv
;
1379 /* Find all plugins implementing this (primary) interface. */
1380 valid_plugins
= g_hash_table_lookup (priv
->plugins_by_interfaces
, iface_name
);
1382 /* Find the first installed plugin from the valid plugins */
1383 node
= valid_plugins
;
1387 plugin
= node
->data
;
1388 obj
= g_hash_table_lookup (priv
->activated_plugins
, plugin
);
1391 node
= g_list_next (node
);
1394 /* If no plugin is installed yet, do something */
1395 if (valid_plugins
&& g_list_length (valid_plugins
) == 1)
1397 /* If there is just one plugin, consider it selected */
1399 plugin
= valid_plugins
->data
;
1401 /* Install and return it */
1402 plugin_set_update (plugin_manager
, plugin
, TRUE
);
1403 obj
= g_hash_table_lookup (priv
->activated_plugins
, plugin
);
1407 else if (valid_plugins
)
1409 /* Prompt the user to select one of these plugins */
1411 GList
*descs
= NULL
;
1412 node
= valid_plugins
;
1415 plugin
= node
->data
;
1416 descs
= g_list_prepend (descs
, anjuta_plugin_handle_get_description (plugin
));
1417 node
= g_list_next (node
);
1419 descs
= g_list_reverse (descs
);
1420 obj
= anjuta_plugin_manager_select_and_activate (plugin_manager
,
1421 _("Select a plugin"),
1422 _("Please select a plugin to activate"),
1424 g_list_free (descs
);
1428 /* No plugin implementing this interface found */
1429 g_warning ("No plugin found implementing %s Interface.", iface_name
);
1434 anjuta_plugin_manager_get_plugin_by_id (AnjutaPluginManager
*plugin_manager
,
1435 const gchar
*plugin_id
)
1437 AnjutaPluginManagerPriv
*priv
;
1438 AnjutaPluginHandle
*plugin
;
1440 g_return_val_if_fail (ANJUTA_IS_PLUGIN_MANAGER (plugin_manager
), NULL
);
1441 g_return_val_if_fail (plugin_id
!= NULL
, NULL
);
1443 priv
= plugin_manager
->priv
;
1444 plugin
= g_hash_table_lookup (priv
->plugins_by_name
, plugin_id
);
1448 obj
= g_hash_table_lookup (priv
->activated_plugins
, plugin
);
1454 plugin_set_update (plugin_manager
, plugin
, TRUE
);
1455 obj
= g_hash_table_lookup (priv
->activated_plugins
, plugin
);
1459 g_warning ("No plugin found with id \"%s\".", plugin_id
);
1464 on_activated_plugins_foreach (gpointer key
, gpointer data
, gpointer user_data
)
1466 AnjutaPluginHandle
*plugin
= ANJUTA_PLUGIN_HANDLE (key
);
1467 GList
**active_plugins
= (GList
**)user_data
;
1468 *active_plugins
= g_list_prepend (*active_plugins
,
1469 anjuta_plugin_handle_get_description (plugin
));
1473 on_activated_plugin_objects_foreach (gpointer key
, gpointer data
, gpointer user_data
)
1475 GList
**active_plugins
= (GList
**)user_data
;
1476 *active_plugins
= g_list_prepend (*active_plugins
,
1481 anjuta_plugin_manager_get_active_plugins (AnjutaPluginManager
*plugin_manager
)
1483 GList
*active_plugins
= NULL
;
1485 g_return_val_if_fail (ANJUTA_IS_PLUGIN_MANAGER (plugin_manager
), NULL
);
1486 g_hash_table_foreach (plugin_manager
->priv
->activated_plugins
,
1487 on_activated_plugins_foreach
,
1489 return g_list_reverse (active_plugins
);
1493 anjuta_plugin_manager_get_active_plugin_objects (AnjutaPluginManager
*plugin_manager
)
1495 GList
*active_plugins
= NULL
;
1497 g_return_val_if_fail (ANJUTA_IS_PLUGIN_MANAGER (plugin_manager
), NULL
);
1498 g_hash_table_foreach (plugin_manager
->priv
->activated_plugins
,
1499 on_activated_plugin_objects_foreach
,
1501 return g_list_reverse (active_plugins
);
1505 anjuta_plugin_manager_unload_plugin_by_id (AnjutaPluginManager
*plugin_manager
,
1506 const gchar
*plugin_id
)
1508 AnjutaPluginManagerPriv
*priv
;
1509 AnjutaPluginHandle
*plugin
;
1511 g_return_val_if_fail (ANJUTA_IS_PLUGIN_MANAGER (plugin_manager
), FALSE
);
1512 g_return_val_if_fail (plugin_id
!= NULL
, FALSE
);
1514 priv
= plugin_manager
->priv
;
1516 plugin
= g_hash_table_lookup (priv
->plugins_by_name
, plugin_id
);
1519 plugin_set_update (plugin_manager
, plugin
, FALSE
);
1521 /* Check if the plugin has been indeed unloaded */
1522 if (!g_hash_table_lookup (priv
->activated_plugins
, plugin
))
1527 g_warning ("No plugin found with id \"%s\".", plugin_id
);
1532 find_plugin_for_object (gpointer key
, gpointer value
, gpointer data
)
1536 g_object_set_data (G_OBJECT (data
), "__plugin_plugin", key
);
1543 anjuta_plugin_manager_unload_plugin (AnjutaPluginManager
*plugin_manager
,
1544 GObject
*plugin_object
)
1546 AnjutaPluginManagerPriv
*priv
;
1547 AnjutaPluginHandle
*plugin
;
1549 g_return_val_if_fail (ANJUTA_IS_PLUGIN_MANAGER (plugin_manager
), FALSE
);
1550 g_return_val_if_fail (ANJUTA_IS_PLUGIN (plugin_object
), FALSE
);
1552 priv
= plugin_manager
->priv
;
1556 /* Find the plugin that correspond to this plugin object */
1557 g_hash_table_find (priv
->activated_plugins
, find_plugin_for_object
,
1559 plugin
= g_object_get_data (G_OBJECT (plugin_object
), "__plugin_plugin");
1563 plugin_set_update (plugin_manager
, plugin
, FALSE
);
1565 /* Check if the plugin has been indeed unloaded */
1566 if (!g_hash_table_lookup (priv
->activated_plugins
, plugin
))
1571 g_warning ("No plugin found with object \"%p\".", plugin_object
);
1576 anjuta_plugin_manager_query (AnjutaPluginManager
*plugin_manager
,
1577 const gchar
*section_name
,
1578 const gchar
*attribute_name
,
1579 const gchar
*attribute_value
,
1582 AnjutaPluginManagerPriv
*priv
;
1585 GList
*anames
= NULL
;
1586 GList
*avalues
= NULL
;
1587 const gchar
*sec
= section_name
;
1588 const gchar
*aname
= attribute_name
;
1589 const gchar
*avalue
= attribute_value
;
1590 GList
*selected_plugins
= NULL
;
1594 g_return_val_if_fail (ANJUTA_IS_PLUGIN_MANAGER (plugin_manager
), NULL
);
1596 priv
= plugin_manager
->priv
;
1597 available
= priv
->available_plugins
;
1599 if (section_name
== NULL
)
1601 /* If no query is given, select all plugins */
1604 AnjutaPluginHandle
*plugin
= available
->data
;
1605 AnjutaPluginDescription
*desc
=
1606 anjuta_plugin_handle_get_description (plugin
);
1607 selected_plugins
= g_list_prepend (selected_plugins
, desc
);
1608 available
= g_list_next (available
);
1610 return g_list_reverse (selected_plugins
);
1613 g_return_val_if_fail (section_name
!= NULL
, NULL
);
1614 g_return_val_if_fail (attribute_name
!= NULL
, NULL
);
1615 g_return_val_if_fail (attribute_value
!= NULL
, NULL
);
1617 secs
= g_list_prepend (secs
, g_strdup (section_name
));
1618 anames
= g_list_prepend (anames
, g_strdup (attribute_name
));
1619 avalues
= g_list_prepend (avalues
, g_strdup (attribute_value
));
1621 va_start (var_args
, attribute_value
);
1624 sec
= va_arg (var_args
, const gchar
*);
1627 aname
= va_arg (var_args
, const gchar
*);
1630 avalue
= va_arg (var_args
, const gchar
*);
1633 secs
= g_list_prepend (secs
, g_strdup (sec
));
1634 anames
= g_list_prepend (anames
, g_strdup (aname
));
1635 avalues
= g_list_prepend (avalues
, g_strdup (avalue
));
1642 secs
= g_list_reverse (secs
);
1643 anames
= g_list_reverse (anames
);
1644 avalues
= g_list_reverse (avalues
);
1648 GList
* s_node
= secs
;
1649 GList
* n_node
= anames
;
1650 GList
* v_node
= avalues
;
1652 gboolean satisfied
= FALSE
;
1654 AnjutaPluginHandle
*plugin
= available
->data
;
1655 AnjutaPluginDescription
*desc
=
1656 anjuta_plugin_handle_get_description (plugin
);
1663 gboolean found
= FALSE
;
1668 aname
= n_node
->data
;
1669 avalue
= v_node
->data
;
1671 if (!anjuta_plugin_description_get_string (desc
, sec
, aname
, &val
))
1677 vals
= property_to_list (val
);
1683 if (strchr(node
->data
, '*') != NULL
)
1688 const gchar
*cursor
;
1690 segments
= g_strsplit (node
->data
, "*", -1);
1694 while (*seg_ptr
!= NULL
)
1696 if (strlen (*seg_ptr
) > 0) {
1697 cursor
= strstr (cursor
, *seg_ptr
);
1701 cursor
+= strlen (*seg_ptr
);
1704 if (*seg_ptr
== NULL
)
1706 g_strfreev (segments
);
1708 else if (g_ascii_strcasecmp (node
->data
, avalue
) == 0)
1713 g_free (node
->data
);
1714 node
= g_list_next (node
);
1722 s_node
= g_list_next (s_node
);
1723 n_node
= g_list_next (n_node
);
1724 v_node
= g_list_next (v_node
);
1728 selected_plugins
= g_list_prepend (selected_plugins
, desc
);
1729 /* DEBUG_PRINT ("Satisfied, Adding %s",
1730 anjuta_plugin_handle_get_name (plugin));*/
1732 available
= g_list_next (available
);
1734 anjuta_util_glist_strings_free (secs
);
1735 anjuta_util_glist_strings_free (anames
);
1736 anjuta_util_glist_strings_free (avalues
);
1738 return g_list_reverse (selected_plugins
);
1744 PLUGIN_DESCRIPTION_COLUMN
,
1749 on_plugin_list_row_activated (GtkTreeView
*tree_view
,
1751 GtkTreeViewColumn
*column
,
1754 gtk_dialog_response (dialog
, GTK_RESPONSE_OK
);
1757 AnjutaPluginDescription
*
1758 anjuta_plugin_manager_select (AnjutaPluginManager
*plugin_manager
,
1759 gchar
*title
, gchar
*description
,
1760 GList
*plugin_descriptions
)
1762 AnjutaPluginDescription
*desc
;
1763 AnjutaPluginManagerPriv
*priv
;
1765 GtkTreeModel
*model
;
1767 GtkTreeViewColumn
*column
;
1768 GtkCellRenderer
*renderer
;
1772 GtkWidget
*remember_checkbox
;
1774 GtkTreeIter selected
;
1775 GtkTreeSelection
*selection
;
1776 GtkTreeModel
*store
;
1777 GList
*selection_ids
= NULL
;
1778 GString
*remember_key
= g_string_new ("");
1780 g_return_val_if_fail (title
!= NULL
, NULL
);
1781 g_return_val_if_fail (description
!= NULL
, NULL
);
1782 g_return_val_if_fail (plugin_descriptions
!= NULL
, NULL
);
1784 priv
= plugin_manager
->priv
;
1786 if (g_list_length (plugin_descriptions
) <= 0)
1789 dlg
= gtk_dialog_new_with_buttons (title
, GTK_WINDOW (priv
->shell
),
1790 GTK_DIALOG_DESTROY_WITH_PARENT
,
1792 GTK_RESPONSE_CANCEL
,
1793 GTK_STOCK_OK
, GTK_RESPONSE_OK
,
1795 gtk_widget_set_size_request (dlg
, 400, 300);
1796 gtk_window_set_default_size (GTK_WINDOW (dlg
), 400, 300);
1798 label
= gtk_label_new (description
);
1799 gtk_widget_show (label
);
1800 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dlg
)->vbox
), label
,
1803 sc
= gtk_scrolled_window_new (NULL
, NULL
);
1804 gtk_widget_show (sc
);
1805 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sc
),
1807 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sc
),
1808 GTK_POLICY_AUTOMATIC
,
1809 GTK_POLICY_AUTOMATIC
);
1811 gtk_box_pack_start (GTK_BOX (GTK_DIALOG(dlg
)->vbox
), sc
,
1814 model
= GTK_TREE_MODEL (gtk_list_store_new (N_COLUMNS
, GDK_TYPE_PIXBUF
,
1815 G_TYPE_STRING
, G_TYPE_POINTER
));
1816 view
= gtk_tree_view_new_with_model (model
);
1817 gtk_widget_show (view
);
1818 gtk_container_add (GTK_CONTAINER (sc
), view
);
1820 column
= gtk_tree_view_column_new ();
1821 gtk_tree_view_column_set_sizing (column
,
1822 GTK_TREE_VIEW_COLUMN_AUTOSIZE
);
1823 gtk_tree_view_column_set_title (column
, _("Available Plugins"));
1825 renderer
= gtk_cell_renderer_pixbuf_new ();
1826 gtk_tree_view_column_pack_start (column
, renderer
, FALSE
);
1827 gtk_tree_view_column_add_attribute (column
, renderer
, "pixbuf",
1830 renderer
= gtk_cell_renderer_text_new ();
1831 gtk_tree_view_column_pack_start (column
, renderer
, TRUE
);
1832 gtk_tree_view_column_add_attribute (column
, renderer
, "markup",
1835 gtk_tree_view_append_column (GTK_TREE_VIEW (view
), column
);
1836 gtk_tree_view_set_expander_column (GTK_TREE_VIEW (view
), column
);
1838 g_signal_connect (view
, "row-activated",
1839 G_CALLBACK (on_plugin_list_row_activated
),
1842 gtk_check_button_new_with_label (_("Remember this selection"));
1843 gtk_container_set_border_width (GTK_CONTAINER (remember_checkbox
), 10);
1844 gtk_widget_show (remember_checkbox
);
1845 gtk_box_pack_start (GTK_BOX (GTK_DIALOG(dlg
)->vbox
), remember_checkbox
,
1848 node
= plugin_descriptions
;
1851 GdkPixbuf
*icon_pixbuf
= NULL
;
1852 gchar
*plugin_name
= NULL
;
1853 gchar
*plugin_desc
= NULL
;
1854 gchar
*icon_filename
= NULL
;
1855 gchar
*location
= NULL
;
1857 desc
= (AnjutaPluginDescription
*)node
->data
;
1859 if (anjuta_plugin_description_get_string (desc
,
1864 gchar
*icon_path
= NULL
;
1865 icon_path
= g_strconcat (PACKAGE_PIXMAPS_DIR
"/",
1866 icon_filename
, NULL
);
1867 /* DEBUG_PRINT ("Icon: %s", icon_path); */
1869 gdk_pixbuf_new_from_file (icon_path
, NULL
);
1870 if (icon_pixbuf
== NULL
)
1872 g_warning ("Plugin pixmap not found: %s", plugin_name
);
1878 g_warning ("Plugin does not define Icon attribute");
1880 if (!anjuta_plugin_description_get_string (desc
,
1885 g_warning ("Plugin does not define Name attribute");
1887 if (!anjuta_plugin_description_get_string (desc
,
1892 g_warning ("Plugin does not define Description attribute");
1894 if (!anjuta_plugin_description_get_string (desc
,
1899 g_warning ("Plugin does not define Location attribute");
1902 if (plugin_name
&& plugin_desc
)
1907 text
= g_markup_printf_escaped ("<span size=\"larger\" weight=\"bold\">%s</span>\n%s", plugin_name
, plugin_desc
);
1909 gtk_list_store_append (GTK_LIST_STORE (model
), &iter
);
1910 gtk_list_store_set (GTK_LIST_STORE (model
), &iter
,
1911 PLUGIN_COLUMN
, text
,
1912 PLUGIN_DESCRIPTION_COLUMN
, desc
, -1);
1914 gtk_list_store_set (GTK_LIST_STORE (model
), &iter
,
1915 PIXBUF_COLUMN
, icon_pixbuf
, -1);
1916 g_object_unref (icon_pixbuf
);
1920 selection_ids
= g_list_prepend (selection_ids
, location
);
1922 node
= g_list_next (node
);
1925 /* Prepare remembering key */
1926 selection_ids
= g_list_sort (selection_ids
,
1927 (GCompareFunc
)strcmp
);
1928 node
= selection_ids
;
1931 g_string_append (remember_key
, (gchar
*)node
->data
);
1932 g_string_append (remember_key
, ",");
1933 node
= g_list_next (node
);
1935 g_list_foreach (selection_ids
, (GFunc
) g_free
, NULL
);
1936 g_list_free (selection_ids
);
1938 /* Find if the selection is remembered */
1939 desc
= g_hash_table_lookup (priv
->remember_plugins
, remember_key
->str
);
1942 g_string_free (remember_key
, TRUE
);
1943 gtk_widget_destroy (dlg
);
1948 response
= gtk_dialog_run (GTK_DIALOG (dlg
));
1951 case GTK_RESPONSE_OK
:
1952 selection
= gtk_tree_view_get_selection (GTK_TREE_VIEW (view
));
1953 if (gtk_tree_selection_get_selected (selection
, &store
,
1956 gtk_tree_model_get (model
, &selected
,
1957 PLUGIN_DESCRIPTION_COLUMN
, &desc
, -1);
1960 /* Remember selection */
1961 if (gtk_toggle_button_get_active
1962 (GTK_TOGGLE_BUTTON (remember_checkbox
)))
1964 /* DEBUG_PRINT ("Remembering selection '%s'",
1965 remember_key->str);*/
1966 g_hash_table_insert (priv
->remember_plugins
,
1967 g_strdup (remember_key
->str
), desc
);
1969 g_string_free (remember_key
, TRUE
);
1970 gtk_widget_destroy (dlg
);
1976 g_string_free (remember_key
, TRUE
);
1977 gtk_widget_destroy (dlg
);
1982 anjuta_plugin_manager_select_and_activate (AnjutaPluginManager
*plugin_manager
,
1985 GList
*plugin_descriptions
)
1987 AnjutaPluginDescription
*d
;
1989 g_return_val_if_fail (ANJUTA_IS_PLUGIN_MANAGER (plugin_manager
), NULL
);
1991 d
= anjuta_plugin_manager_select (plugin_manager
, title
, description
,
1992 plugin_descriptions
);
1995 GObject
*plugin
= NULL
;
1996 gchar
*location
= NULL
;
1998 anjuta_plugin_description_get_string (d
,
2002 g_return_val_if_fail (location
!= NULL
, NULL
);
2004 anjuta_plugin_manager_get_plugin_by_id (plugin_manager
, location
);
2011 /* Plugin manager */
2014 anjuta_plugin_manager_init (AnjutaPluginManager
*object
)
2016 object
->priv
= g_new0 (AnjutaPluginManagerPriv
, 1);
2017 object
->priv
->plugins_by_name
= g_hash_table_new (g_str_hash
, g_str_equal
);
2018 object
->priv
->plugins_by_interfaces
= g_hash_table_new_full (g_str_hash
,
2021 (GDestroyNotify
) g_list_free
);
2022 object
->priv
->plugins_by_description
= g_hash_table_new (g_direct_hash
,
2024 object
->priv
->activated_plugins
= g_hash_table_new (g_direct_hash
,
2026 object
->priv
->plugins_cache
= g_hash_table_new (g_direct_hash
,
2028 object
->priv
->remember_plugins
= g_hash_table_new_full (g_str_hash
,
2034 anjuta_plugin_manager_finalize (GObject
*object
)
2036 AnjutaPluginManagerPriv
*priv
;
2037 priv
= ANJUTA_PLUGIN_MANAGER (object
)->priv
;
2038 if (priv
->available_plugins
)
2040 /* anjuta_plugin_manager_unload_all_plugins (ANJUTA_PLUGIN_MANAGER (object)); */
2041 g_list_foreach (priv
->available_plugins
, (GFunc
)g_object_unref
, NULL
);
2042 g_list_free (priv
->available_plugins
);
2043 priv
->available_plugins
= NULL
;
2045 if (priv
->activated_plugins
)
2047 g_hash_table_destroy (priv
->activated_plugins
);
2048 priv
->activated_plugins
= NULL
;
2050 if (priv
->plugins_cache
)
2052 g_hash_table_destroy (priv
->plugins_cache
);
2053 priv
->plugins_cache
= NULL
;
2055 if (priv
->plugins_by_name
)
2057 g_hash_table_destroy (priv
->plugins_by_name
);
2058 priv
->plugins_by_name
= NULL
;
2060 if (priv
->plugins_by_description
)
2062 g_hash_table_destroy (priv
->plugins_by_description
);
2063 priv
->plugins_by_description
= NULL
;
2065 if (priv
->plugins_by_interfaces
)
2067 g_hash_table_destroy (priv
->plugins_by_interfaces
);
2068 priv
->plugins_by_interfaces
= NULL
;
2070 if (priv
->plugin_dirs
)
2072 g_list_foreach (priv
->plugin_dirs
, (GFunc
)g_free
, NULL
);
2073 g_list_free (priv
->plugin_dirs
);
2074 priv
->plugin_dirs
= NULL
;
2077 if (anjuta_c_plugin_factory
)
2079 g_object_unref (anjuta_c_plugin_factory
);
2080 anjuta_c_plugin_factory
= NULL
;
2083 G_OBJECT_CLASS (parent_class
)->finalize (object
);
2087 anjuta_plugin_manager_set_property (GObject
*object
, guint prop_id
,
2088 const GValue
*value
, GParamSpec
*pspec
)
2090 AnjutaPluginManagerPriv
*priv
;
2092 g_return_if_fail (ANJUTA_IS_PLUGIN_MANAGER (object
));
2093 priv
= ANJUTA_PLUGIN_MANAGER (object
)->priv
;
2098 priv
->status
= g_value_get_object (value
);
2101 priv
->shell
= g_value_get_object (value
);
2104 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
2110 anjuta_plugin_manager_get_property (GObject
*object
, guint prop_id
,
2111 GValue
*value
, GParamSpec
*pspec
)
2113 AnjutaPluginManagerPriv
*priv
;
2115 g_return_if_fail (ANJUTA_IS_PLUGIN_MANAGER (object
));
2116 priv
= ANJUTA_PLUGIN_MANAGER (object
)->priv
;
2121 g_value_set_object (value
, priv
->shell
);
2124 g_value_set_object (value
, priv
->status
);
2126 case PROP_AVAILABLE_PLUGINS
:
2127 g_value_set_pointer (value
, priv
->available_plugins
);
2129 case PROP_ACTIVATED_PLUGINS
:
2130 g_value_set_pointer (value
, priv
->activated_plugins
);
2133 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
2138 anjuta_plugin_manager_plugin_activated (AnjutaPluginManager
*self
,
2139 AnjutaPluginDescription
* plugin_desc
,
2142 /* TODO: Add default signal handler implementation here */
2146 anjuta_plugin_manager_plugin_deactivated (AnjutaPluginManager
*self
,
2147 AnjutaPluginDescription
* plugin_desc
,
2150 /* TODO: Add default signal handler implementation here */
2154 anjuta_plugin_manager_class_init (AnjutaPluginManagerClass
*klass
)
2156 GObjectClass
* object_class
= G_OBJECT_CLASS (klass
);
2157 parent_class
= G_OBJECT_CLASS (g_type_class_peek_parent (klass
));
2159 object_class
->finalize
= anjuta_plugin_manager_finalize
;
2160 object_class
->set_property
= anjuta_plugin_manager_set_property
;
2161 object_class
->get_property
= anjuta_plugin_manager_get_property
;
2163 klass
->plugin_activated
= anjuta_plugin_manager_plugin_activated
;
2164 klass
->plugin_deactivated
= anjuta_plugin_manager_plugin_deactivated
;
2166 g_object_class_install_property (object_class
,
2168 g_param_spec_pointer ("profiles",
2170 _("Current stack of profiles"),
2172 g_object_class_install_property (object_class
,
2173 PROP_AVAILABLE_PLUGINS
,
2174 g_param_spec_pointer ("available-plugins",
2175 _("Available plugins"),
2176 _("Currently available plugins found in plugin paths"),
2179 g_object_class_install_property (object_class
,
2180 PROP_ACTIVATED_PLUGINS
,
2181 g_param_spec_pointer ("activated-plugins",
2182 _("Activated plugins"),
2183 _("Currently activated plugins"),
2185 g_object_class_install_property (object_class
,
2187 g_param_spec_object ("shell",
2189 _("Anjuta shell for which the plugins are"),
2193 G_PARAM_CONSTRUCT
));
2194 g_object_class_install_property (object_class
,
2196 g_param_spec_object ("status",
2198 _("Anjuta status to use in loading and unloading of plugins"),
2202 G_PARAM_CONSTRUCT
));
2204 plugin_manager_signals
[PLUGIN_ACTIVATED
] =
2205 g_signal_new ("plugin-activated",
2206 G_OBJECT_CLASS_TYPE (klass
),
2208 G_STRUCT_OFFSET (AnjutaPluginManagerClass
,
2211 anjuta_cclosure_marshal_VOID__POINTER_OBJECT
,
2213 G_TYPE_POINTER
, ANJUTA_TYPE_PLUGIN
);
2215 plugin_manager_signals
[PLUGIN_DEACTIVATED
] =
2216 g_signal_new ("plugin-deactivated",
2217 G_OBJECT_CLASS_TYPE (klass
),
2219 G_STRUCT_OFFSET (AnjutaPluginManagerClass
,
2220 plugin_deactivated
),
2222 anjuta_cclosure_marshal_VOID__POINTER_OBJECT
,
2224 G_TYPE_POINTER
, ANJUTA_TYPE_PLUGIN
);
2228 anjuta_plugin_manager_get_type (void)
2230 static GType our_type
= 0;
2234 static const GTypeInfo our_info
=
2236 sizeof (AnjutaPluginManagerClass
), /* class_size */
2237 (GBaseInitFunc
) NULL
, /* base_init */
2238 (GBaseFinalizeFunc
) NULL
, /* base_finalize */
2239 (GClassInitFunc
) anjuta_plugin_manager_class_init
, /* class_init */
2240 (GClassFinalizeFunc
) NULL
, /* class_finalize */
2241 NULL
/* class_data */,
2242 sizeof (AnjutaPluginManager
), /* instance_size */
2243 0, /* n_preallocs */
2244 (GInstanceInitFunc
) anjuta_plugin_manager_init
, /* instance_init */
2245 NULL
/* value_table */
2247 our_type
= g_type_register_static (G_TYPE_OBJECT
,
2248 "AnjutaPluginManager",
2255 AnjutaPluginManager
*
2256 anjuta_plugin_manager_new (GObject
*shell
, AnjutaStatus
*status
,
2257 GList
* plugins_directories
)
2259 GObject
*manager_object
;
2260 AnjutaPluginManager
*plugin_manager
;
2261 GList
*cycles
= NULL
;
2262 const char *gnome2_path
;
2266 GList
*plugin_dirs
= NULL
;
2268 /* Initialize the anjuta plugin system */
2269 manager_object
= g_object_new (ANJUTA_TYPE_PLUGIN_MANAGER
,
2270 "shell", shell
, "status", status
, NULL
);
2271 plugin_manager
= ANJUTA_PLUGIN_MANAGER (manager_object
);
2273 if (anjuta_plugin_factory
== NULL
)
2275 anjuta_plugin_factory
= anjuta_c_plugin_factory_new ();
2278 gnome2_path
= g_getenv ("GNOME2_PATH");
2280 pathv
= g_strsplit (gnome2_path
, ":", 1);
2282 for (p
= pathv
; *p
!= NULL
; p
++) {
2283 char *path
= g_strdup (*p
);
2284 plugin_dirs
= g_list_prepend (plugin_dirs
, path
);
2289 node
= plugins_directories
;
2293 char *path
= g_strdup (node
->data
);
2294 plugin_dirs
= g_list_prepend (plugin_dirs
, path
);
2295 node
= g_list_next (node
);
2297 plugin_dirs
= g_list_reverse (plugin_dirs
);
2298 /* load_plugins (); */
2303 load_plugins_from_directory (plugin_manager
, (char*)node
->data
);
2304 node
= g_list_next (node
);
2306 resolve_dependencies (plugin_manager
, &cycles
);
2307 g_list_foreach(plugin_dirs
, (GFunc
) g_free
, NULL
);
2308 g_list_free(plugin_dirs
);
2309 return plugin_manager
;
2313 anjuta_plugin_manager_activate_plugins (AnjutaPluginManager
*plugin_manager
,
2314 GList
*plugins_to_activate
)
2316 AnjutaPluginManagerPriv
*priv
;
2317 GdkPixbuf
*icon_pixbuf
;
2320 priv
= plugin_manager
->priv
;
2322 /* Freeze shell operations */
2323 anjuta_shell_freeze (ANJUTA_SHELL (priv
->shell
), NULL
);
2324 if (plugins_to_activate
)
2326 anjuta_status_progress_add_ticks (ANJUTA_STATUS (priv
->status
),
2327 g_list_length (plugins_to_activate
));
2329 node
= plugins_to_activate
;
2332 AnjutaPluginDescription
*d
;
2334 gchar
*icon_filename
, *label
;
2335 gchar
*icon_path
= NULL
;
2341 if (anjuta_plugin_description_get_string (d
, "Anjuta Plugin",
2345 gchar
*title
, *description
;
2346 anjuta_plugin_description_get_string (d
, "Anjuta Plugin",
2349 anjuta_plugin_description_get_string (d
, "Anjuta Plugin",
2352 icon_path
= g_strconcat (PACKAGE_PIXMAPS_DIR
"/",
2353 icon_filename
, NULL
);
2354 /* DEBUG_PRINT ("Icon: %s", icon_path); */
2355 label
= g_strconcat (_("Loaded: "), title
, _("..."), NULL
);
2356 icon_pixbuf
= gdk_pixbuf_new_from_file (icon_path
, NULL
);
2358 g_warning ("Plugin does not define Icon: No such file %s",
2361 g_free (icon_filename
);
2364 if (anjuta_plugin_description_get_string (d
, "Anjuta Plugin",
2365 "Location", &plugin_id
))
2367 GObject
*plugin_obj
;
2370 anjuta_plugin_manager_get_plugin_by_id (plugin_manager
,
2374 anjuta_status_progress_tick (ANJUTA_STATUS (priv
->status
),
2375 icon_pixbuf
, label
);
2378 g_object_unref (icon_pixbuf
);
2380 node
= g_list_next (node
);
2383 /* Thaw shell operations */
2384 anjuta_shell_thaw (ANJUTA_SHELL (priv
->shell
), NULL
);
2388 on_collect (gpointer key
, gpointer value
, gpointer user_data
)
2391 gchar
*query
= (gchar
*) key
;
2392 AnjutaPluginDescription
*desc
= (AnjutaPluginDescription
*) value
;
2393 GString
*write_buffer
= (GString
*) user_data
;
2395 anjuta_plugin_description_get_string (desc
, "Anjuta Plugin", "Location",
2397 g_string_append_printf (write_buffer
, "%s=%s;", query
, id
);
2402 anjuta_plugin_manager_get_remembered_plugins (AnjutaPluginManager
*plugin_manager
)
2404 AnjutaPluginManagerPriv
*priv
;
2405 GString
*write_buffer
= g_string_new ("");
2407 g_return_val_if_fail (ANJUTA_IS_PLUGIN_MANAGER (plugin_manager
), FALSE
);
2409 priv
= plugin_manager
->priv
;
2410 g_hash_table_foreach (priv
->remember_plugins
, on_collect
,
2412 return g_string_free (write_buffer
, FALSE
);
2416 on_foreach_remove_true (gpointer k
, gpointer v
, gpointer d
)
2422 anjuta_plugin_manager_set_remembered_plugins (AnjutaPluginManager
*plugin_manager
,
2423 const gchar
*remembered_plugins
)
2425 AnjutaPluginManagerPriv
*priv
;
2426 gchar
**strv_lines
, **line_idx
;
2428 g_return_if_fail (ANJUTA_IS_PLUGIN_MANAGER (plugin_manager
));
2429 g_return_if_fail (remembered_plugins
!= NULL
);
2431 priv
= plugin_manager
->priv
;
2433 g_hash_table_foreach_remove (priv
->remember_plugins
,
2434 on_foreach_remove_true
, NULL
);
2436 strv_lines
= g_strsplit (remembered_plugins
, ";", -1);
2437 line_idx
= strv_lines
;
2440 gchar
**strv_keyvals
;
2441 strv_keyvals
= g_strsplit (*line_idx
, "=", -1);
2442 if (strv_keyvals
&& strv_keyvals
[0] && strv_keyvals
[1])
2444 AnjutaPluginHandle
*plugin
;
2445 plugin
= g_hash_table_lookup (priv
->plugins_by_name
,
2449 AnjutaPluginDescription
*desc
;
2450 desc
= anjuta_plugin_handle_get_description (plugin
);
2452 DEBUG_PRINT ("Restoring remember plugin: %s=%s",
2456 g_hash_table_insert (priv
->remember_plugins
,
2457 g_strdup (strv_keyvals
[0]), desc
);
2459 g_strfreev (strv_keyvals
);
2463 g_strfreev (strv_lines
);