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>
42 #include <libanjuta/interfaces/ianjuta-preferences.h>
52 PROP_AVAILABLE_PLUGINS
,
53 PROP_ACTIVATED_PLUGINS
68 struct _AnjutaPluginManagerPriv
73 GList
*available_plugins
;
75 /* Indexes => plugin handles */
76 GHashTable
*plugins_by_interfaces
;
77 GHashTable
*plugins_by_name
;
78 GHashTable
*plugins_by_description
;
80 /* Plugins that are currently activated */
81 GHashTable
*activated_plugins
;
83 /* Plugins that have been previously loaded but current deactivated */
84 GHashTable
*plugins_cache
;
86 /* Remember plugin selection */
87 GHashTable
*remember_plugins
;
90 /* Available plugins page treeview */
100 /* Remembered plugins page treeview */
108 /* Plugin class types */
110 static AnjutaCPluginFactory
*anjuta_plugin_factory
= NULL
;
112 static GObjectClass
* parent_class
= NULL
;
113 static guint plugin_manager_signals
[LAST_SIGNAL
] = { 0 };
115 static GHashTable
* plugin_set_update (AnjutaPluginManager
*plugin_manager
,
116 AnjutaPluginHandle
* selected_plugin
,
119 static IAnjutaPluginFactory
* get_plugin_factory (AnjutaPluginManager
*plugin_manager
,
120 const gchar
*language
, GError
**error
);
123 anjuta_plugin_manager_error_quark (void)
125 static GQuark quark
= 0;
128 quark
= g_quark_from_static_string ("anjuta-plugin-manager-quark");
133 /** Dependency Resolution **/
136 collect_cycle (AnjutaPluginManager
*plugin_manager
,
137 AnjutaPluginHandle
*base_plugin
, AnjutaPluginHandle
*cur_plugin
,
140 AnjutaPluginManagerPriv
*priv
;
143 priv
= plugin_manager
->priv
;
145 for (l
= anjuta_plugin_handle_get_dependency_names (cur_plugin
);
146 l
!= NULL
; l
= l
->next
)
148 AnjutaPluginHandle
*dep
= g_hash_table_lookup (priv
->plugins_by_name
,
152 if (dep
== base_plugin
)
154 *cycle
= g_list_prepend (NULL
, dep
);
155 /* DEBUG_PRINT ("%s ", anjuta_plugin_handle_get_name (dep)); */
160 if (collect_cycle (plugin_manager
, base_plugin
, dep
, cycle
))
162 *cycle
= g_list_prepend (*cycle
, dep
);
163 /* DEBUG_PRINT ("%s ", anjuta_plugin_handle_get_name (dep)); */
173 add_dependency (AnjutaPluginHandle
*dependent
, AnjutaPluginHandle
*dependency
)
175 g_hash_table_insert (anjuta_plugin_handle_get_dependents (dependency
),
176 dependent
, dependency
);
177 g_hash_table_insert (anjuta_plugin_handle_get_dependencies (dependent
),
178 dependency
, dependent
);
182 child_dep_foreach_cb (gpointer key
, gpointer value
, gpointer user_data
)
184 add_dependency (ANJUTA_PLUGIN_HANDLE (user_data
),
185 ANJUTA_PLUGIN_HANDLE (key
));
188 /* Resolves dependencies for a single module recursively. Shortcuts if
189 * the module has already been resolved. Returns a list representing
190 * any cycles found, or NULL if no cycles are found. If a cycle is found,
191 * the graph is left unresolved.
194 resolve_for_module (AnjutaPluginManager
*plugin_manager
,
195 AnjutaPluginHandle
*plugin
, int pass
)
197 AnjutaPluginManagerPriv
*priv
;
201 priv
= plugin_manager
->priv
;
203 if (anjuta_plugin_handle_get_checked (plugin
))
208 if (anjuta_plugin_handle_get_resolve_pass (plugin
) == pass
)
211 g_warning ("cycle found: %s on pass %d",
212 anjuta_plugin_handle_get_name (plugin
),
213 anjuta_plugin_handle_get_resolve_pass (plugin
));
214 collect_cycle (plugin_manager
, plugin
, plugin
, &cycle
);
218 if (anjuta_plugin_handle_get_resolve_pass (plugin
) != -1)
223 anjuta_plugin_handle_set_can_load (plugin
, TRUE
);
224 anjuta_plugin_handle_set_resolve_pass (plugin
, pass
);
226 for (l
= anjuta_plugin_handle_get_dependency_names (plugin
);
227 l
!= NULL
; l
= l
->next
)
230 AnjutaPluginHandle
*child
=
231 g_hash_table_lookup (priv
->plugins_by_name
, dep
);
234 ret
= resolve_for_module (plugin_manager
, child
, pass
);
240 /* Add the dependency's dense dependency list
241 * to the current module's dense dependency list */
242 g_hash_table_foreach (anjuta_plugin_handle_get_dependencies (child
),
243 child_dep_foreach_cb
, plugin
);
244 add_dependency (plugin
, child
);
246 /* If the child can't load due to dependency problems,
247 * the current module can't either */
248 anjuta_plugin_handle_set_can_load (plugin
,
249 anjuta_plugin_handle_get_can_load (child
));
251 g_warning ("Dependency %s not found.\n", dep
);
252 anjuta_plugin_handle_set_can_load (plugin
, FALSE
);
256 anjuta_plugin_handle_set_checked (plugin
, TRUE
);
261 /* Clean up the results of a resolving run */
263 unresolve_dependencies (AnjutaPluginManager
*plugin_manager
)
265 AnjutaPluginManagerPriv
*priv
;
268 priv
= plugin_manager
->priv
;
270 for (l
= priv
->available_plugins
; l
!= NULL
; l
= l
->next
)
272 AnjutaPluginHandle
*plugin
= l
->data
;
273 anjuta_plugin_handle_unresolve_dependencies (plugin
);
280 prune_modules (AnjutaPluginManager
*plugin_manager
, GList
*modules
)
282 AnjutaPluginManagerPriv
*priv
;
285 priv
= plugin_manager
->priv
;
287 for (l
= modules
; l
!= NULL
; l
= l
->next
) {
288 AnjutaPluginHandle
*plugin
= l
->data
;
290 g_hash_table_remove (priv
->plugins_by_name
,
291 anjuta_plugin_handle_get_id (plugin
));
292 priv
->available_plugins
= g_list_remove (priv
->available_plugins
, plugin
);
297 dependency_compare (AnjutaPluginHandle
*plugin_a
,
298 AnjutaPluginHandle
*plugin_b
)
300 int a
= g_hash_table_size (anjuta_plugin_handle_get_dependencies (plugin_a
));
301 int b
= g_hash_table_size (anjuta_plugin_handle_get_dependencies (plugin_b
));
306 /* Resolves the dependencies of the priv->available_plugins list. When this
307 * function is complete, the following will be true:
309 * 1) The dependencies and dependents hash tables of the modules will
312 * 2) Cycles in the graph will be removed.
314 * 3) Modules which cannot be loaded due to failed dependencies will
317 * 4) priv->available_plugins will be sorted such that no module depends on a
320 * If a cycle in the graph is found, it is pruned from the tree and
321 * returned as a list stored in the cycles list.
324 resolve_dependencies (AnjutaPluginManager
*plugin_manager
, GList
**cycles
)
326 AnjutaPluginManagerPriv
*priv
;
330 priv
= plugin_manager
->priv
;
333 /* Try resolving dependencies. If there is a cycle, prune the
334 * cycle and try to resolve again */
339 for (l
= priv
->available_plugins
; l
!= NULL
&& !cycle
; l
= l
->next
) {
340 cycle
= resolve_for_module (plugin_manager
, l
->data
, pass
++);
344 *cycles
= g_list_prepend (*cycles
, cycle
);
345 prune_modules (plugin_manager
, cycle
);
346 unresolve_dependencies (plugin_manager
);
350 /* Now that there is a fully resolved dependency tree, sort
351 * priv->available_plugins to create a valid load order */
352 priv
->available_plugins
= g_list_sort (priv
->available_plugins
,
353 (GCompareFunc
)dependency_compare
);
356 /* Plugins loading */
359 str_has_suffix (const char *haystack
, const char *needle
)
363 if (needle
== NULL
) {
366 if (haystack
== NULL
) {
367 return needle
[0] == '\0';
370 /* Eat one character at a time. */
371 h
= haystack
+ strlen(haystack
);
372 n
= needle
+ strlen(needle
);
380 } while (*--h
== *--n
);
385 load_plugin (AnjutaPluginManager
*plugin_manager
,
386 const gchar
*plugin_desc_path
)
388 AnjutaPluginManagerPriv
*priv
;
389 AnjutaPluginHandle
*plugin_handle
;
391 g_return_if_fail (ANJUTA_IS_PLUGIN_MANAGER (plugin_manager
));
392 priv
= plugin_manager
->priv
;
394 plugin_handle
= anjuta_plugin_handle_new (plugin_desc_path
);
397 if (g_hash_table_lookup (priv
->plugins_by_name
,
398 anjuta_plugin_handle_get_id (plugin_handle
)))
400 g_object_unref (plugin_handle
);
405 /* Available plugin */
406 priv
->available_plugins
= g_list_prepend (priv
->available_plugins
,
409 g_hash_table_insert (priv
->plugins_by_name
,
410 (gchar
*)anjuta_plugin_handle_get_id (plugin_handle
),
413 /* Index by description */
414 g_hash_table_insert (priv
->plugins_by_description
,
415 anjuta_plugin_handle_get_description (plugin_handle
),
418 /* Index by interfaces exported by this plugin */
419 node
= anjuta_plugin_handle_get_interfaces (plugin_handle
);
428 objs
= (GList
*)g_hash_table_lookup (priv
->plugins_by_interfaces
, iface
);
434 if (obj_node
->data
== plugin_handle
)
439 obj_node
= g_list_next (obj_node
);
443 g_hash_table_steal (priv
->plugins_by_interfaces
, iface
);
444 objs
= g_list_prepend (objs
, plugin_handle
);
445 g_hash_table_insert (priv
->plugins_by_interfaces
, iface
, objs
);
447 node
= g_list_next (node
);
455 load_plugins_from_directory (AnjutaPluginManager
* plugin_manager
,
456 const gchar
*dirname
)
459 struct dirent
*entry
;
461 dir
= opendir (dirname
);
468 for (entry
= readdir (dir
); entry
!= NULL
; entry
= readdir (dir
))
470 if (str_has_suffix (entry
->d_name
, ".plugin"))
473 pathname
= g_strdup_printf ("%s/%s", dirname
, entry
->d_name
);
474 load_plugin (plugin_manager
,pathname
);
481 /* Plugin activation and deactivation */
484 on_plugin_activated (AnjutaPlugin
*plugin_object
, AnjutaPluginHandle
*plugin
)
486 AnjutaPluginManager
*plugin_manager
;
487 AnjutaPluginManagerPriv
*priv
;
489 /* FIXME: Pass plugin_manager directly in signal arguments */
490 plugin_manager
= anjuta_shell_get_plugin_manager (plugin_object
->shell
, NULL
);
492 g_return_if_fail(plugin_manager
!= NULL
);
494 priv
= plugin_manager
->priv
;
496 g_hash_table_insert (priv
->activated_plugins
, plugin
,
497 G_OBJECT (plugin_object
));
498 if (g_hash_table_lookup (priv
->plugins_cache
, plugin
))
499 g_hash_table_remove (priv
->plugins_cache
, plugin
);
501 g_signal_emit_by_name (plugin_manager
, "plugin-activated",
502 anjuta_plugin_handle_get_description (plugin
),
507 on_plugin_deactivated (AnjutaPlugin
*plugin_object
, AnjutaPluginHandle
*plugin
)
509 AnjutaPluginManager
*plugin_manager
;
510 AnjutaPluginManagerPriv
*priv
;
512 /* FIXME: Pass plugin_manager directly in signal arguments */
513 plugin_manager
= anjuta_shell_get_plugin_manager (plugin_object
->shell
, NULL
);
515 g_return_if_fail (plugin_manager
!= NULL
);
517 priv
= plugin_manager
->priv
;
519 g_hash_table_insert (priv
->plugins_cache
, plugin
, G_OBJECT (plugin_object
));
520 g_hash_table_remove (priv
->activated_plugins
, plugin
);
522 g_signal_emit_by_name (plugin_manager
, "plugin-deactivated",
523 anjuta_plugin_handle_get_description (plugin
),
528 activate_plugin (AnjutaPluginManager
*plugin_manager
,
529 AnjutaPluginHandle
*handle
, GError
**error
)
531 AnjutaPluginManagerPriv
*priv
;
532 IAnjutaPluginFactory
* factory
;
533 AnjutaPlugin
*plugin
;
534 const gchar
*plugin_id
;
535 const gchar
*language
;
538 priv
= plugin_manager
->priv
;
540 plugin_id
= anjuta_plugin_handle_get_id (handle
);
542 resident
= anjuta_plugin_handle_get_resident (handle
);
543 language
= anjuta_plugin_handle_get_language (handle
);
545 factory
= get_plugin_factory (plugin_manager
, language
, error
);
546 if (factory
== NULL
) return NULL
;
548 plugin
= ianjuta_plugin_factory_new_plugin (factory
, handle
, ANJUTA_SHELL (priv
->shell
), error
);
554 g_signal_connect (plugin
, "activated",
555 G_CALLBACK (on_plugin_activated
), handle
);
556 g_signal_connect (plugin
, "deactivated",
557 G_CALLBACK (on_plugin_deactivated
), handle
);
563 g_hashtable_foreach_true (gpointer key
, gpointer value
, gpointer user_data
)
569 anjuta_plugin_manager_unload_all_plugins (AnjutaPluginManager
*plugin_manager
)
571 AnjutaPluginManagerPriv
*priv
;
573 priv
= plugin_manager
->priv
;
574 if (g_hash_table_size (priv
->activated_plugins
) > 0 ||
575 g_hash_table_size (priv
->plugins_cache
) > 0)
577 priv
->available_plugins
= g_list_reverse (priv
->available_plugins
);
578 if (g_hash_table_size (priv
->activated_plugins
) > 0)
581 node
= priv
->available_plugins
;
584 AnjutaPluginHandle
*selected_plugin
= node
->data
;
585 if (g_hash_table_lookup (priv
->activated_plugins
, selected_plugin
))
587 plugin_set_update (plugin_manager
, selected_plugin
, FALSE
);
588 /* DEBUG_PRINT ("Unloading plugin: %s",
589 anjuta_plugin_handle_get_id (selected_plugin));
592 node
= g_list_next (node
);
594 g_hash_table_foreach_remove (priv
->activated_plugins
,
595 g_hashtable_foreach_true
, NULL
);
597 if (g_hash_table_size (priv
->plugins_cache
) > 0)
600 node
= priv
->available_plugins
;
604 AnjutaPluginHandle
*selected_plugin
= node
->data
;
606 plugin_obj
= g_hash_table_lookup (priv
->plugins_cache
,
610 /* DEBUG_PRINT ("Destroying plugin: %s",
611 anjuta_plugin_handle_get_id (selected_plugin));
613 g_object_unref (plugin_obj
);
615 node
= g_list_next (node
);
617 g_hash_table_foreach_remove (priv
->plugins_cache
,
618 g_hashtable_foreach_true
, NULL
);
620 priv
->available_plugins
= g_list_reverse (priv
->available_plugins
);
625 should_unload (GHashTable
*activated_plugins
, AnjutaPluginHandle
*plugin_to_unload
,
626 AnjutaPluginHandle
*plugin
)
628 GObject
*plugin_obj
= g_hash_table_lookup (activated_plugins
, plugin
);
633 if (plugin_to_unload
== plugin
)
637 GPOINTER_TO_INT (g_hash_table_lookup (anjuta_plugin_handle_get_dependents (plugin
),
643 should_load (GHashTable
*activated_plugins
, AnjutaPluginHandle
*plugin_to_load
,
644 AnjutaPluginHandle
*plugin
)
646 GObject
*plugin_obj
= g_hash_table_lookup (activated_plugins
, plugin
);
651 if (plugin_to_load
== plugin
)
652 return anjuta_plugin_handle_get_can_load (plugin
);
654 gboolean dependency
=
655 GPOINTER_TO_INT (g_hash_table_lookup (anjuta_plugin_handle_get_dependencies (plugin_to_load
),
657 return (dependency
&& anjuta_plugin_handle_get_can_load (plugin
));
660 static AnjutaPluginHandle
*
661 plugin_for_iter (GtkListStore
*store
, GtkTreeIter
*iter
)
663 AnjutaPluginHandle
*plugin
;
665 gtk_tree_model_get (GTK_TREE_MODEL (store
), iter
, COL_PLUGIN
, &plugin
, -1);
670 update_enabled (GtkTreeModel
*model
, GHashTable
*activated_plugins
)
674 if (gtk_tree_model_get_iter_first (model
, &iter
)) {
676 AnjutaPluginHandle
*plugin
;
680 plugin
= plugin_for_iter(GTK_LIST_STORE(model
), &iter
);
681 plugin_obj
= g_hash_table_lookup (activated_plugins
, plugin
);
682 installed
= (plugin_obj
!= NULL
) ? TRUE
: FALSE
;
683 gtk_tree_model_get (model
, &iter
, COL_PLUGIN
, &plugin
, -1);
684 gtk_list_store_set (GTK_LIST_STORE (model
), &iter
,
685 COL_ENABLED
, installed
, -1);
686 } while (gtk_tree_model_iter_next (model
, &iter
));
691 plugin_set_update (AnjutaPluginManager
*plugin_manager
,
692 AnjutaPluginHandle
* selected_plugin
,
695 AnjutaPluginManagerPriv
*priv
;
699 priv
= plugin_manager
->priv
;
700 plugin_obj
= g_hash_table_lookup (priv
->activated_plugins
, selected_plugin
);
702 if (plugin_obj
&& load
)
704 g_warning ("Trying to install already installed plugin '%s'",
705 anjuta_plugin_handle_get_name (selected_plugin
));
706 return priv
->activated_plugins
;
708 if (!plugin_obj
&& !load
)
710 g_warning ("Trying to uninstall a not installed plugin '%s'",
711 anjuta_plugin_handle_get_name (selected_plugin
));
712 return priv
->activated_plugins
;
716 anjuta_status_busy_push (priv
->status
);
720 /* reverse priv->available_plugins when unloading, so that plugins are
721 * unloaded in the right order */
722 priv
->available_plugins
= g_list_reverse (priv
->available_plugins
);
724 for (l
= priv
->available_plugins
; l
!= NULL
; l
= l
->next
)
726 AnjutaPluginHandle
*plugin
= l
->data
;
727 if (should_unload (priv
->activated_plugins
, selected_plugin
, plugin
))
729 /* FIXME: Unload the class and sharedlib if possible */
730 AnjutaPlugin
*anjuta_plugin
= ANJUTA_PLUGIN (plugin_obj
);
731 if (!anjuta_plugin_deactivate (ANJUTA_PLUGIN (anjuta_plugin
)))
733 anjuta_util_dialog_info (GTK_WINDOW (priv
->shell
),
734 _("Plugin '%s' do not want to be deactivated"),
735 anjuta_plugin_handle_get_name (plugin
));
739 priv
->available_plugins
= g_list_reverse (priv
->available_plugins
);
743 for (l
= priv
->available_plugins
; l
!= NULL
; l
= l
->next
)
745 AnjutaPluginHandle
*plugin
= l
->data
;
746 if (should_load (priv
->activated_plugins
, selected_plugin
, plugin
))
748 AnjutaPlugin
*plugin_obj
;
749 GError
*error
= NULL
;
750 plugin_obj
= g_hash_table_lookup (priv
->plugins_cache
, plugin
);
753 plugin_obj
= activate_plugin (plugin_manager
, plugin
,
759 anjuta_plugin_activate (ANJUTA_PLUGIN (plugin_obj
));
765 gchar
* message
= g_strdup_printf (_("Could not load %s\n"
766 "This usually means that your installation is corrupted. The "
767 "error message leading to this was:\n%s"),
768 anjuta_plugin_handle_get_name (selected_plugin
),
770 anjuta_util_dialog_error (GTK_WINDOW(plugin_manager
->priv
->shell
),
772 g_error_free (error
);
780 anjuta_status_busy_pop (priv
->status
);
781 return priv
->activated_plugins
;
785 plugin_toggled (GtkCellRendererToggle
*cell
, char *path_str
, gpointer data
)
787 AnjutaPluginManager
*plugin_manager
;
788 AnjutaPluginManagerPriv
*priv
;
789 GtkListStore
*store
= GTK_LIST_STORE (data
);
792 AnjutaPluginHandle
*plugin
;
794 GHashTable
*activated_plugins
;
795 AnjutaPlugin
* plugin_object
;
797 path
= gtk_tree_path_new_from_string (path_str
);
799 plugin_manager
= g_object_get_data (G_OBJECT (store
), "plugin-manager");
800 priv
= plugin_manager
->priv
;
802 gtk_tree_model_get_iter (GTK_TREE_MODEL (store
), &iter
, path
);
803 gtk_tree_model_get (GTK_TREE_MODEL (store
), &iter
,
804 COL_ENABLED
, &enabled
,
810 plugin_object
= g_hash_table_lookup (priv
->activated_plugins
, plugin
);
812 IANJUTA_IS_PREFERENCES(plugin_object
))
814 ianjuta_preferences_unmerge (IANJUTA_PREFERENCES (plugin_object
),
815 anjuta_shell_get_preferences (ANJUTA_SHELL (priv
->shell
), NULL
),
821 activated_plugins
= plugin_set_update (plugin_manager
, plugin
, enabled
);
822 plugin_object
= g_hash_table_lookup (priv
->activated_plugins
, plugin
);
824 /* Make sure that it appears in the preferences. This method
825 can only be called when the preferences dialog is active so
829 IANJUTA_IS_PREFERENCES(plugin_object
))
831 ianjuta_preferences_merge (IANJUTA_PREFERENCES (plugin_object
),
832 anjuta_shell_get_preferences (ANJUTA_SHELL (priv
->shell
), NULL
),
836 update_enabled (GTK_TREE_MODEL (store
), activated_plugins
);
837 gtk_tree_path_free (path
);
842 selection_changed (GtkTreeSelection
*selection
, GtkListStore
*store
)
846 if (gtk_tree_selection_get_selected (selection
, NULL
,
848 GtkTextBuffer
*buffer
;
850 GtkWidget
*txt
= g_object_get_data (G_OBJECT (store
),
853 GtkWidget
*image
= g_object_get_data (G_OBJECT (store
),
855 AnjutaPluginHandle
*plugin
= plugin_for_iter (store
, &iter
);
857 buffer
= gtk_text_view_get_buffer (GTK_TEXT_VIEW (txt
));
858 gtk_text_buffer_set_text (buffer
, plugin
->about
, -1);
860 if (plugin
->icon_path
) {
861 gtk_image_set_from_file (GTK_IMAGE (image
),
863 gtk_widget_show (GTK_WIDGET (image
));
865 gtk_widget_hide (GTK_WIDGET (image
));
872 create_plugin_tree (void)
876 GtkCellRenderer
*renderer
;
877 GtkTreeViewColumn
*column
;
879 store
= gtk_list_store_new (N_COLS
,
885 tree
= gtk_tree_view_new_with_model (GTK_TREE_MODEL (store
));
887 renderer
= gtk_cell_renderer_toggle_new ();
888 g_signal_connect (G_OBJECT (renderer
), "toggled",
889 G_CALLBACK (plugin_toggled
), store
);
890 column
= gtk_tree_view_column_new_with_attributes (_("Load"),
897 gtk_tree_view_append_column (GTK_TREE_VIEW (tree
), column
);
898 gtk_tree_view_column_set_sizing (column
,
899 GTK_TREE_VIEW_COLUMN_AUTOSIZE
);
901 column
= gtk_tree_view_column_new ();
902 renderer
= gtk_cell_renderer_pixbuf_new ();
903 gtk_tree_view_column_pack_start (column
, renderer
, FALSE
);
904 gtk_tree_view_column_add_attribute (column
, renderer
, "pixbuf",
906 renderer
= gtk_cell_renderer_text_new ();
907 gtk_tree_view_column_pack_start (column
, renderer
, FALSE
);
908 gtk_tree_view_column_add_attribute (column
, renderer
, "markup",
910 gtk_tree_view_column_set_sizing (column
,
911 GTK_TREE_VIEW_COLUMN_AUTOSIZE
);
912 gtk_tree_view_column_set_title (column
, _("Available Plugins"));
913 gtk_tree_view_append_column (GTK_TREE_VIEW (tree
), column
);
914 gtk_tree_view_set_expander_column (GTK_TREE_VIEW (tree
), column
);
916 g_object_unref (store
);
920 /* Sort function for plugins */
922 sort_plugins(gconstpointer a
, gconstpointer b
)
924 g_return_val_if_fail (a
!= NULL
, 0);
925 g_return_val_if_fail (b
!= NULL
, 0);
927 AnjutaPluginHandle
* plugin_a
= ANJUTA_PLUGIN_HANDLE (a
);
928 AnjutaPluginHandle
* plugin_b
= ANJUTA_PLUGIN_HANDLE (b
);
930 return strcmp (anjuta_plugin_handle_get_name (plugin_a
),
931 anjuta_plugin_handle_get_name (plugin_b
));
934 /* If show_all == FALSE, show only user activatable plugins
935 * If show_all == TRUE, show all plugins
938 populate_plugin_model (AnjutaPluginManager
*plugin_manager
,
940 GHashTable
*plugins_to_show
,
941 GHashTable
*activated_plugins
,
944 AnjutaPluginManagerPriv
*priv
;
947 priv
= plugin_manager
->priv
;
948 gtk_list_store_clear (store
);
950 priv
->available_plugins
= g_list_sort (priv
->available_plugins
, sort_plugins
);
952 for (l
= priv
->available_plugins
; l
!= NULL
; l
= l
->next
)
954 AnjutaPluginHandle
*plugin
= l
->data
;
956 /* If plugins to show is NULL, show all available plugins */
957 if (plugins_to_show
== NULL
||
958 g_hash_table_lookup (plugins_to_show
, plugin
))
961 gboolean enable
= FALSE
;
962 if (g_hash_table_lookup (activated_plugins
, plugin
))
965 if (anjuta_plugin_handle_get_name (plugin
) &&
966 anjuta_plugin_handle_get_description (plugin
) &&
967 (anjuta_plugin_handle_get_user_activatable (plugin
) ||
973 text
= g_markup_printf_escaped ("<span size=\"larger\" weight=\"bold\">%s</span>\n%s",
974 anjuta_plugin_handle_get_name (plugin
),
975 anjuta_plugin_handle_get_about (plugin
));
977 gtk_list_store_append (store
, &iter
);
978 gtk_list_store_set (store
, &iter
,
980 anjuta_plugin_handle_get_user_activatable (plugin
),
985 if (anjuta_plugin_handle_get_icon_path (plugin
))
988 icon
= gdk_pixbuf_new_from_file_at_size (anjuta_plugin_handle_get_icon_path (plugin
),
991 gtk_list_store_set (store
, &iter
,
993 gdk_pixbuf_unref (icon
);
1003 create_remembered_plugins_tree (void)
1005 GtkListStore
*store
;
1007 GtkCellRenderer
*renderer
;
1008 GtkTreeViewColumn
*column
;
1010 store
= gtk_list_store_new (N_REM_COLS
, GDK_TYPE_PIXBUF
, G_TYPE_STRING
,
1012 tree
= gtk_tree_view_new_with_model (GTK_TREE_MODEL (store
));
1014 column
= gtk_tree_view_column_new ();
1015 renderer
= gtk_cell_renderer_pixbuf_new ();
1016 gtk_tree_view_column_pack_start (column
, renderer
, FALSE
);
1017 gtk_tree_view_column_add_attribute (column
, renderer
, "pixbuf",
1019 renderer
= gtk_cell_renderer_text_new ();
1020 gtk_tree_view_column_pack_start (column
, renderer
, FALSE
);
1021 gtk_tree_view_column_add_attribute (column
, renderer
, "markup",
1023 gtk_tree_view_column_set_sizing (column
,
1024 GTK_TREE_VIEW_COLUMN_AUTOSIZE
);
1025 gtk_tree_view_column_set_title (column
, _("Preferred plugins"));
1026 gtk_tree_view_append_column (GTK_TREE_VIEW (tree
), column
);
1027 gtk_tree_view_set_expander_column (GTK_TREE_VIEW (tree
), column
);
1029 g_object_unref (store
);
1034 foreach_remembered_plugin (gpointer key
, gpointer value
, gpointer user_data
)
1036 AnjutaPluginDescription
*desc
= (AnjutaPluginDescription
*) value
;
1037 GtkListStore
*store
= GTK_LIST_STORE (user_data
);
1038 AnjutaPluginManager
*manager
= g_object_get_data (G_OBJECT (store
),
1040 AnjutaPluginHandle
*plugin
=
1041 g_hash_table_lookup (manager
->priv
->plugins_by_description
, desc
);
1042 g_return_if_fail (plugin
!= NULL
);
1044 if (anjuta_plugin_handle_get_name (plugin
) &&
1045 anjuta_plugin_handle_get_description (plugin
))
1050 text
= g_markup_printf_escaped ("<span size=\"larger\" weight=\"bold\">%s</span>\n%s",
1051 anjuta_plugin_handle_get_name (plugin
),
1052 anjuta_plugin_handle_get_about (plugin
));
1054 gtk_list_store_append (store
, &iter
);
1055 gtk_list_store_set (store
, &iter
,
1057 COL_REM_PLUGIN_KEY
, key
,
1059 if (anjuta_plugin_handle_get_icon_path (plugin
))
1062 icon
= gdk_pixbuf_new_from_file_at_size (anjuta_plugin_handle_get_icon_path (plugin
),
1065 gtk_list_store_set (store
, &iter
,
1066 COL_REM_ICON
, icon
, -1);
1067 gdk_pixbuf_unref (icon
);
1075 populate_remembered_plugins_model (AnjutaPluginManager
*plugin_manager
,
1076 GtkListStore
*store
)
1078 AnjutaPluginManagerPriv
*priv
= plugin_manager
->priv
;
1079 gtk_list_store_clear (store
);
1080 g_hash_table_foreach (priv
->remember_plugins
, foreach_remembered_plugin
,
1085 on_show_all_plugins_toggled (GtkToggleButton
*button
, GtkListStore
*store
)
1087 AnjutaPluginManager
*plugin_manager
;
1089 plugin_manager
= g_object_get_data (G_OBJECT (button
), "__plugin_manager");
1091 populate_plugin_model (plugin_manager
, store
, NULL
,
1092 plugin_manager
->priv
->activated_plugins
,
1093 !gtk_toggle_button_get_active (button
));
1097 on_forget_plugin_clicked (GtkWidget
*button
, GtkTreeView
*view
)
1100 GtkTreeModel
*model
;
1101 GtkTreeSelection
*selection
= gtk_tree_view_get_selection (view
);
1102 if (gtk_tree_selection_get_selected (selection
, &model
, &iter
))
1105 AnjutaPluginManager
*manager
= g_object_get_data (G_OBJECT (model
),
1107 gtk_tree_model_get (model
, &iter
, COL_REM_PLUGIN_KEY
, &plugin_key
, -1);
1108 g_hash_table_remove (manager
->priv
->remember_plugins
, plugin_key
);
1109 gtk_list_store_remove (GTK_LIST_STORE (model
), &iter
);
1110 g_free (plugin_key
);
1115 on_forget_plugin_sel_changed (GtkTreeSelection
*selection
,
1120 if (gtk_tree_selection_get_selected (selection
, NULL
, &iter
))
1121 gtk_widget_set_sensitive (button
, TRUE
);
1123 gtk_widget_set_sensitive (button
, FALSE
);
1127 anjuta_plugin_manager_get_plugins_page (AnjutaPluginManager
*plugin_manager
)
1130 GtkWidget
*checkbutton
;
1132 GtkWidget
*scrolled
;
1133 GtkListStore
*store
;
1136 vbox
= gtk_vbox_new (FALSE
, 0);
1137 gtk_container_set_border_width (GTK_CONTAINER (vbox
), 10);
1139 checkbutton
= gtk_check_button_new_with_label (_("Only show user activatable plugins"));
1140 gtk_container_set_border_width (GTK_CONTAINER (checkbutton
), 10);
1141 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (checkbutton
), TRUE
);
1142 gtk_box_pack_start (GTK_BOX (vbox
), checkbutton
, FALSE
, FALSE
, 0);
1144 scrolled
= gtk_scrolled_window_new (NULL
, NULL
);
1145 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled
),
1147 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled
),
1148 GTK_POLICY_AUTOMATIC
,
1149 GTK_POLICY_AUTOMATIC
);
1150 gtk_box_pack_start (GTK_BOX (vbox
), scrolled
, TRUE
, TRUE
, 0);
1152 tree
= create_plugin_tree ();
1153 store
= GTK_LIST_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (tree
)));
1155 populate_plugin_model (plugin_manager
, store
, NULL
,
1156 plugin_manager
->priv
->activated_plugins
, FALSE
);
1158 gtk_container_add (GTK_CONTAINER (scrolled
), tree
);
1159 g_object_set_data (G_OBJECT (store
), "plugin-manager", plugin_manager
);
1162 g_object_set_data (G_OBJECT (checkbutton
), "__plugin_manager", plugin_manager
);
1163 g_signal_connect (G_OBJECT (checkbutton
), "toggled",
1164 G_CALLBACK (on_show_all_plugins_toggled
),
1166 gtk_widget_show_all (vbox
);
1171 anjuta_plugin_manager_get_remembered_plugins_page (AnjutaPluginManager
*plugin_manager
)
1175 GtkWidget
*scrolled
;
1176 GtkListStore
*store
;
1178 GtkWidget
*display_label
;
1179 GtkWidget
*forget_button
;
1180 GtkTreeSelection
*selection
;
1182 /* Remembered plugin */
1183 vbox
= gtk_vbox_new (FALSE
, 10);
1184 gtk_container_set_border_width (GTK_CONTAINER (vbox
), 10);
1186 display_label
= gtk_label_new (_("These are the plugins selected by you "
1187 "when Anjuta prompted to choose one of "
1188 "many suitable plugins. Removing the "
1189 "preferred plugin will let Anjuta prompt "
1190 "you again to choose different plugin."));
1191 gtk_label_set_line_wrap (GTK_LABEL (display_label
), TRUE
);
1192 gtk_box_pack_start (GTK_BOX (vbox
), display_label
, FALSE
, FALSE
, 0);
1194 scrolled
= gtk_scrolled_window_new (NULL
, NULL
);
1195 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled
),
1197 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled
),
1198 GTK_POLICY_AUTOMATIC
,
1199 GTK_POLICY_AUTOMATIC
);
1200 gtk_box_pack_start (GTK_BOX (vbox
), scrolled
, TRUE
, TRUE
, 0);
1202 tree
= create_remembered_plugins_tree ();
1203 store
= GTK_LIST_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (tree
)));
1205 gtk_container_add (GTK_CONTAINER (scrolled
), tree
);
1206 g_object_set_data (G_OBJECT (store
), "plugin-manager", plugin_manager
);
1207 populate_remembered_plugins_model (plugin_manager
, store
);
1209 hbox
= gtk_hbox_new (FALSE
, 0);
1210 gtk_container_set_border_width (GTK_CONTAINER (hbox
), 5);
1211 gtk_box_pack_start (GTK_BOX (vbox
), hbox
, FALSE
, FALSE
, 0);
1212 forget_button
= gtk_button_new_with_label (_("Forget selected plugin"));
1213 gtk_widget_set_sensitive (forget_button
, FALSE
);
1214 gtk_box_pack_end (GTK_BOX (hbox
), forget_button
, FALSE
, FALSE
, 0);
1216 g_signal_connect (forget_button
, "clicked",
1217 G_CALLBACK (on_forget_plugin_clicked
),
1219 selection
= gtk_tree_view_get_selection (GTK_TREE_VIEW (tree
));
1220 g_signal_connect (selection
, "changed",
1221 G_CALLBACK (on_forget_plugin_sel_changed
),
1223 gtk_widget_show_all (vbox
);
1228 property_to_list (const char *value
)
1234 split_str
= g_strsplit (value
, ",", -1);
1235 for (p
= split_str
; *p
!= NULL
; p
++) {
1236 l
= g_list_prepend (l
, g_strdup (g_strstrip (*p
)));
1238 g_strfreev (split_str
);
1242 static IAnjutaPluginFactory
*
1243 get_plugin_factory (AnjutaPluginManager
*plugin_manager
,
1244 const gchar
*language
,
1247 AnjutaPluginManagerPriv
*priv
;
1248 AnjutaPluginHandle
*plugin
;
1249 GList
*loader_plugins
, *node
;
1250 GList
*valid_plugins
;
1251 GObject
*obj
= NULL
;
1253 g_return_val_if_fail (ANJUTA_IS_PLUGIN_MANAGER (plugin_manager
), G_TYPE_INVALID
);
1256 if ((language
== NULL
) || (g_ascii_strcasecmp (language
, "C") == 0))
1258 /* Support of C plugin is built-in */
1259 return IANJUTA_PLUGIN_FACTORY (anjuta_plugin_factory
);
1262 priv
= plugin_manager
->priv
;
1265 /* Find all plugins implementing the IAnjutaPluginLoader interface. */
1266 loader_plugins
= g_hash_table_lookup (priv
->plugins_by_interfaces
, "IAnjutaPluginLoader");
1268 /* Create a list of loader supporting this language */
1269 node
= loader_plugins
;
1270 valid_plugins
= NULL
;
1273 AnjutaPluginDescription
*desc
;
1279 plugin
= node
->data
;
1281 desc
= anjuta_plugin_handle_get_description (plugin
);
1282 if (anjuta_plugin_description_get_string (desc
, "Plugin Loader", "SupportedLanguage", &val
))
1286 vals
= property_to_list (val
);
1295 if (!found
&& (g_ascii_strcasecmp (l_node
->data
, language
) == 0))
1299 g_free (l_node
->data
);
1300 l_node
= g_list_next (l_node
);
1306 valid_plugins
= g_list_prepend (valid_plugins
, plugin
);
1309 node
= g_list_next (node
);
1312 /* Find the first installed plugin from the valid plugins */
1313 node
= valid_plugins
;
1316 plugin
= node
->data
;
1317 obj
= g_hash_table_lookup (priv
->activated_plugins
, plugin
);
1319 node
= g_list_next (node
);
1322 /* If no plugin is installed yet, do something */
1323 if ((obj
== NULL
) && valid_plugins
&& g_list_length (valid_plugins
) == 1)
1325 /* If there is just one plugin, consider it selected */
1326 plugin
= valid_plugins
->data
;
1328 /* Install and return it */
1329 plugin_set_update (plugin_manager
, plugin
, TRUE
);
1330 obj
= g_hash_table_lookup (priv
->activated_plugins
, plugin
);
1332 else if ((obj
== NULL
) && valid_plugins
)
1334 /* Prompt the user to select one of these plugins */
1336 GList
*descs
= NULL
;
1337 node
= valid_plugins
;
1340 plugin
= node
->data
;
1341 descs
= g_list_prepend (descs
, anjuta_plugin_handle_get_description (plugin
));
1342 node
= g_list_next (node
);
1344 descs
= g_list_reverse (descs
);
1345 obj
= anjuta_plugin_manager_select_and_activate (plugin_manager
,
1346 _("Select a plugin"),
1347 _("Please select a plugin to activate"),
1349 g_list_free (descs
);
1351 g_list_free (valid_plugins
);
1355 return IANJUTA_PLUGIN_FACTORY (obj
);
1358 /* No plugin implementing this interface found */
1359 g_set_error (error
, ANJUTA_PLUGIN_MANAGER_ERROR
,
1360 ANJUTA_PLUGIN_MANAGER_MISSING_FACTORY
,
1361 _("No plugin able to load other plugins in %s"), language
);
1367 on_is_active_plugins_foreach (gpointer key
, gpointer data
, gpointer user_data
)
1369 AnjutaPluginHandle
*handle
= ANJUTA_PLUGIN_HANDLE (key
);
1370 gchar
const **search_iface
= (gchar
const **)user_data
;
1372 if (*search_iface
!= NULL
)
1377 interfaces
= anjuta_plugin_handle_get_interfaces (handle
);
1379 for (found
= g_list_first (interfaces
); found
!= NULL
; found
= g_list_next (found
))
1383 found
= g_list_find_custom (interfaces
, *search_iface
, (GCompareFunc
)strcmp
);
1385 if (found
!= NULL
) *search_iface
= NULL
;
1390 * anjuta_plugin_manager_is_active_plugin:
1391 * @plugin_manager: A #AnjutaPluginManager object
1392 * @iface_name: The interface implemented by the object to be found
1394 * Searches if a currently loaded plugins implements
1395 * the given interface.
1397 * Return value: True is the plugin is currently loaded.
1401 anjuta_plugin_manager_is_active_plugin (AnjutaPluginManager
*plugin_manager
,
1402 const gchar
*iface_name
)
1404 const gchar
*search_iface
= iface_name
;
1406 g_return_val_if_fail (ANJUTA_IS_PLUGIN_MANAGER (plugin_manager
), FALSE
);
1408 g_hash_table_foreach (plugin_manager
->priv
->activated_plugins
,
1409 on_is_active_plugins_foreach
,
1412 return search_iface
== NULL
;
1416 * anjuta_plugin_manager_get_plugin:
1417 * @plugin_manager: A #AnjutaPluginManager object
1418 * @iface_name: The interface implemented by the object to be found
1420 * Searches the currently available plugins to find the one which
1421 * implements the given interface as primary interface and returns it. If
1422 * the plugin is not yet loaded, it will be loaded and activated.
1423 * The returned object is garanteed to be an implementor of the
1424 * interface (as exported by the plugin metafile). It only searches
1425 * from the pool of plugin objects loaded in this shell and can only search
1426 * by primary interface. If there are more objects implementing this primary
1427 * interface, user might be prompted to select one from them (and might give
1428 * the option to use it as default for future queries). A typical usage of this
1432 * anjuta_plugin_manager_get_plugin (plugin_manager, "IAnjutaDocumentManager", error);
1434 * Notice that this function takes the interface name string as string, unlike
1435 * anjuta_plugins_get_interface() which takes the type directly.
1437 * Return value: The plugin object (subclass of #AnjutaPlugin) which implements
1438 * the given interface. See #AnjutaPlugin for more detail on interfaces
1439 * implemented by plugins.
1442 anjuta_plugin_manager_get_plugin (AnjutaPluginManager
*plugin_manager
,
1443 const gchar
*iface_name
)
1445 AnjutaPluginManagerPriv
*priv
;
1446 AnjutaPluginHandle
*plugin
;
1447 GList
*valid_plugins
, *node
;
1449 g_return_val_if_fail (ANJUTA_IS_PLUGIN_MANAGER (plugin_manager
), NULL
);
1450 g_return_val_if_fail (iface_name
!= NULL
, NULL
);
1452 priv
= plugin_manager
->priv
;
1455 /* Find all plugins implementing this (primary) interface. */
1456 valid_plugins
= g_hash_table_lookup (priv
->plugins_by_interfaces
, iface_name
);
1458 /* Find the first installed plugin from the valid plugins */
1459 node
= valid_plugins
;
1463 plugin
= node
->data
;
1464 obj
= g_hash_table_lookup (priv
->activated_plugins
, plugin
);
1467 node
= g_list_next (node
);
1470 /* If no plugin is installed yet, do something */
1471 if (valid_plugins
&& g_list_length (valid_plugins
) == 1)
1473 /* If there is just one plugin, consider it selected */
1475 plugin
= valid_plugins
->data
;
1477 /* Install and return it */
1478 plugin_set_update (plugin_manager
, plugin
, TRUE
);
1479 obj
= g_hash_table_lookup (priv
->activated_plugins
, plugin
);
1483 else if (valid_plugins
)
1485 /* Prompt the user to select one of these plugins */
1487 GList
*descs
= NULL
;
1488 node
= valid_plugins
;
1491 plugin
= node
->data
;
1492 descs
= g_list_prepend (descs
, anjuta_plugin_handle_get_description (plugin
));
1493 node
= g_list_next (node
);
1495 descs
= g_list_reverse (descs
);
1496 obj
= anjuta_plugin_manager_select_and_activate (plugin_manager
,
1497 _("Select a plugin"),
1498 _("Please select a plugin to activate"),
1500 g_list_free (descs
);
1504 /* No plugin implementing this interface found */
1505 g_warning ("No plugin found implementing %s Interface.", iface_name
);
1510 anjuta_plugin_manager_get_plugin_by_id (AnjutaPluginManager
*plugin_manager
,
1511 const gchar
*plugin_id
)
1513 AnjutaPluginManagerPriv
*priv
;
1514 AnjutaPluginHandle
*plugin
;
1516 g_return_val_if_fail (ANJUTA_IS_PLUGIN_MANAGER (plugin_manager
), NULL
);
1517 g_return_val_if_fail (plugin_id
!= NULL
, NULL
);
1519 priv
= plugin_manager
->priv
;
1520 plugin
= g_hash_table_lookup (priv
->plugins_by_name
, plugin_id
);
1524 obj
= g_hash_table_lookup (priv
->activated_plugins
, plugin
);
1530 plugin_set_update (plugin_manager
, plugin
, TRUE
);
1531 obj
= g_hash_table_lookup (priv
->activated_plugins
, plugin
);
1535 g_warning ("No plugin found with id \"%s\".", plugin_id
);
1540 on_activated_plugins_foreach (gpointer key
, gpointer data
, gpointer user_data
)
1542 AnjutaPluginHandle
*plugin
= ANJUTA_PLUGIN_HANDLE (key
);
1543 GList
**active_plugins
= (GList
**)user_data
;
1544 *active_plugins
= g_list_prepend (*active_plugins
,
1545 anjuta_plugin_handle_get_description (plugin
));
1549 on_activated_plugin_objects_foreach (gpointer key
, gpointer data
, gpointer user_data
)
1551 GList
**active_plugins
= (GList
**)user_data
;
1552 *active_plugins
= g_list_prepend (*active_plugins
,
1557 anjuta_plugin_manager_get_active_plugins (AnjutaPluginManager
*plugin_manager
)
1559 GList
*active_plugins
= NULL
;
1561 g_return_val_if_fail (ANJUTA_IS_PLUGIN_MANAGER (plugin_manager
), NULL
);
1562 g_hash_table_foreach (plugin_manager
->priv
->activated_plugins
,
1563 on_activated_plugins_foreach
,
1565 return g_list_reverse (active_plugins
);
1569 anjuta_plugin_manager_get_active_plugin_objects (AnjutaPluginManager
*plugin_manager
)
1571 GList
*active_plugins
= NULL
;
1573 g_return_val_if_fail (ANJUTA_IS_PLUGIN_MANAGER (plugin_manager
), NULL
);
1574 g_hash_table_foreach (plugin_manager
->priv
->activated_plugins
,
1575 on_activated_plugin_objects_foreach
,
1577 return g_list_reverse (active_plugins
);
1581 anjuta_plugin_manager_unload_plugin_by_id (AnjutaPluginManager
*plugin_manager
,
1582 const gchar
*plugin_id
)
1584 AnjutaPluginManagerPriv
*priv
;
1585 AnjutaPluginHandle
*plugin
;
1587 g_return_val_if_fail (ANJUTA_IS_PLUGIN_MANAGER (plugin_manager
), FALSE
);
1588 g_return_val_if_fail (plugin_id
!= NULL
, FALSE
);
1590 priv
= plugin_manager
->priv
;
1592 plugin
= g_hash_table_lookup (priv
->plugins_by_name
, plugin_id
);
1595 plugin_set_update (plugin_manager
, plugin
, FALSE
);
1597 /* Check if the plugin has been indeed unloaded */
1598 if (!g_hash_table_lookup (priv
->activated_plugins
, plugin
))
1603 g_warning ("No plugin found with id \"%s\".", plugin_id
);
1608 find_plugin_for_object (gpointer key
, gpointer value
, gpointer data
)
1612 g_object_set_data (G_OBJECT (data
), "__plugin_plugin", key
);
1619 anjuta_plugin_manager_unload_plugin (AnjutaPluginManager
*plugin_manager
,
1620 GObject
*plugin_object
)
1622 AnjutaPluginManagerPriv
*priv
;
1623 AnjutaPluginHandle
*plugin
;
1625 g_return_val_if_fail (ANJUTA_IS_PLUGIN_MANAGER (plugin_manager
), FALSE
);
1626 g_return_val_if_fail (ANJUTA_IS_PLUGIN (plugin_object
), FALSE
);
1628 priv
= plugin_manager
->priv
;
1632 /* Find the plugin that correspond to this plugin object */
1633 g_hash_table_find (priv
->activated_plugins
, find_plugin_for_object
,
1635 plugin
= g_object_get_data (G_OBJECT (plugin_object
), "__plugin_plugin");
1639 plugin_set_update (plugin_manager
, plugin
, FALSE
);
1641 /* Check if the plugin has been indeed unloaded */
1642 if (!g_hash_table_lookup (priv
->activated_plugins
, plugin
))
1647 g_warning ("No plugin found with object \"%p\".", plugin_object
);
1652 anjuta_plugin_manager_query (AnjutaPluginManager
*plugin_manager
,
1653 const gchar
*section_name
,
1654 const gchar
*attribute_name
,
1655 const gchar
*attribute_value
,
1658 AnjutaPluginManagerPriv
*priv
;
1661 GList
*anames
= NULL
;
1662 GList
*avalues
= NULL
;
1663 const gchar
*sec
= section_name
;
1664 const gchar
*aname
= attribute_name
;
1665 const gchar
*avalue
= attribute_value
;
1666 GList
*selected_plugins
= NULL
;
1670 g_return_val_if_fail (ANJUTA_IS_PLUGIN_MANAGER (plugin_manager
), NULL
);
1672 priv
= plugin_manager
->priv
;
1673 available
= priv
->available_plugins
;
1675 if (section_name
== NULL
)
1677 /* If no query is given, select all plugins */
1680 AnjutaPluginHandle
*plugin
= available
->data
;
1681 AnjutaPluginDescription
*desc
=
1682 anjuta_plugin_handle_get_description (plugin
);
1683 selected_plugins
= g_list_prepend (selected_plugins
, desc
);
1684 available
= g_list_next (available
);
1686 return g_list_reverse (selected_plugins
);
1689 g_return_val_if_fail (section_name
!= NULL
, NULL
);
1690 g_return_val_if_fail (attribute_name
!= NULL
, NULL
);
1691 g_return_val_if_fail (attribute_value
!= NULL
, NULL
);
1693 secs
= g_list_prepend (secs
, g_strdup (section_name
));
1694 anames
= g_list_prepend (anames
, g_strdup (attribute_name
));
1695 avalues
= g_list_prepend (avalues
, g_strdup (attribute_value
));
1697 va_start (var_args
, attribute_value
);
1700 sec
= va_arg (var_args
, const gchar
*);
1703 aname
= va_arg (var_args
, const gchar
*);
1706 avalue
= va_arg (var_args
, const gchar
*);
1709 secs
= g_list_prepend (secs
, g_strdup (sec
));
1710 anames
= g_list_prepend (anames
, g_strdup (aname
));
1711 avalues
= g_list_prepend (avalues
, g_strdup (avalue
));
1718 secs
= g_list_reverse (secs
);
1719 anames
= g_list_reverse (anames
);
1720 avalues
= g_list_reverse (avalues
);
1724 GList
* s_node
= secs
;
1725 GList
* n_node
= anames
;
1726 GList
* v_node
= avalues
;
1728 gboolean satisfied
= FALSE
;
1730 AnjutaPluginHandle
*plugin
= available
->data
;
1731 AnjutaPluginDescription
*desc
=
1732 anjuta_plugin_handle_get_description (plugin
);
1739 gboolean found
= FALSE
;
1744 aname
= n_node
->data
;
1745 avalue
= v_node
->data
;
1747 if (!anjuta_plugin_description_get_string (desc
, sec
, aname
, &val
))
1753 vals
= property_to_list (val
);
1759 if (strchr(node
->data
, '*') != NULL
)
1764 const gchar
*cursor
;
1766 segments
= g_strsplit (node
->data
, "*", -1);
1770 while (*seg_ptr
!= NULL
)
1772 if (strlen (*seg_ptr
) > 0) {
1773 cursor
= strstr (cursor
, *seg_ptr
);
1777 cursor
+= strlen (*seg_ptr
);
1780 if (*seg_ptr
== NULL
)
1782 g_strfreev (segments
);
1784 else if (g_ascii_strcasecmp (node
->data
, avalue
) == 0)
1789 g_free (node
->data
);
1790 node
= g_list_next (node
);
1798 s_node
= g_list_next (s_node
);
1799 n_node
= g_list_next (n_node
);
1800 v_node
= g_list_next (v_node
);
1804 selected_plugins
= g_list_prepend (selected_plugins
, desc
);
1805 /* DEBUG_PRINT ("Satisfied, Adding %s",
1806 anjuta_plugin_handle_get_name (plugin));*/
1808 available
= g_list_next (available
);
1810 anjuta_util_glist_strings_free (secs
);
1811 anjuta_util_glist_strings_free (anames
);
1812 anjuta_util_glist_strings_free (avalues
);
1814 return g_list_reverse (selected_plugins
);
1820 PLUGIN_DESCRIPTION_COLUMN
,
1825 on_plugin_list_row_activated (GtkTreeView
*tree_view
,
1827 GtkTreeViewColumn
*column
,
1830 gtk_dialog_response (dialog
, GTK_RESPONSE_OK
);
1833 AnjutaPluginDescription
*
1834 anjuta_plugin_manager_select (AnjutaPluginManager
*plugin_manager
,
1835 gchar
*title
, gchar
*description
,
1836 GList
*plugin_descriptions
)
1838 AnjutaPluginDescription
*desc
;
1839 AnjutaPluginManagerPriv
*priv
;
1841 GtkTreeModel
*model
;
1843 GtkTreeViewColumn
*column
;
1844 GtkCellRenderer
*renderer
;
1848 GtkWidget
*remember_checkbox
;
1850 GtkTreeIter selected
;
1851 GtkTreeSelection
*selection
;
1852 GtkTreeModel
*store
;
1853 GList
*selection_ids
= NULL
;
1854 GString
*remember_key
= g_string_new ("");
1856 g_return_val_if_fail (title
!= NULL
, NULL
);
1857 g_return_val_if_fail (description
!= NULL
, NULL
);
1858 g_return_val_if_fail (plugin_descriptions
!= NULL
, NULL
);
1860 priv
= plugin_manager
->priv
;
1862 if (g_list_length (plugin_descriptions
) <= 0)
1865 dlg
= gtk_dialog_new_with_buttons (title
, GTK_WINDOW (priv
->shell
),
1866 GTK_DIALOG_DESTROY_WITH_PARENT
,
1868 GTK_RESPONSE_CANCEL
,
1869 GTK_STOCK_OK
, GTK_RESPONSE_OK
,
1871 gtk_widget_set_size_request (dlg
, 400, 300);
1872 gtk_window_set_default_size (GTK_WINDOW (dlg
), 400, 300);
1874 label
= gtk_label_new (description
);
1875 gtk_label_set_use_markup (GTK_LABEL (label
), TRUE
);
1876 gtk_widget_show (label
);
1877 gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dlg
)->vbox
), label
,
1880 sc
= gtk_scrolled_window_new (NULL
, NULL
);
1881 gtk_widget_show (sc
);
1882 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sc
),
1884 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sc
),
1885 GTK_POLICY_AUTOMATIC
,
1886 GTK_POLICY_AUTOMATIC
);
1888 gtk_box_pack_start (GTK_BOX (GTK_DIALOG(dlg
)->vbox
), sc
,
1891 model
= GTK_TREE_MODEL (gtk_list_store_new (N_COLUMNS
, GDK_TYPE_PIXBUF
,
1892 G_TYPE_STRING
, G_TYPE_POINTER
));
1893 view
= gtk_tree_view_new_with_model (model
);
1894 gtk_widget_show (view
);
1895 gtk_container_add (GTK_CONTAINER (sc
), view
);
1897 column
= gtk_tree_view_column_new ();
1898 gtk_tree_view_column_set_sizing (column
,
1899 GTK_TREE_VIEW_COLUMN_AUTOSIZE
);
1900 gtk_tree_view_column_set_title (column
, _("Available Plugins"));
1902 renderer
= gtk_cell_renderer_pixbuf_new ();
1903 gtk_tree_view_column_pack_start (column
, renderer
, FALSE
);
1904 gtk_tree_view_column_add_attribute (column
, renderer
, "pixbuf",
1907 renderer
= gtk_cell_renderer_text_new ();
1908 gtk_tree_view_column_pack_start (column
, renderer
, TRUE
);
1909 gtk_tree_view_column_add_attribute (column
, renderer
, "markup",
1912 gtk_tree_view_append_column (GTK_TREE_VIEW (view
), column
);
1913 gtk_tree_view_set_expander_column (GTK_TREE_VIEW (view
), column
);
1915 g_signal_connect (view
, "row-activated",
1916 G_CALLBACK (on_plugin_list_row_activated
),
1919 gtk_check_button_new_with_label (_("Remember this selection"));
1920 gtk_container_set_border_width (GTK_CONTAINER (remember_checkbox
), 10);
1921 gtk_widget_show (remember_checkbox
);
1922 gtk_box_pack_start (GTK_BOX (GTK_DIALOG(dlg
)->vbox
), remember_checkbox
,
1925 node
= plugin_descriptions
;
1928 GdkPixbuf
*icon_pixbuf
= NULL
;
1929 gchar
*plugin_name
= NULL
;
1930 gchar
*plugin_desc
= NULL
;
1931 gchar
*icon_filename
= NULL
;
1932 gchar
*location
= NULL
;
1934 desc
= (AnjutaPluginDescription
*)node
->data
;
1936 if (anjuta_plugin_description_get_string (desc
,
1941 gchar
*icon_path
= NULL
;
1942 icon_path
= g_strconcat (PACKAGE_PIXMAPS_DIR
"/",
1943 icon_filename
, NULL
);
1944 /* DEBUG_PRINT ("Icon: %s", icon_path); */
1946 gdk_pixbuf_new_from_file (icon_path
, NULL
);
1947 if (icon_pixbuf
== NULL
)
1949 g_warning ("Plugin pixmap not found: %s", plugin_name
);
1955 g_warning ("Plugin does not define Icon attribute");
1957 if (!anjuta_plugin_description_get_locale_string (desc
,
1962 g_warning ("Plugin does not define Name attribute");
1964 if (!anjuta_plugin_description_get_locale_string (desc
,
1969 g_warning ("Plugin does not define Description attribute");
1971 if (!anjuta_plugin_description_get_string (desc
,
1976 g_warning ("Plugin does not define Location attribute");
1979 if (plugin_name
&& plugin_desc
)
1984 text
= g_markup_printf_escaped ("<span size=\"larger\" weight=\"bold\">%s</span>\n%s", plugin_name
, plugin_desc
);
1986 gtk_list_store_append (GTK_LIST_STORE (model
), &iter
);
1987 gtk_list_store_set (GTK_LIST_STORE (model
), &iter
,
1988 PLUGIN_COLUMN
, text
,
1989 PLUGIN_DESCRIPTION_COLUMN
, desc
, -1);
1991 gtk_list_store_set (GTK_LIST_STORE (model
), &iter
,
1992 PIXBUF_COLUMN
, icon_pixbuf
, -1);
1993 g_object_unref (icon_pixbuf
);
1997 selection_ids
= g_list_prepend (selection_ids
, location
);
1999 node
= g_list_next (node
);
2002 /* Prepare remembering key */
2003 selection_ids
= g_list_sort (selection_ids
,
2004 (GCompareFunc
)strcmp
);
2005 node
= selection_ids
;
2008 g_string_append (remember_key
, (gchar
*)node
->data
);
2009 g_string_append (remember_key
, ",");
2010 node
= g_list_next (node
);
2012 g_list_foreach (selection_ids
, (GFunc
) g_free
, NULL
);
2013 g_list_free (selection_ids
);
2015 /* Find if the selection is remembered */
2016 desc
= g_hash_table_lookup (priv
->remember_plugins
, remember_key
->str
);
2019 g_string_free (remember_key
, TRUE
);
2020 gtk_widget_destroy (dlg
);
2025 response
= gtk_dialog_run (GTK_DIALOG (dlg
));
2028 case GTK_RESPONSE_OK
:
2029 selection
= gtk_tree_view_get_selection (GTK_TREE_VIEW (view
));
2030 if (gtk_tree_selection_get_selected (selection
, &store
,
2033 gtk_tree_model_get (model
, &selected
,
2034 PLUGIN_DESCRIPTION_COLUMN
, &desc
, -1);
2037 /* Remember selection */
2038 if (gtk_toggle_button_get_active
2039 (GTK_TOGGLE_BUTTON (remember_checkbox
)))
2041 /* DEBUG_PRINT ("Remembering selection '%s'",
2042 remember_key->str);*/
2043 g_hash_table_insert (priv
->remember_plugins
,
2044 g_strdup (remember_key
->str
), desc
);
2046 g_string_free (remember_key
, TRUE
);
2047 gtk_widget_destroy (dlg
);
2053 g_string_free (remember_key
, TRUE
);
2054 gtk_widget_destroy (dlg
);
2059 anjuta_plugin_manager_select_and_activate (AnjutaPluginManager
*plugin_manager
,
2062 GList
*plugin_descriptions
)
2064 AnjutaPluginDescription
*d
;
2066 g_return_val_if_fail (ANJUTA_IS_PLUGIN_MANAGER (plugin_manager
), NULL
);
2068 d
= anjuta_plugin_manager_select (plugin_manager
, title
, description
,
2069 plugin_descriptions
);
2072 GObject
*plugin
= NULL
;
2073 gchar
*location
= NULL
;
2075 anjuta_plugin_description_get_string (d
,
2079 g_return_val_if_fail (location
!= NULL
, NULL
);
2081 anjuta_plugin_manager_get_plugin_by_id (plugin_manager
, location
);
2088 /* Plugin manager */
2091 anjuta_plugin_manager_init (AnjutaPluginManager
*object
)
2093 object
->priv
= g_new0 (AnjutaPluginManagerPriv
, 1);
2094 object
->priv
->plugins_by_name
= g_hash_table_new (g_str_hash
, g_str_equal
);
2095 object
->priv
->plugins_by_interfaces
= g_hash_table_new_full (g_str_hash
,
2098 (GDestroyNotify
) g_list_free
);
2099 object
->priv
->plugins_by_description
= g_hash_table_new (g_direct_hash
,
2101 object
->priv
->activated_plugins
= g_hash_table_new (g_direct_hash
,
2103 object
->priv
->plugins_cache
= g_hash_table_new (g_direct_hash
,
2105 object
->priv
->remember_plugins
= g_hash_table_new_full (g_str_hash
,
2111 anjuta_plugin_manager_finalize (GObject
*object
)
2113 AnjutaPluginManagerPriv
*priv
;
2114 priv
= ANJUTA_PLUGIN_MANAGER (object
)->priv
;
2115 if (priv
->available_plugins
)
2117 /* anjuta_plugin_manager_unload_all_plugins (ANJUTA_PLUGIN_MANAGER (object)); */
2118 g_list_foreach (priv
->available_plugins
, (GFunc
)g_object_unref
, NULL
);
2119 g_list_free (priv
->available_plugins
);
2120 priv
->available_plugins
= NULL
;
2122 if (priv
->activated_plugins
)
2124 g_hash_table_destroy (priv
->activated_plugins
);
2125 priv
->activated_plugins
= NULL
;
2127 if (priv
->plugins_cache
)
2129 g_hash_table_destroy (priv
->plugins_cache
);
2130 priv
->plugins_cache
= NULL
;
2132 if (priv
->plugins_by_name
)
2134 g_hash_table_destroy (priv
->plugins_by_name
);
2135 priv
->plugins_by_name
= NULL
;
2137 if (priv
->plugins_by_description
)
2139 g_hash_table_destroy (priv
->plugins_by_description
);
2140 priv
->plugins_by_description
= NULL
;
2142 if (priv
->plugins_by_interfaces
)
2144 g_hash_table_destroy (priv
->plugins_by_interfaces
);
2145 priv
->plugins_by_interfaces
= NULL
;
2147 if (priv
->plugin_dirs
)
2149 g_list_foreach (priv
->plugin_dirs
, (GFunc
)g_free
, NULL
);
2150 g_list_free (priv
->plugin_dirs
);
2151 priv
->plugin_dirs
= NULL
;
2154 if (anjuta_c_plugin_factory
)
2156 g_object_unref (anjuta_c_plugin_factory
);
2157 anjuta_c_plugin_factory
= NULL
;
2160 G_OBJECT_CLASS (parent_class
)->finalize (object
);
2164 anjuta_plugin_manager_set_property (GObject
*object
, guint prop_id
,
2165 const GValue
*value
, GParamSpec
*pspec
)
2167 AnjutaPluginManagerPriv
*priv
;
2169 g_return_if_fail (ANJUTA_IS_PLUGIN_MANAGER (object
));
2170 priv
= ANJUTA_PLUGIN_MANAGER (object
)->priv
;
2175 priv
->status
= g_value_get_object (value
);
2178 priv
->shell
= g_value_get_object (value
);
2181 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
2187 anjuta_plugin_manager_get_property (GObject
*object
, guint prop_id
,
2188 GValue
*value
, GParamSpec
*pspec
)
2190 AnjutaPluginManagerPriv
*priv
;
2192 g_return_if_fail (ANJUTA_IS_PLUGIN_MANAGER (object
));
2193 priv
= ANJUTA_PLUGIN_MANAGER (object
)->priv
;
2198 g_value_set_object (value
, priv
->shell
);
2201 g_value_set_object (value
, priv
->status
);
2203 case PROP_AVAILABLE_PLUGINS
:
2204 g_value_set_pointer (value
, priv
->available_plugins
);
2206 case PROP_ACTIVATED_PLUGINS
:
2207 g_value_set_pointer (value
, priv
->activated_plugins
);
2210 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
2215 anjuta_plugin_manager_plugin_activated (AnjutaPluginManager
*self
,
2216 AnjutaPluginDescription
* plugin_desc
,
2219 /* TODO: Add default signal handler implementation here */
2223 anjuta_plugin_manager_plugin_deactivated (AnjutaPluginManager
*self
,
2224 AnjutaPluginDescription
* plugin_desc
,
2227 /* TODO: Add default signal handler implementation here */
2231 anjuta_plugin_manager_class_init (AnjutaPluginManagerClass
*klass
)
2233 GObjectClass
* object_class
= G_OBJECT_CLASS (klass
);
2234 parent_class
= G_OBJECT_CLASS (g_type_class_peek_parent (klass
));
2236 object_class
->finalize
= anjuta_plugin_manager_finalize
;
2237 object_class
->set_property
= anjuta_plugin_manager_set_property
;
2238 object_class
->get_property
= anjuta_plugin_manager_get_property
;
2240 klass
->plugin_activated
= anjuta_plugin_manager_plugin_activated
;
2241 klass
->plugin_deactivated
= anjuta_plugin_manager_plugin_deactivated
;
2243 g_object_class_install_property (object_class
,
2245 g_param_spec_pointer ("profiles",
2247 _("Current stack of profiles"),
2249 g_object_class_install_property (object_class
,
2250 PROP_AVAILABLE_PLUGINS
,
2251 g_param_spec_pointer ("available-plugins",
2252 _("Available plugins"),
2253 _("Currently available plugins found in plugin paths"),
2256 g_object_class_install_property (object_class
,
2257 PROP_ACTIVATED_PLUGINS
,
2258 g_param_spec_pointer ("activated-plugins",
2259 _("Activated plugins"),
2260 _("Currently activated plugins"),
2262 g_object_class_install_property (object_class
,
2264 g_param_spec_object ("shell",
2266 _("Anjuta shell for which the plugins are"),
2270 G_PARAM_CONSTRUCT
));
2271 g_object_class_install_property (object_class
,
2273 g_param_spec_object ("status",
2275 _("Anjuta status to use in loading and unloading of plugins"),
2279 G_PARAM_CONSTRUCT
));
2281 plugin_manager_signals
[PLUGIN_ACTIVATED
] =
2282 g_signal_new ("plugin-activated",
2283 G_OBJECT_CLASS_TYPE (klass
),
2285 G_STRUCT_OFFSET (AnjutaPluginManagerClass
,
2288 anjuta_cclosure_marshal_VOID__POINTER_OBJECT
,
2290 G_TYPE_POINTER
, ANJUTA_TYPE_PLUGIN
);
2292 plugin_manager_signals
[PLUGIN_DEACTIVATED
] =
2293 g_signal_new ("plugin-deactivated",
2294 G_OBJECT_CLASS_TYPE (klass
),
2296 G_STRUCT_OFFSET (AnjutaPluginManagerClass
,
2297 plugin_deactivated
),
2299 anjuta_cclosure_marshal_VOID__POINTER_OBJECT
,
2301 G_TYPE_POINTER
, ANJUTA_TYPE_PLUGIN
);
2305 anjuta_plugin_manager_get_type (void)
2307 static GType our_type
= 0;
2311 static const GTypeInfo our_info
=
2313 sizeof (AnjutaPluginManagerClass
), /* class_size */
2314 (GBaseInitFunc
) NULL
, /* base_init */
2315 (GBaseFinalizeFunc
) NULL
, /* base_finalize */
2316 (GClassInitFunc
) anjuta_plugin_manager_class_init
, /* class_init */
2317 (GClassFinalizeFunc
) NULL
, /* class_finalize */
2318 NULL
/* class_data */,
2319 sizeof (AnjutaPluginManager
), /* instance_size */
2320 0, /* n_preallocs */
2321 (GInstanceInitFunc
) anjuta_plugin_manager_init
, /* instance_init */
2322 NULL
/* value_table */
2324 our_type
= g_type_register_static (G_TYPE_OBJECT
,
2325 "AnjutaPluginManager",
2332 AnjutaPluginManager
*
2333 anjuta_plugin_manager_new (GObject
*shell
, AnjutaStatus
*status
,
2334 GList
* plugins_directories
)
2336 GObject
*manager_object
;
2337 AnjutaPluginManager
*plugin_manager
;
2338 GList
*cycles
= NULL
;
2339 const char *gnome2_path
;
2343 GList
*plugin_dirs
= NULL
;
2345 /* Initialize the anjuta plugin system */
2346 manager_object
= g_object_new (ANJUTA_TYPE_PLUGIN_MANAGER
,
2347 "shell", shell
, "status", status
, NULL
);
2348 plugin_manager
= ANJUTA_PLUGIN_MANAGER (manager_object
);
2350 if (anjuta_plugin_factory
== NULL
)
2352 anjuta_plugin_factory
= anjuta_c_plugin_factory_new ();
2355 gnome2_path
= g_getenv ("GNOME2_PATH");
2357 pathv
= g_strsplit (gnome2_path
, ":", 1);
2359 for (p
= pathv
; *p
!= NULL
; p
++) {
2360 char *path
= g_strdup (*p
);
2361 plugin_dirs
= g_list_prepend (plugin_dirs
, path
);
2366 node
= plugins_directories
;
2370 char *path
= g_strdup (node
->data
);
2371 plugin_dirs
= g_list_prepend (plugin_dirs
, path
);
2372 node
= g_list_next (node
);
2374 plugin_dirs
= g_list_reverse (plugin_dirs
);
2375 /* load_plugins (); */
2380 load_plugins_from_directory (plugin_manager
, (char*)node
->data
);
2381 node
= g_list_next (node
);
2383 resolve_dependencies (plugin_manager
, &cycles
);
2384 g_list_foreach(plugin_dirs
, (GFunc
) g_free
, NULL
);
2385 g_list_free(plugin_dirs
);
2386 return plugin_manager
;
2390 anjuta_plugin_manager_activate_plugins (AnjutaPluginManager
*plugin_manager
,
2391 GList
*plugins_to_activate
)
2393 AnjutaPluginManagerPriv
*priv
;
2394 GdkPixbuf
*icon_pixbuf
;
2397 priv
= plugin_manager
->priv
;
2399 /* Freeze shell operations */
2400 anjuta_shell_freeze (ANJUTA_SHELL (priv
->shell
), NULL
);
2401 if (plugins_to_activate
)
2403 anjuta_status_progress_add_ticks (ANJUTA_STATUS (priv
->status
),
2404 g_list_length (plugins_to_activate
));
2406 node
= plugins_to_activate
;
2409 AnjutaPluginDescription
*d
;
2411 gchar
*icon_filename
, *label
;
2412 gchar
*icon_path
= NULL
;
2418 if (anjuta_plugin_description_get_string (d
, "Anjuta Plugin",
2422 gchar
*title
/*, *description */;
2423 anjuta_plugin_description_get_locale_string (d
, "Anjuta Plugin",
2427 anjuta_plugin_description_get_locale_string (d, "Anjuta Plugin",
2431 icon_path
= g_strconcat (PACKAGE_PIXMAPS_DIR
"/",
2432 icon_filename
, NULL
);
2433 /* DEBUG_PRINT ("Icon: %s", icon_path); */
2434 label
= g_strconcat (_("Loaded: "), title
, "...", NULL
);
2435 icon_pixbuf
= gdk_pixbuf_new_from_file (icon_path
, NULL
);
2437 g_warning ("Plugin does not define Icon: No such file %s",
2440 g_free (icon_filename
);
2444 if (anjuta_plugin_description_get_string (d
, "Anjuta Plugin",
2445 "Location", &plugin_id
))
2447 GObject
*plugin_obj
;
2450 anjuta_plugin_manager_get_plugin_by_id (plugin_manager
,
2454 anjuta_status_progress_tick (ANJUTA_STATUS (priv
->status
),
2455 icon_pixbuf
, label
);
2458 g_object_unref (icon_pixbuf
);
2460 node
= g_list_next (node
);
2463 /* Thaw shell operations */
2464 anjuta_shell_thaw (ANJUTA_SHELL (priv
->shell
), NULL
);
2468 on_collect (gpointer key
, gpointer value
, gpointer user_data
)
2471 gchar
*query
= (gchar
*) key
;
2472 AnjutaPluginDescription
*desc
= (AnjutaPluginDescription
*) value
;
2473 GString
*write_buffer
= (GString
*) user_data
;
2475 anjuta_plugin_description_get_string (desc
, "Anjuta Plugin", "Location",
2477 g_string_append_printf (write_buffer
, "%s=%s;", query
, id
);
2482 anjuta_plugin_manager_get_remembered_plugins (AnjutaPluginManager
*plugin_manager
)
2484 AnjutaPluginManagerPriv
*priv
;
2485 GString
*write_buffer
= g_string_new ("");
2487 g_return_val_if_fail (ANJUTA_IS_PLUGIN_MANAGER (plugin_manager
), FALSE
);
2489 priv
= plugin_manager
->priv
;
2490 g_hash_table_foreach (priv
->remember_plugins
, on_collect
,
2492 return g_string_free (write_buffer
, FALSE
);
2496 on_foreach_remove_true (gpointer k
, gpointer v
, gpointer d
)
2502 anjuta_plugin_manager_set_remembered_plugins (AnjutaPluginManager
*plugin_manager
,
2503 const gchar
*remembered_plugins
)
2505 AnjutaPluginManagerPriv
*priv
;
2506 gchar
**strv_lines
, **line_idx
;
2508 g_return_if_fail (ANJUTA_IS_PLUGIN_MANAGER (plugin_manager
));
2509 g_return_if_fail (remembered_plugins
!= NULL
);
2511 priv
= plugin_manager
->priv
;
2513 g_hash_table_foreach_remove (priv
->remember_plugins
,
2514 on_foreach_remove_true
, NULL
);
2516 strv_lines
= g_strsplit (remembered_plugins
, ";", -1);
2517 line_idx
= strv_lines
;
2520 gchar
**strv_keyvals
;
2521 strv_keyvals
= g_strsplit (*line_idx
, "=", -1);
2522 if (strv_keyvals
&& strv_keyvals
[0] && strv_keyvals
[1])
2524 AnjutaPluginHandle
*plugin
;
2525 plugin
= g_hash_table_lookup (priv
->plugins_by_name
,
2529 AnjutaPluginDescription
*desc
;
2530 desc
= anjuta_plugin_handle_get_description (plugin
);
2532 DEBUG_PRINT ("Restoring remember plugin: %s=%s",
2536 g_hash_table_insert (priv
->remember_plugins
,
2537 g_strdup (strv_keyvals
[0]), desc
);
2539 g_strfreev (strv_keyvals
);
2543 g_strfreev (strv_lines
);