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
34 #include <sys/types.h>
38 #include <libanjuta/anjuta-plugin-manager.h>
39 #include <libanjuta/anjuta-marshal.h>
40 #include <libanjuta/anjuta-debug.h>
41 #include <libanjuta/anjuta-plugin-handle.h>
42 #include <libanjuta/anjuta-plugin.h>
43 #include <libanjuta/anjuta-c-plugin-factory.h>
44 #include <libanjuta/interfaces/ianjuta-plugin-factory.h>
45 #include <libanjuta/interfaces/ianjuta-preferences.h>
55 PROP_AVAILABLE_PLUGINS
,
56 PROP_ACTIVATED_PLUGINS
71 struct _AnjutaPluginManagerPriv
76 GList
*available_plugins
;
78 /* Indexes => plugin handles */
79 GHashTable
*plugins_by_interfaces
;
80 GHashTable
*plugins_by_name
;
81 GHashTable
*plugins_by_description
;
83 /* Plugins that are currently activated */
84 GHashTable
*activated_plugins
;
86 /* Plugins that have been previously loaded but current deactivated */
87 GHashTable
*plugins_cache
;
89 /* Remember plugin selection */
90 GHashTable
*remember_plugins
;
93 /* Available plugins page treeview */
103 /* Remembered plugins page treeview */
111 /* Plugin class types */
113 static AnjutaCPluginFactory
*anjuta_plugin_factory
= NULL
;
115 static GObjectClass
* parent_class
= NULL
;
116 static guint plugin_manager_signals
[LAST_SIGNAL
] = { 0 };
118 static GHashTable
* plugin_set_update (AnjutaPluginManager
*plugin_manager
,
119 AnjutaPluginHandle
* selected_plugin
,
122 static IAnjutaPluginFactory
* get_plugin_factory (AnjutaPluginManager
*plugin_manager
,
123 const gchar
*language
, GError
**error
);
126 anjuta_plugin_manager_error_quark (void)
128 static GQuark quark
= 0;
131 quark
= g_quark_from_static_string ("anjuta-plugin-manager-quark");
136 /** Dependency Resolution **/
139 collect_cycle (AnjutaPluginManager
*plugin_manager
,
140 AnjutaPluginHandle
*base_plugin
, AnjutaPluginHandle
*cur_plugin
,
143 AnjutaPluginManagerPriv
*priv
;
146 priv
= plugin_manager
->priv
;
148 for (l
= anjuta_plugin_handle_get_dependency_names (cur_plugin
);
149 l
!= NULL
; l
= l
->next
)
151 AnjutaPluginHandle
*dep
= g_hash_table_lookup (priv
->plugins_by_name
,
155 if (dep
== base_plugin
)
157 *cycle
= g_list_prepend (NULL
, dep
);
158 /* DEBUG_PRINT ("%s", anjuta_plugin_handle_get_name (dep)); */
163 if (collect_cycle (plugin_manager
, base_plugin
, dep
, cycle
))
165 *cycle
= g_list_prepend (*cycle
, dep
);
166 /* DEBUG_PRINT ("%s", anjuta_plugin_handle_get_name (dep)); */
176 add_dependency (AnjutaPluginHandle
*dependent
, AnjutaPluginHandle
*dependency
)
178 g_hash_table_insert (anjuta_plugin_handle_get_dependents (dependency
),
179 dependent
, dependency
);
180 g_hash_table_insert (anjuta_plugin_handle_get_dependencies (dependent
),
181 dependency
, dependent
);
185 child_dep_foreach_cb (gpointer key
, gpointer value
, gpointer user_data
)
187 add_dependency (ANJUTA_PLUGIN_HANDLE (user_data
),
188 ANJUTA_PLUGIN_HANDLE (key
));
191 /* Resolves dependencies for a single module recursively. Shortcuts if
192 * the module has already been resolved. Returns a list representing
193 * any cycles found, or NULL if no cycles are found. If a cycle is found,
194 * the graph is left unresolved.
197 resolve_for_module (AnjutaPluginManager
*plugin_manager
,
198 AnjutaPluginHandle
*plugin
, int pass
)
200 AnjutaPluginManagerPriv
*priv
;
204 priv
= plugin_manager
->priv
;
206 if (anjuta_plugin_handle_get_checked (plugin
))
211 if (anjuta_plugin_handle_get_resolve_pass (plugin
) == pass
)
214 g_warning ("cycle found: %s on pass %d",
215 anjuta_plugin_handle_get_name (plugin
),
216 anjuta_plugin_handle_get_resolve_pass (plugin
));
217 collect_cycle (plugin_manager
, plugin
, plugin
, &cycle
);
221 if (anjuta_plugin_handle_get_resolve_pass (plugin
) != -1)
226 anjuta_plugin_handle_set_can_load (plugin
, TRUE
);
227 anjuta_plugin_handle_set_resolve_pass (plugin
, pass
);
229 for (l
= anjuta_plugin_handle_get_dependency_names (plugin
);
230 l
!= NULL
; l
= l
->next
)
233 AnjutaPluginHandle
*child
=
234 g_hash_table_lookup (priv
->plugins_by_name
, dep
);
237 ret
= resolve_for_module (plugin_manager
, child
, pass
);
243 /* Add the dependency's dense dependency list
244 * to the current module's dense dependency list */
245 g_hash_table_foreach (anjuta_plugin_handle_get_dependencies (child
),
246 child_dep_foreach_cb
, plugin
);
247 add_dependency (plugin
, child
);
249 /* If the child can't load due to dependency problems,
250 * the current module can't either */
251 anjuta_plugin_handle_set_can_load (plugin
,
252 anjuta_plugin_handle_get_can_load (child
));
254 g_warning ("Dependency %s not found.\n", dep
);
255 anjuta_plugin_handle_set_can_load (plugin
, FALSE
);
259 anjuta_plugin_handle_set_checked (plugin
, TRUE
);
264 /* Clean up the results of a resolving run */
266 unresolve_dependencies (AnjutaPluginManager
*plugin_manager
)
268 AnjutaPluginManagerPriv
*priv
;
271 priv
= plugin_manager
->priv
;
273 for (l
= priv
->available_plugins
; l
!= NULL
; l
= l
->next
)
275 AnjutaPluginHandle
*plugin
= l
->data
;
276 anjuta_plugin_handle_unresolve_dependencies (plugin
);
283 prune_modules (AnjutaPluginManager
*plugin_manager
, GList
*modules
)
285 AnjutaPluginManagerPriv
*priv
;
288 priv
= plugin_manager
->priv
;
290 for (l
= modules
; l
!= NULL
; l
= l
->next
) {
291 AnjutaPluginHandle
*plugin
= l
->data
;
293 g_hash_table_remove (priv
->plugins_by_name
,
294 anjuta_plugin_handle_get_id (plugin
));
295 priv
->available_plugins
= g_list_remove (priv
->available_plugins
, plugin
);
300 dependency_compare (AnjutaPluginHandle
*plugin_a
,
301 AnjutaPluginHandle
*plugin_b
)
303 int a
= g_hash_table_size (anjuta_plugin_handle_get_dependencies (plugin_a
));
304 int b
= g_hash_table_size (anjuta_plugin_handle_get_dependencies (plugin_b
));
309 /* Resolves the dependencies of the priv->available_plugins list. When this
310 * function is complete, the following will be true:
312 * 1) The dependencies and dependents hash tables of the modules will
315 * 2) Cycles in the graph will be removed.
317 * 3) Modules which cannot be loaded due to failed dependencies will
320 * 4) priv->available_plugins will be sorted such that no module depends on a
323 * If a cycle in the graph is found, it is pruned from the tree and
324 * returned as a list stored in the cycles list.
327 resolve_dependencies (AnjutaPluginManager
*plugin_manager
, GList
**cycles
)
329 AnjutaPluginManagerPriv
*priv
;
333 priv
= plugin_manager
->priv
;
336 /* Try resolving dependencies. If there is a cycle, prune the
337 * cycle and try to resolve again */
342 for (l
= priv
->available_plugins
; l
!= NULL
&& !cycle
; l
= l
->next
) {
343 cycle
= resolve_for_module (plugin_manager
, l
->data
, pass
++);
347 *cycles
= g_list_prepend (*cycles
, cycle
);
348 prune_modules (plugin_manager
, cycle
);
349 unresolve_dependencies (plugin_manager
);
353 /* Now that there is a fully resolved dependency tree, sort
354 * priv->available_plugins to create a valid load order */
355 priv
->available_plugins
= g_list_sort (priv
->available_plugins
,
356 (GCompareFunc
)dependency_compare
);
359 /* Plugins loading */
362 str_has_suffix (const char *haystack
, const char *needle
)
366 if (needle
== NULL
) {
369 if (haystack
== NULL
) {
370 return needle
[0] == '\0';
373 /* Eat one character at a time. */
374 h
= haystack
+ strlen(haystack
);
375 n
= needle
+ strlen(needle
);
383 } while (*--h
== *--n
);
388 load_plugin (AnjutaPluginManager
*plugin_manager
,
389 const gchar
*plugin_desc_path
)
391 AnjutaPluginManagerPriv
*priv
;
392 AnjutaPluginHandle
*plugin_handle
;
394 g_return_if_fail (ANJUTA_IS_PLUGIN_MANAGER (plugin_manager
));
395 priv
= plugin_manager
->priv
;
397 plugin_handle
= anjuta_plugin_handle_new (plugin_desc_path
);
400 if (g_hash_table_lookup (priv
->plugins_by_name
,
401 anjuta_plugin_handle_get_id (plugin_handle
)))
403 g_object_unref (plugin_handle
);
408 /* Available plugin */
409 priv
->available_plugins
= g_list_prepend (priv
->available_plugins
,
412 g_hash_table_insert (priv
->plugins_by_name
,
413 (gchar
*)anjuta_plugin_handle_get_id (plugin_handle
),
416 /* Index by description */
417 g_hash_table_insert (priv
->plugins_by_description
,
418 anjuta_plugin_handle_get_description (plugin_handle
),
421 /* Index by interfaces exported by this plugin */
422 node
= anjuta_plugin_handle_get_interfaces (plugin_handle
);
431 objs
= (GList
*)g_hash_table_lookup (priv
->plugins_by_interfaces
, iface
);
437 if (obj_node
->data
== plugin_handle
)
442 obj_node
= g_list_next (obj_node
);
446 g_hash_table_steal (priv
->plugins_by_interfaces
, iface
);
447 objs
= g_list_prepend (objs
, plugin_handle
);
448 g_hash_table_insert (priv
->plugins_by_interfaces
, iface
, objs
);
450 node
= g_list_next (node
);
458 load_plugins_from_directory (AnjutaPluginManager
* plugin_manager
,
459 const gchar
*dirname
)
462 struct dirent
*entry
;
464 dir
= opendir (dirname
);
471 for (entry
= readdir (dir
); entry
!= NULL
; entry
= readdir (dir
))
473 if (str_has_suffix (entry
->d_name
, ".plugin"))
476 pathname
= g_strdup_printf ("%s/%s", dirname
, entry
->d_name
);
477 load_plugin (plugin_manager
,pathname
);
484 /* Plugin activation and deactivation */
487 on_plugin_activated (AnjutaPlugin
*plugin_object
, AnjutaPluginHandle
*plugin
)
489 AnjutaPluginManager
*plugin_manager
;
490 AnjutaPluginManagerPriv
*priv
;
492 /* FIXME: Pass plugin_manager directly in signal arguments */
493 plugin_manager
= anjuta_shell_get_plugin_manager (plugin_object
->shell
, NULL
);
495 g_return_if_fail(plugin_manager
!= NULL
);
497 priv
= plugin_manager
->priv
;
499 g_hash_table_insert (priv
->activated_plugins
, plugin
,
500 G_OBJECT (plugin_object
));
501 if (g_hash_table_lookup (priv
->plugins_cache
, plugin
))
502 g_hash_table_remove (priv
->plugins_cache
, plugin
);
504 g_signal_emit_by_name (plugin_manager
, "plugin-activated",
505 anjuta_plugin_handle_get_description (plugin
),
510 on_plugin_deactivated (AnjutaPlugin
*plugin_object
, AnjutaPluginHandle
*plugin
)
512 AnjutaPluginManager
*plugin_manager
;
513 AnjutaPluginManagerPriv
*priv
;
515 /* FIXME: Pass plugin_manager directly in signal arguments */
516 plugin_manager
= anjuta_shell_get_plugin_manager (plugin_object
->shell
, NULL
);
518 g_return_if_fail (plugin_manager
!= NULL
);
520 priv
= plugin_manager
->priv
;
522 g_hash_table_insert (priv
->plugins_cache
, plugin
, G_OBJECT (plugin_object
));
523 g_hash_table_remove (priv
->activated_plugins
, plugin
);
525 g_signal_emit_by_name (plugin_manager
, "plugin-deactivated",
526 anjuta_plugin_handle_get_description (plugin
),
531 activate_plugin (AnjutaPluginManager
*plugin_manager
,
532 AnjutaPluginHandle
*handle
, GError
**error
)
534 AnjutaPluginManagerPriv
*priv
;
535 IAnjutaPluginFactory
* factory
;
536 AnjutaPlugin
*plugin
;
537 const gchar
*plugin_id
;
538 const gchar
*language
;
541 priv
= plugin_manager
->priv
;
543 plugin_id
= anjuta_plugin_handle_get_id (handle
);
545 resident
= anjuta_plugin_handle_get_resident (handle
);
546 language
= anjuta_plugin_handle_get_language (handle
);
548 factory
= get_plugin_factory (plugin_manager
, language
, error
);
549 if (factory
== NULL
) return NULL
;
551 plugin
= ianjuta_plugin_factory_new_plugin (factory
, handle
, ANJUTA_SHELL (priv
->shell
), error
);
557 g_signal_connect (plugin
, "activated",
558 G_CALLBACK (on_plugin_activated
), handle
);
559 g_signal_connect (plugin
, "deactivated",
560 G_CALLBACK (on_plugin_deactivated
), handle
);
566 g_hashtable_foreach_true (gpointer key
, gpointer value
, gpointer user_data
)
572 anjuta_plugin_manager_unload_all_plugins (AnjutaPluginManager
*plugin_manager
)
574 AnjutaPluginManagerPriv
*priv
;
576 priv
= plugin_manager
->priv
;
577 if (g_hash_table_size (priv
->activated_plugins
) > 0 ||
578 g_hash_table_size (priv
->plugins_cache
) > 0)
580 priv
->available_plugins
= g_list_reverse (priv
->available_plugins
);
581 if (g_hash_table_size (priv
->activated_plugins
) > 0)
584 node
= priv
->available_plugins
;
587 AnjutaPluginHandle
*selected_plugin
= node
->data
;
588 if (g_hash_table_lookup (priv
->activated_plugins
, selected_plugin
))
590 plugin_set_update (plugin_manager
, selected_plugin
, FALSE
);
591 /* DEBUG_PRINT ("Unloading plugin: %s",
592 anjuta_plugin_handle_get_id (selected_plugin));
595 node
= g_list_next (node
);
597 g_hash_table_foreach_remove (priv
->activated_plugins
,
598 g_hashtable_foreach_true
, NULL
);
600 if (g_hash_table_size (priv
->plugins_cache
) > 0)
603 node
= priv
->available_plugins
;
607 AnjutaPluginHandle
*selected_plugin
= node
->data
;
609 plugin_obj
= g_hash_table_lookup (priv
->plugins_cache
,
613 /* DEBUG_PRINT ("Destroying plugin: %s",
614 anjuta_plugin_handle_get_id (selected_plugin));
616 g_object_unref (plugin_obj
);
618 node
= g_list_next (node
);
620 g_hash_table_foreach_remove (priv
->plugins_cache
,
621 g_hashtable_foreach_true
, NULL
);
623 priv
->available_plugins
= g_list_reverse (priv
->available_plugins
);
628 should_unload (GHashTable
*activated_plugins
, AnjutaPluginHandle
*plugin_to_unload
,
629 AnjutaPluginHandle
*plugin
)
631 GObject
*plugin_obj
= g_hash_table_lookup (activated_plugins
, plugin
);
636 if (plugin_to_unload
== plugin
)
640 GPOINTER_TO_INT (g_hash_table_lookup (anjuta_plugin_handle_get_dependents (plugin
),
646 should_load (GHashTable
*activated_plugins
, AnjutaPluginHandle
*plugin_to_load
,
647 AnjutaPluginHandle
*plugin
)
649 GObject
*plugin_obj
= g_hash_table_lookup (activated_plugins
, plugin
);
654 if (plugin_to_load
== plugin
)
655 return anjuta_plugin_handle_get_can_load (plugin
);
657 gboolean dependency
=
658 GPOINTER_TO_INT (g_hash_table_lookup (anjuta_plugin_handle_get_dependencies (plugin_to_load
),
660 return (dependency
&& anjuta_plugin_handle_get_can_load (plugin
));
663 static AnjutaPluginHandle
*
664 plugin_for_iter (GtkListStore
*store
, GtkTreeIter
*iter
)
666 AnjutaPluginHandle
*plugin
;
668 gtk_tree_model_get (GTK_TREE_MODEL (store
), iter
, COL_PLUGIN
, &plugin
, -1);
673 update_enabled (GtkTreeModel
*model
, GHashTable
*activated_plugins
)
677 if (gtk_tree_model_get_iter_first (model
, &iter
)) {
679 AnjutaPluginHandle
*plugin
;
683 plugin
= plugin_for_iter(GTK_LIST_STORE(model
), &iter
);
684 plugin_obj
= g_hash_table_lookup (activated_plugins
, plugin
);
685 installed
= (plugin_obj
!= NULL
) ? TRUE
: FALSE
;
686 gtk_tree_model_get (model
, &iter
, COL_PLUGIN
, &plugin
, -1);
687 gtk_list_store_set (GTK_LIST_STORE (model
), &iter
,
688 COL_ENABLED
, installed
, -1);
689 } while (gtk_tree_model_iter_next (model
, &iter
));
694 plugin_set_update (AnjutaPluginManager
*plugin_manager
,
695 AnjutaPluginHandle
* selected_plugin
,
698 AnjutaPluginManagerPriv
*priv
;
702 priv
= plugin_manager
->priv
;
703 plugin_obj
= g_hash_table_lookup (priv
->activated_plugins
, selected_plugin
);
705 if (plugin_obj
&& load
)
707 g_warning ("Trying to install already installed plugin '%s'",
708 anjuta_plugin_handle_get_name (selected_plugin
));
709 return priv
->activated_plugins
;
711 if (!plugin_obj
&& !load
)
713 g_warning ("Trying to uninstall a not installed plugin '%s'",
714 anjuta_plugin_handle_get_name (selected_plugin
));
715 return priv
->activated_plugins
;
719 anjuta_status_busy_push (priv
->status
);
723 /* reverse priv->available_plugins when unloading, so that plugins are
724 * unloaded in the right order */
725 priv
->available_plugins
= g_list_reverse (priv
->available_plugins
);
727 for (l
= priv
->available_plugins
; l
!= NULL
; l
= l
->next
)
729 AnjutaPluginHandle
*plugin
= l
->data
;
730 if (should_unload (priv
->activated_plugins
, selected_plugin
, plugin
))
732 /* FIXME: Unload the class and sharedlib if possible */
733 AnjutaPlugin
*anjuta_plugin
= ANJUTA_PLUGIN (plugin_obj
);
734 if (!anjuta_plugin_deactivate (ANJUTA_PLUGIN (anjuta_plugin
)))
736 anjuta_util_dialog_info (GTK_WINDOW (priv
->shell
),
737 dgettext (GETTEXT_PACKAGE
, "Plugin '%s' does not want to be deactivated"),
738 anjuta_plugin_handle_get_name (plugin
));
742 priv
->available_plugins
= g_list_reverse (priv
->available_plugins
);
746 for (l
= priv
->available_plugins
; l
!= NULL
; l
= l
->next
)
748 AnjutaPluginHandle
*plugin
= l
->data
;
749 if (should_load (priv
->activated_plugins
, selected_plugin
, plugin
))
751 AnjutaPlugin
*plugin_obj
;
752 GError
*error
= NULL
;
753 plugin_obj
= g_hash_table_lookup (priv
->plugins_cache
, plugin
);
756 plugin_obj
= activate_plugin (plugin_manager
, plugin
,
762 anjuta_plugin_activate (ANJUTA_PLUGIN (plugin_obj
));
768 gchar
* message
= g_strdup_printf (dgettext (GETTEXT_PACKAGE
, "Could not load %s\n"
769 "This usually means that your installation is corrupted. The "
770 "error message leading to this was:\n%s"),
771 anjuta_plugin_handle_get_name (selected_plugin
),
773 anjuta_util_dialog_error (GTK_WINDOW(plugin_manager
->priv
->shell
),
775 g_error_free (error
);
783 anjuta_status_busy_pop (priv
->status
);
784 return priv
->activated_plugins
;
788 plugin_toggled (GtkCellRendererToggle
*cell
, char *path_str
, gpointer data
)
790 AnjutaPluginManager
*plugin_manager
;
791 AnjutaPluginManagerPriv
*priv
;
792 GtkListStore
*store
= GTK_LIST_STORE (data
);
795 AnjutaPluginHandle
*plugin
;
797 GList
*activated_plugins
;
799 AnjutaPlugin
* plugin_object
;
801 path
= gtk_tree_path_new_from_string (path_str
);
803 plugin_manager
= g_object_get_data (G_OBJECT (store
), "plugin-manager");
804 priv
= plugin_manager
->priv
;
806 gtk_tree_model_get_iter (GTK_TREE_MODEL (store
), &iter
, path
);
807 gtk_tree_model_get (GTK_TREE_MODEL (store
), &iter
,
808 COL_ENABLED
, &enabled
,
812 /* Activate one plugin can force the loading of other ones, instead of
813 * searching which plugins have to be activated, we just unmerge all
814 * current plugins and merge all plugins after the modification */
816 /* unmerge all plugins */
817 activated_plugins
= g_hash_table_get_values (priv
->activated_plugins
);
818 for (node
= g_list_first (activated_plugins
); node
!= NULL
; node
= g_list_next (node
))
820 plugin_object
= (AnjutaPlugin
*)node
->data
;
822 IANJUTA_IS_PREFERENCES(plugin_object
))
824 ianjuta_preferences_unmerge (IANJUTA_PREFERENCES (plugin_object
),
825 anjuta_shell_get_preferences (ANJUTA_SHELL (priv
->shell
), NULL
),
829 g_list_free (activated_plugins
);
831 plugin_set_update (plugin_manager
, plugin
, !enabled
);
833 /* Make sure that it appears in the preferences. This method
834 can only be called when the preferences dialog is active so
837 activated_plugins
= g_hash_table_get_values (priv
->activated_plugins
);
838 for (node
= g_list_first (activated_plugins
); node
!= NULL
; node
= g_list_next (node
))
840 plugin_object
= (AnjutaPlugin
*)node
->data
;
842 IANJUTA_IS_PREFERENCES(plugin_object
))
844 ianjuta_preferences_merge (IANJUTA_PREFERENCES (plugin_object
),
845 anjuta_shell_get_preferences (ANJUTA_SHELL (priv
->shell
), NULL
),
849 g_list_free (activated_plugins
);
851 update_enabled (GTK_TREE_MODEL (store
), priv
->activated_plugins
);
852 gtk_tree_path_free (path
);
857 selection_changed (GtkTreeSelection
*selection
, GtkListStore
*store
)
861 if (gtk_tree_selection_get_selected (selection
, NULL
,
863 GtkTextBuffer
*buffer
;
865 GtkWidget
*txt
= g_object_get_data (G_OBJECT (store
),
868 GtkWidget
*image
= g_object_get_data (G_OBJECT (store
),
870 AnjutaPluginHandle
*plugin
= plugin_for_iter (store
, &iter
);
872 buffer
= gtk_text_view_get_buffer (GTK_TEXT_VIEW (txt
));
873 gtk_text_buffer_set_text (buffer
, plugin
->about
, -1);
875 if (plugin
->icon_path
) {
876 gtk_image_set_from_file (GTK_IMAGE (image
),
878 gtk_widget_show (GTK_WIDGET (image
));
880 gtk_widget_hide (GTK_WIDGET (image
));
887 create_plugin_tree (void)
891 GtkCellRenderer
*renderer
;
892 GtkTreeViewColumn
*column
;
894 store
= gtk_list_store_new (N_COLS
,
900 tree
= gtk_tree_view_new_with_model (GTK_TREE_MODEL (store
));
902 renderer
= gtk_cell_renderer_toggle_new ();
903 g_signal_connect (G_OBJECT (renderer
), "toggled",
904 G_CALLBACK (plugin_toggled
), store
);
905 column
= gtk_tree_view_column_new_with_attributes (dgettext (GETTEXT_PACKAGE
, "Load"),
912 gtk_tree_view_append_column (GTK_TREE_VIEW (tree
), column
);
913 gtk_tree_view_column_set_sizing (column
,
914 GTK_TREE_VIEW_COLUMN_AUTOSIZE
);
916 column
= gtk_tree_view_column_new ();
917 renderer
= gtk_cell_renderer_pixbuf_new ();
918 gtk_tree_view_column_pack_start (column
, renderer
, FALSE
);
919 gtk_tree_view_column_add_attribute (column
, renderer
, "pixbuf",
921 renderer
= gtk_cell_renderer_text_new ();
922 g_object_set(renderer
, "ellipsize", PANGO_ELLIPSIZE_END
, NULL
);
923 gtk_tree_view_column_pack_start (column
, renderer
, TRUE
);
924 gtk_tree_view_column_add_attribute (column
, renderer
, "markup",
926 gtk_tree_view_column_set_sizing (column
,
927 GTK_TREE_VIEW_COLUMN_AUTOSIZE
);
928 gtk_tree_view_column_set_title (column
, dgettext (GETTEXT_PACKAGE
, "Available Plugins"));
929 gtk_tree_view_append_column (GTK_TREE_VIEW (tree
), column
);
930 gtk_tree_view_set_expander_column (GTK_TREE_VIEW (tree
), column
);
932 g_object_unref (store
);
936 /* Sort function for plugins */
938 sort_plugins(gconstpointer a
, gconstpointer b
)
940 g_return_val_if_fail (a
!= NULL
, 0);
941 g_return_val_if_fail (b
!= NULL
, 0);
943 AnjutaPluginHandle
* plugin_a
= ANJUTA_PLUGIN_HANDLE (a
);
944 AnjutaPluginHandle
* plugin_b
= ANJUTA_PLUGIN_HANDLE (b
);
946 return strcmp (anjuta_plugin_handle_get_name (plugin_a
),
947 anjuta_plugin_handle_get_name (plugin_b
));
950 /* If show_all == FALSE, show only user activatable plugins
951 * If show_all == TRUE, show all plugins
954 populate_plugin_model (AnjutaPluginManager
*plugin_manager
,
956 GHashTable
*plugins_to_show
,
957 GHashTable
*activated_plugins
,
960 AnjutaPluginManagerPriv
*priv
;
963 priv
= plugin_manager
->priv
;
964 gtk_list_store_clear (store
);
966 priv
->available_plugins
= g_list_sort (priv
->available_plugins
, sort_plugins
);
968 for (l
= priv
->available_plugins
; l
!= NULL
; l
= l
->next
)
970 AnjutaPluginHandle
*plugin
= l
->data
;
972 /* If plugins to show is NULL, show all available plugins */
973 if (plugins_to_show
== NULL
||
974 g_hash_table_lookup (plugins_to_show
, plugin
))
977 gboolean enable
= FALSE
;
978 if (g_hash_table_lookup (activated_plugins
, plugin
))
981 if (anjuta_plugin_handle_get_name (plugin
) &&
982 anjuta_plugin_handle_get_description (plugin
) &&
983 (anjuta_plugin_handle_get_user_activatable (plugin
) ||
989 text
= g_markup_printf_escaped ("<span size=\"larger\" weight=\"bold\">%s</span>\n%s",
990 anjuta_plugin_handle_get_name (plugin
),
991 anjuta_plugin_handle_get_about (plugin
));
993 gtk_list_store_append (store
, &iter
);
994 gtk_list_store_set (store
, &iter
,
996 anjuta_plugin_handle_get_user_activatable (plugin
),
1001 if (anjuta_plugin_handle_get_icon_path (plugin
))
1004 icon
= gdk_pixbuf_new_from_file_at_size (anjuta_plugin_handle_get_icon_path (plugin
),
1007 gtk_list_store_set (store
, &iter
,
1008 COL_ICON
, icon
, -1);
1009 g_object_unref (icon
);
1019 create_remembered_plugins_tree (void)
1021 GtkListStore
*store
;
1023 GtkCellRenderer
*renderer
;
1024 GtkTreeViewColumn
*column
;
1026 store
= gtk_list_store_new (N_REM_COLS
, GDK_TYPE_PIXBUF
, G_TYPE_STRING
,
1028 tree
= gtk_tree_view_new_with_model (GTK_TREE_MODEL (store
));
1030 column
= gtk_tree_view_column_new ();
1031 renderer
= gtk_cell_renderer_pixbuf_new ();
1032 gtk_tree_view_column_pack_start (column
, renderer
, FALSE
);
1033 gtk_tree_view_column_add_attribute (column
, renderer
, "pixbuf",
1035 renderer
= gtk_cell_renderer_text_new ();
1036 gtk_tree_view_column_pack_start (column
, renderer
, FALSE
);
1037 gtk_tree_view_column_add_attribute (column
, renderer
, "markup",
1039 gtk_tree_view_column_set_sizing (column
,
1040 GTK_TREE_VIEW_COLUMN_AUTOSIZE
);
1041 gtk_tree_view_column_set_title (column
, dgettext (GETTEXT_PACKAGE
, "Preferred plugins"));
1042 gtk_tree_view_append_column (GTK_TREE_VIEW (tree
), column
);
1043 gtk_tree_view_set_expander_column (GTK_TREE_VIEW (tree
), column
);
1045 g_object_unref (store
);
1050 foreach_remembered_plugin (gpointer key
, gpointer value
, gpointer user_data
)
1052 AnjutaPluginDescription
*desc
= (AnjutaPluginDescription
*) value
;
1053 GtkListStore
*store
= GTK_LIST_STORE (user_data
);
1054 AnjutaPluginManager
*manager
= g_object_get_data (G_OBJECT (store
),
1056 AnjutaPluginHandle
*plugin
=
1057 g_hash_table_lookup (manager
->priv
->plugins_by_description
, desc
);
1058 g_return_if_fail (plugin
!= NULL
);
1060 if (anjuta_plugin_handle_get_name (plugin
) &&
1061 anjuta_plugin_handle_get_description (plugin
))
1066 text
= g_markup_printf_escaped ("<span size=\"larger\" weight=\"bold\">%s</span>\n%s",
1067 anjuta_plugin_handle_get_name (plugin
),
1068 anjuta_plugin_handle_get_about (plugin
));
1070 gtk_list_store_append (store
, &iter
);
1071 gtk_list_store_set (store
, &iter
,
1073 COL_REM_PLUGIN_KEY
, key
,
1075 if (anjuta_plugin_handle_get_icon_path (plugin
))
1078 icon
= gdk_pixbuf_new_from_file_at_size (anjuta_plugin_handle_get_icon_path (plugin
),
1081 gtk_list_store_set (store
, &iter
,
1082 COL_REM_ICON
, icon
, -1);
1083 g_object_unref (icon
);
1091 populate_remembered_plugins_model (AnjutaPluginManager
*plugin_manager
,
1092 GtkListStore
*store
)
1094 AnjutaPluginManagerPriv
*priv
= plugin_manager
->priv
;
1095 gtk_list_store_clear (store
);
1096 g_hash_table_foreach (priv
->remember_plugins
, foreach_remembered_plugin
,
1101 on_show_all_plugins_toggled (GtkToggleButton
*button
, GtkListStore
*store
)
1103 AnjutaPluginManager
*plugin_manager
;
1105 plugin_manager
= g_object_get_data (G_OBJECT (button
), "__plugin_manager");
1107 populate_plugin_model (plugin_manager
, store
, NULL
,
1108 plugin_manager
->priv
->activated_plugins
,
1109 !gtk_toggle_button_get_active (button
));
1113 on_forget_plugin_clicked (GtkWidget
*button
, GtkTreeView
*view
)
1116 GtkTreeModel
*model
;
1117 GtkTreeSelection
*selection
= gtk_tree_view_get_selection (view
);
1118 if (gtk_tree_selection_get_selected (selection
, &model
, &iter
))
1121 AnjutaPluginManager
*manager
= g_object_get_data (G_OBJECT (model
),
1123 gtk_tree_model_get (model
, &iter
, COL_REM_PLUGIN_KEY
, &plugin_key
, -1);
1124 g_hash_table_remove (manager
->priv
->remember_plugins
, plugin_key
);
1125 gtk_list_store_remove (GTK_LIST_STORE (model
), &iter
);
1126 g_free (plugin_key
);
1131 on_forget_plugin_sel_changed (GtkTreeSelection
*selection
,
1136 if (gtk_tree_selection_get_selected (selection
, NULL
, &iter
))
1137 gtk_widget_set_sensitive (button
, TRUE
);
1139 gtk_widget_set_sensitive (button
, FALSE
);
1143 anjuta_plugin_manager_get_plugins_page (AnjutaPluginManager
*plugin_manager
)
1146 GtkWidget
*checkbutton
;
1148 GtkWidget
*scrolled
;
1150 GtkWidget
*toolitem
;
1151 GtkListStore
*store
;
1154 vbox
= gtk_vbox_new (FALSE
, 0);
1155 gtk_container_set_border_width (GTK_CONTAINER (vbox
), 6);
1157 scrolled
= gtk_scrolled_window_new (NULL
, NULL
);
1158 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled
),
1160 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled
),
1162 GTK_POLICY_AUTOMATIC
);
1163 gtk_style_context_set_junction_sides (gtk_widget_get_style_context (scrolled
), GTK_JUNCTION_BOTTOM
);
1164 gtk_box_pack_start (GTK_BOX (vbox
), scrolled
, TRUE
, TRUE
, 0);
1166 toolbar
= gtk_toolbar_new ();
1167 gtk_style_context_add_class (gtk_widget_get_style_context (toolbar
), GTK_STYLE_CLASS_INLINE_TOOLBAR
);
1168 gtk_style_context_set_junction_sides (gtk_widget_get_style_context (toolbar
), GTK_JUNCTION_TOP
);
1169 gtk_box_pack_start (GTK_BOX (vbox
), toolbar
, FALSE
, FALSE
, 0);
1170 gtk_widget_show (toolbar
);
1172 toolitem
= gtk_tool_item_new ();
1173 gtk_toolbar_insert (GTK_TOOLBAR (toolbar
), GTK_TOOL_ITEM (toolitem
), 0);
1174 gtk_widget_show (toolitem
);
1176 checkbutton
= gtk_check_button_new_with_label (dgettext (GETTEXT_PACKAGE
, "Only show user activatable plugins"));
1177 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (checkbutton
), TRUE
);
1178 gtk_container_add (GTK_CONTAINER (toolitem
), checkbutton
);
1180 tree
= create_plugin_tree ();
1181 gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (tree
), TRUE
);
1182 gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (tree
), FALSE
);
1183 store
= GTK_LIST_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (tree
)));
1185 populate_plugin_model (plugin_manager
, store
, NULL
,
1186 plugin_manager
->priv
->activated_plugins
, FALSE
);
1188 gtk_container_add (GTK_CONTAINER (scrolled
), tree
);
1189 g_object_set_data (G_OBJECT (store
), "plugin-manager", plugin_manager
);
1192 g_object_set_data (G_OBJECT (checkbutton
), "__plugin_manager", plugin_manager
);
1193 g_signal_connect (G_OBJECT (checkbutton
), "toggled",
1194 G_CALLBACK (on_show_all_plugins_toggled
),
1196 gtk_widget_show_all (vbox
);
1201 anjuta_plugin_manager_get_remembered_plugins_page (AnjutaPluginManager
*plugin_manager
)
1205 GtkWidget
*scrolled
;
1206 GtkListStore
*store
;
1208 GtkWidget
*display_label
;
1209 GtkWidget
*forget_button
;
1210 GtkTreeSelection
*selection
;
1212 /* Remembered plugin */
1213 vbox
= gtk_vbox_new (FALSE
, 10);
1214 gtk_container_set_border_width (GTK_CONTAINER (vbox
), 10);
1216 display_label
= gtk_label_new (dgettext (GETTEXT_PACKAGE
, "These are the plugins selected by you "
1217 "when Anjuta prompted to choose one of "
1218 "many suitable plugins. Removing the "
1219 "preferred plugin will let Anjuta prompt "
1220 "you again to choose different plugin."));
1221 gtk_label_set_line_wrap (GTK_LABEL (display_label
), TRUE
);
1222 gtk_box_pack_start (GTK_BOX (vbox
), display_label
, FALSE
, FALSE
, 0);
1224 scrolled
= gtk_scrolled_window_new (NULL
, NULL
);
1225 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled
),
1227 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled
),
1228 GTK_POLICY_AUTOMATIC
,
1229 GTK_POLICY_AUTOMATIC
);
1230 gtk_box_pack_start (GTK_BOX (vbox
), scrolled
, TRUE
, TRUE
, 0);
1232 tree
= create_remembered_plugins_tree ();
1233 store
= GTK_LIST_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (tree
)));
1235 gtk_container_add (GTK_CONTAINER (scrolled
), tree
);
1236 g_object_set_data (G_OBJECT (store
), "plugin-manager", plugin_manager
);
1237 populate_remembered_plugins_model (plugin_manager
, store
);
1239 hbox
= gtk_hbox_new (FALSE
, 0);
1240 gtk_container_set_border_width (GTK_CONTAINER (hbox
), 5);
1241 gtk_box_pack_start (GTK_BOX (vbox
), hbox
, FALSE
, FALSE
, 0);
1242 forget_button
= gtk_button_new_with_label (dgettext (GETTEXT_PACKAGE
, "Forget selected plugin"));
1243 gtk_widget_set_sensitive (forget_button
, FALSE
);
1244 gtk_box_pack_end (GTK_BOX (hbox
), forget_button
, FALSE
, FALSE
, 0);
1246 g_signal_connect (forget_button
, "clicked",
1247 G_CALLBACK (on_forget_plugin_clicked
),
1249 selection
= gtk_tree_view_get_selection (GTK_TREE_VIEW (tree
));
1250 g_signal_connect (selection
, "changed",
1251 G_CALLBACK (on_forget_plugin_sel_changed
),
1253 gtk_widget_show_all (vbox
);
1258 property_to_list (const char *value
)
1264 split_str
= g_strsplit (value
, ",", -1);
1265 for (p
= split_str
; *p
!= NULL
; p
++) {
1266 l
= g_list_prepend (l
, g_strdup (g_strstrip (*p
)));
1268 g_strfreev (split_str
);
1272 static IAnjutaPluginFactory
*
1273 get_plugin_factory (AnjutaPluginManager
*plugin_manager
,
1274 const gchar
*language
,
1277 AnjutaPluginManagerPriv
*priv
;
1278 AnjutaPluginHandle
*plugin
;
1279 GList
*loader_plugins
, *node
;
1280 GList
*valid_plugins
;
1281 GObject
*obj
= NULL
;
1283 g_return_val_if_fail (ANJUTA_IS_PLUGIN_MANAGER (plugin_manager
), G_TYPE_INVALID
);
1286 if ((language
== NULL
) || (g_ascii_strcasecmp (language
, "C") == 0))
1288 /* Support of C plugin is built-in */
1289 return IANJUTA_PLUGIN_FACTORY (anjuta_plugin_factory
);
1292 priv
= plugin_manager
->priv
;
1295 /* Find all plugins implementing the IAnjutaPluginLoader interface. */
1296 loader_plugins
= g_hash_table_lookup (priv
->plugins_by_interfaces
, "IAnjutaPluginLoader");
1298 /* Create a list of loader supporting this language */
1299 node
= loader_plugins
;
1300 valid_plugins
= NULL
;
1303 AnjutaPluginDescription
*desc
;
1309 plugin
= node
->data
;
1311 desc
= anjuta_plugin_handle_get_description (plugin
);
1312 if (anjuta_plugin_description_get_string (desc
, "Plugin Loader", "SupportedLanguage", &val
))
1316 vals
= property_to_list (val
);
1325 if (!found
&& (g_ascii_strcasecmp (l_node
->data
, language
) == 0))
1329 g_free (l_node
->data
);
1330 l_node
= g_list_next (l_node
);
1336 valid_plugins
= g_list_prepend (valid_plugins
, plugin
);
1339 node
= g_list_next (node
);
1342 /* Find the first installed plugin from the valid plugins */
1343 node
= valid_plugins
;
1346 plugin
= node
->data
;
1347 obj
= g_hash_table_lookup (priv
->activated_plugins
, plugin
);
1349 node
= g_list_next (node
);
1352 /* If no plugin is installed yet, do something */
1353 if ((obj
== NULL
) && valid_plugins
&& g_list_length (valid_plugins
) == 1)
1355 /* If there is just one plugin, consider it selected */
1356 plugin
= valid_plugins
->data
;
1358 /* Install and return it */
1359 plugin_set_update (plugin_manager
, plugin
, TRUE
);
1360 obj
= g_hash_table_lookup (priv
->activated_plugins
, plugin
);
1362 else if ((obj
== NULL
) && valid_plugins
)
1364 /* Prompt the user to select one of these plugins */
1366 GList
*descs
= NULL
;
1367 node
= valid_plugins
;
1370 plugin
= node
->data
;
1371 descs
= g_list_prepend (descs
, anjuta_plugin_handle_get_description (plugin
));
1372 node
= g_list_next (node
);
1374 descs
= g_list_reverse (descs
);
1375 obj
= anjuta_plugin_manager_select_and_activate (plugin_manager
,
1376 dgettext (GETTEXT_PACKAGE
, "Select a plugin"),
1377 dgettext (GETTEXT_PACKAGE
, "Please select a plugin to activate"),
1379 g_list_free (descs
);
1381 g_list_free (valid_plugins
);
1385 return IANJUTA_PLUGIN_FACTORY (obj
);
1388 /* No plugin implementing this interface found */
1389 g_set_error (error
, ANJUTA_PLUGIN_MANAGER_ERROR
,
1390 ANJUTA_PLUGIN_MANAGER_MISSING_FACTORY
,
1391 dgettext (GETTEXT_PACKAGE
, "No plugin is able to load other plugins in %s"), language
);
1397 on_is_active_plugins_foreach (gpointer key
, gpointer data
, gpointer user_data
)
1399 AnjutaPluginHandle
*handle
= ANJUTA_PLUGIN_HANDLE (key
);
1400 gchar
const **search_iface
= (gchar
const **)user_data
;
1402 if (*search_iface
!= NULL
)
1407 interfaces
= anjuta_plugin_handle_get_interfaces (handle
);
1409 for (found
= g_list_first (interfaces
); found
!= NULL
; found
= g_list_next (found
))
1413 found
= g_list_find_custom (interfaces
, *search_iface
, (GCompareFunc
)strcmp
);
1415 if (found
!= NULL
) *search_iface
= NULL
;
1420 * anjuta_plugin_manager_is_active_plugin:
1421 * @plugin_manager: A #AnjutaPluginManager object
1422 * @iface_name: The interface implemented by the object to be found
1424 * Searches if a currently loaded plugins implements
1425 * the given interface.
1427 * Return value: True is the plugin is currently loaded.
1431 anjuta_plugin_manager_is_active_plugin (AnjutaPluginManager
*plugin_manager
,
1432 const gchar
*iface_name
)
1434 const gchar
*search_iface
= iface_name
;
1436 g_return_val_if_fail (ANJUTA_IS_PLUGIN_MANAGER (plugin_manager
), FALSE
);
1438 g_hash_table_foreach (plugin_manager
->priv
->activated_plugins
,
1439 on_is_active_plugins_foreach
,
1442 return search_iface
== NULL
;
1446 * anjuta_plugin_manager_get_plugin:
1447 * @plugin_manager: A #AnjutaPluginManager object
1448 * @iface_name: The interface implemented by the object to be found
1450 * Searches the currently available plugins to find the one which
1451 * implements the given interface as primary interface and returns it. If
1452 * the plugin is not yet loaded, it will be loaded and activated.
1454 * from the pool of plugin objects loaded in this shell and can only search
1455 * by primary interface. If there are more objects implementing this primary
1456 * interface, user might be prompted to select one from them (and might give
1457 * the option to use it as default for future queries). A typical usage of this
1461 * anjuta_plugin_manager_get_plugin (plugin_manager, "IAnjutaDocumentManager", error);
1463 * Notice that this function takes the interface name string as string, unlike
1464 * anjuta_plugins_get_interface() which takes the type directly.
1465 * If no plugin implementing this interface can be found, returns NULL.
1467 * Return value: The plugin object (subclass of #AnjutaPlugin) which implements
1468 * the given interface or NULL. See #AnjutaPlugin for more detail on interfaces
1469 * implemented by plugins.
1472 anjuta_plugin_manager_get_plugin (AnjutaPluginManager
*plugin_manager
,
1473 const gchar
*iface_name
)
1475 AnjutaPluginManagerPriv
*priv
;
1476 AnjutaPluginHandle
*plugin
;
1477 GList
*valid_plugins
, *node
;
1479 g_return_val_if_fail (ANJUTA_IS_PLUGIN_MANAGER (plugin_manager
), NULL
);
1480 g_return_val_if_fail (iface_name
!= NULL
, NULL
);
1482 priv
= plugin_manager
->priv
;
1485 /* Find all plugins implementing this (primary) interface. */
1486 valid_plugins
= g_hash_table_lookup (priv
->plugins_by_interfaces
, iface_name
);
1488 /* Find the first installed plugin from the valid plugins */
1489 node
= valid_plugins
;
1493 plugin
= node
->data
;
1494 obj
= g_hash_table_lookup (priv
->activated_plugins
, plugin
);
1497 node
= g_list_next (node
);
1500 /* If no plugin is installed yet, do something */
1501 if (valid_plugins
&& g_list_length (valid_plugins
) == 1)
1503 /* If there is just one plugin, consider it selected */
1505 plugin
= valid_plugins
->data
;
1507 /* Install and return it */
1508 plugin_set_update (plugin_manager
, plugin
, TRUE
);
1509 obj
= g_hash_table_lookup (priv
->activated_plugins
, plugin
);
1513 else if (valid_plugins
)
1515 /* Prompt the user to select one of these plugins */
1517 GList
*descs
= NULL
;
1518 node
= valid_plugins
;
1521 plugin
= node
->data
;
1522 descs
= g_list_prepend (descs
, anjuta_plugin_handle_get_description (plugin
));
1523 node
= g_list_next (node
);
1525 descs
= g_list_reverse (descs
);
1526 obj
= anjuta_plugin_manager_select_and_activate (plugin_manager
,
1527 dgettext (GETTEXT_PACKAGE
, "Select a plugin"),
1528 dgettext (GETTEXT_PACKAGE
, "<b>Please select a plugin to activate</b>"),
1530 g_list_free (descs
);
1534 /* No plugin implementing this interface found */
1539 anjuta_plugin_manager_get_plugin_by_id (AnjutaPluginManager
*plugin_manager
,
1540 const gchar
*plugin_id
)
1542 AnjutaPluginManagerPriv
*priv
;
1543 AnjutaPluginHandle
*plugin
;
1545 g_return_val_if_fail (ANJUTA_IS_PLUGIN_MANAGER (plugin_manager
), NULL
);
1546 g_return_val_if_fail (plugin_id
!= NULL
, NULL
);
1548 priv
= plugin_manager
->priv
;
1549 plugin
= g_hash_table_lookup (priv
->plugins_by_name
, plugin_id
);
1553 obj
= g_hash_table_lookup (priv
->activated_plugins
, plugin
);
1559 plugin_set_update (plugin_manager
, plugin
, TRUE
);
1560 obj
= g_hash_table_lookup (priv
->activated_plugins
, plugin
);
1564 g_warning ("No plugin found with id \"%s\".", plugin_id
);
1569 on_activated_plugins_foreach (gpointer key
, gpointer data
, gpointer user_data
)
1571 AnjutaPluginHandle
*plugin
= ANJUTA_PLUGIN_HANDLE (key
);
1572 GList
**active_plugins
= (GList
**)user_data
;
1573 *active_plugins
= g_list_prepend (*active_plugins
,
1574 anjuta_plugin_handle_get_description (plugin
));
1578 on_activated_plugin_objects_foreach (gpointer key
, gpointer data
, gpointer user_data
)
1580 GList
**active_plugins
= (GList
**)user_data
;
1581 *active_plugins
= g_list_prepend (*active_plugins
,
1586 anjuta_plugin_manager_get_active_plugins (AnjutaPluginManager
*plugin_manager
)
1588 GList
*active_plugins
= NULL
;
1590 g_return_val_if_fail (ANJUTA_IS_PLUGIN_MANAGER (plugin_manager
), NULL
);
1591 g_hash_table_foreach (plugin_manager
->priv
->activated_plugins
,
1592 on_activated_plugins_foreach
,
1594 return g_list_reverse (active_plugins
);
1598 anjuta_plugin_manager_get_active_plugin_objects (AnjutaPluginManager
*plugin_manager
)
1600 GList
*active_plugins
= NULL
;
1602 g_return_val_if_fail (ANJUTA_IS_PLUGIN_MANAGER (plugin_manager
), NULL
);
1603 g_hash_table_foreach (plugin_manager
->priv
->activated_plugins
,
1604 on_activated_plugin_objects_foreach
,
1606 return g_list_reverse (active_plugins
);
1610 anjuta_plugin_manager_unload_plugin_by_id (AnjutaPluginManager
*plugin_manager
,
1611 const gchar
*plugin_id
)
1613 AnjutaPluginManagerPriv
*priv
;
1614 AnjutaPluginHandle
*plugin
;
1616 g_return_val_if_fail (ANJUTA_IS_PLUGIN_MANAGER (plugin_manager
), FALSE
);
1617 g_return_val_if_fail (plugin_id
!= NULL
, FALSE
);
1619 priv
= plugin_manager
->priv
;
1621 plugin
= g_hash_table_lookup (priv
->plugins_by_name
, plugin_id
);
1624 plugin_set_update (plugin_manager
, plugin
, FALSE
);
1626 /* Check if the plugin has been indeed unloaded */
1627 if (!g_hash_table_lookup (priv
->activated_plugins
, plugin
))
1632 g_warning ("No plugin found with id \"%s\".", plugin_id
);
1637 find_plugin_for_object (gpointer key
, gpointer value
, gpointer data
)
1641 g_object_set_data (G_OBJECT (data
), "__plugin_plugin", key
);
1648 anjuta_plugin_manager_unload_plugin (AnjutaPluginManager
*plugin_manager
,
1649 GObject
*plugin_object
)
1651 AnjutaPluginManagerPriv
*priv
;
1652 AnjutaPluginHandle
*plugin
;
1654 g_return_val_if_fail (ANJUTA_IS_PLUGIN_MANAGER (plugin_manager
), FALSE
);
1655 g_return_val_if_fail (ANJUTA_IS_PLUGIN (plugin_object
), FALSE
);
1657 priv
= plugin_manager
->priv
;
1661 /* Find the plugin that correspond to this plugin object */
1662 g_hash_table_find (priv
->activated_plugins
, find_plugin_for_object
,
1664 plugin
= g_object_get_data (G_OBJECT (plugin_object
), "__plugin_plugin");
1668 plugin_set_update (plugin_manager
, plugin
, FALSE
);
1670 /* Check if the plugin has been indeed unloaded */
1671 if (!g_hash_table_lookup (priv
->activated_plugins
, plugin
))
1676 g_warning ("No plugin found with object \"%p\".", plugin_object
);
1681 anjuta_plugin_manager_list_query (AnjutaPluginManager
*plugin_manager
,
1686 AnjutaPluginManagerPriv
*priv
;
1687 GList
*selected_plugins
= NULL
;
1690 const gchar
*avalue
;
1693 g_return_val_if_fail (ANJUTA_IS_PLUGIN_MANAGER (plugin_manager
), NULL
);
1695 priv
= plugin_manager
->priv
;
1696 available
= priv
->available_plugins
;
1700 /* If no query is given, select all plugins */
1703 AnjutaPluginHandle
*plugin
= available
->data
;
1704 AnjutaPluginDescription
*desc
=
1705 anjuta_plugin_handle_get_description (plugin
);
1706 selected_plugins
= g_list_prepend (selected_plugins
, desc
);
1707 available
= g_list_next (available
);
1709 return g_list_reverse (selected_plugins
);
1712 g_return_val_if_fail (secs
!= NULL
, NULL
);
1713 g_return_val_if_fail (anames
!= NULL
, NULL
);
1714 g_return_val_if_fail (avalues
!= NULL
, NULL
);
1718 GList
* s_node
= secs
;
1719 GList
* n_node
= anames
;
1720 GList
* v_node
= avalues
;
1722 gboolean satisfied
= FALSE
;
1724 AnjutaPluginHandle
*plugin
= available
->data
;
1725 AnjutaPluginDescription
*desc
=
1726 anjuta_plugin_handle_get_description (plugin
);
1733 gboolean found
= FALSE
;
1738 aname
= n_node
->data
;
1739 avalue
= v_node
->data
;
1741 if (!anjuta_plugin_description_get_string (desc
, sec
, aname
, &val
))
1747 vals
= property_to_list (val
);
1753 if (strchr(node
->data
, '*') != NULL
)
1758 const gchar
*cursor
;
1760 segments
= g_strsplit (node
->data
, "*", -1);
1764 while (*seg_ptr
!= NULL
)
1766 if (strlen (*seg_ptr
) > 0) {
1767 cursor
= strstr (cursor
, *seg_ptr
);
1771 cursor
+= strlen (*seg_ptr
);
1774 if (*seg_ptr
== NULL
)
1776 g_strfreev (segments
);
1778 else if (g_ascii_strcasecmp (node
->data
, avalue
) == 0)
1783 g_free (node
->data
);
1784 node
= g_list_next (node
);
1792 s_node
= g_list_next (s_node
);
1793 n_node
= g_list_next (n_node
);
1794 v_node
= g_list_next (v_node
);
1798 selected_plugins
= g_list_prepend (selected_plugins
, desc
);
1799 /* DEBUG_PRINT ("Satisfied, Adding %s",
1800 anjuta_plugin_handle_get_name (plugin));*/
1802 available
= g_list_next (available
);
1805 return g_list_reverse (selected_plugins
);
1809 anjuta_plugin_manager_query (AnjutaPluginManager
*plugin_manager
,
1810 const gchar
*section_name
,
1811 const gchar
*attribute_name
,
1812 const gchar
*attribute_value
,
1817 GList
*anames
= NULL
;
1818 GList
*avalues
= NULL
;
1821 const gchar
*avalue
;
1822 GList
*selected_plugins
;
1825 if (section_name
== NULL
)
1827 /* If no query is given, select all plugins */
1828 return anjuta_plugin_manager_list_query (plugin_manager
, NULL
, NULL
, NULL
);
1831 g_return_val_if_fail (section_name
!= NULL
, NULL
);
1832 g_return_val_if_fail (attribute_name
!= NULL
, NULL
);
1833 g_return_val_if_fail (attribute_value
!= NULL
, NULL
);
1835 secs
= g_list_prepend (secs
, g_strdup (section_name
));
1836 anames
= g_list_prepend (anames
, g_strdup (attribute_name
));
1837 avalues
= g_list_prepend (avalues
, g_strdup (attribute_value
));
1839 va_start (var_args
, attribute_value
);
1842 sec
= va_arg (var_args
, const gchar
*);
1845 aname
= va_arg (var_args
, const gchar
*);
1848 avalue
= va_arg (var_args
, const gchar
*);
1851 secs
= g_list_prepend (secs
, g_strdup (sec
));
1852 anames
= g_list_prepend (anames
, g_strdup (aname
));
1853 avalues
= g_list_prepend (avalues
, g_strdup (avalue
));
1861 secs
= g_list_reverse (secs
);
1862 anames
= g_list_reverse (anames
);
1863 avalues
= g_list_reverse (avalues
);
1865 selected_plugins
= anjuta_plugin_manager_list_query (plugin_manager
,
1870 anjuta_util_glist_strings_free (secs
);
1871 anjuta_util_glist_strings_free (anames
);
1872 anjuta_util_glist_strings_free (avalues
);
1874 return selected_plugins
;
1880 PLUGIN_DESCRIPTION_COLUMN
,
1885 on_plugin_list_row_activated (GtkTreeView
*tree_view
,
1887 GtkTreeViewColumn
*column
,
1890 gtk_dialog_response (dialog
, GTK_RESPONSE_OK
);
1895 on_plugin_list_show (GtkTreeView
*view
,
1896 GtkDirectionType direction
,
1899 GtkTreeSelection
*selection
;
1900 selection
= gtk_tree_view_get_selection (GTK_TREE_VIEW (view
));
1902 g_signal_emit_by_name (G_OBJECT (selection
), "changed", GTK_DIALOG(dialog
), NULL
);
1907 on_plugin_list_selection_changed (GtkTreeSelection
*tree_selection
,
1910 GtkContainer
*action_area
;
1912 GtkButton
*bt
= NULL
;
1914 action_area
= GTK_CONTAINER (gtk_dialog_get_action_area (dialog
));
1915 list
= gtk_container_get_children (action_area
);
1916 for (; list
; list
= list
->next
) {
1918 if (!strcmp("gtk-ok", gtk_button_get_label (bt
)))
1921 if (bt
&& gtk_tree_selection_get_selected (tree_selection
, NULL
, NULL
))
1922 gtk_widget_set_sensitive ((GtkWidget
*) bt
, TRUE
);
1924 gtk_widget_set_sensitive ((GtkWidget
*) bt
, FALSE
);
1929 * anjuta_plugin_manager_select:
1930 * @plugin_manager: #AnjutaPluginManager object
1931 * @title: Title of the dialog
1932 * @description: label shown on the dialog
1933 * @plugin_descriptions: List of #AnjutaPluginDescription
1935 * Show a dialog where the user can choose between the given plugins
1937 * Returns: The chosen plugin description
1939 AnjutaPluginDescription
*
1940 anjuta_plugin_manager_select (AnjutaPluginManager
*plugin_manager
,
1941 gchar
*title
, gchar
*description
,
1942 GList
*plugin_descriptions
)
1944 AnjutaPluginDescription
*desc
;
1945 AnjutaPluginManagerPriv
*priv
;
1947 GtkTreeModel
*model
;
1949 GtkTreeViewColumn
*column
;
1950 GtkCellRenderer
*renderer
;
1953 GtkWidget
*content_area
;
1955 GtkWidget
*remember_checkbox
;
1957 GtkTreeIter selected
;
1958 GtkTreeSelection
*selection
;
1959 GtkTreeModel
*store
;
1960 GList
*selection_ids
= NULL
;
1961 GString
*remember_key
= g_string_new ("");
1963 g_return_val_if_fail (title
!= NULL
, NULL
);
1964 g_return_val_if_fail (description
!= NULL
, NULL
);
1965 g_return_val_if_fail (plugin_descriptions
!= NULL
, NULL
);
1967 priv
= plugin_manager
->priv
;
1969 if (g_list_length (plugin_descriptions
) <= 0)
1972 dlg
= gtk_dialog_new_with_buttons (title
, GTK_WINDOW (priv
->shell
),
1973 GTK_DIALOG_DESTROY_WITH_PARENT
,
1975 GTK_RESPONSE_CANCEL
,
1976 GTK_STOCK_OK
, GTK_RESPONSE_OK
,
1978 gtk_window_set_default_size (GTK_WINDOW (dlg
), 400, 300);
1980 label
= gtk_label_new (description
);
1981 gtk_label_set_use_markup (GTK_LABEL (label
), TRUE
);
1982 gtk_widget_show (label
);
1983 content_area
= gtk_dialog_get_content_area (GTK_DIALOG (dlg
));
1984 gtk_box_pack_start (GTK_BOX (content_area
), label
,
1987 sc
= gtk_scrolled_window_new (NULL
, NULL
);
1988 gtk_widget_show (sc
);
1989 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sc
),
1991 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sc
),
1992 GTK_POLICY_AUTOMATIC
,
1993 GTK_POLICY_AUTOMATIC
);
1995 gtk_box_pack_start (GTK_BOX (content_area
), sc
,
1998 model
= GTK_TREE_MODEL (gtk_list_store_new (N_COLUMNS
, GDK_TYPE_PIXBUF
,
1999 G_TYPE_STRING
, G_TYPE_POINTER
));
2000 view
= gtk_tree_view_new_with_model (model
);
2001 gtk_widget_show (view
);
2002 gtk_container_add (GTK_CONTAINER (sc
), view
);
2004 column
= gtk_tree_view_column_new ();
2005 gtk_tree_view_column_set_sizing (column
,
2006 GTK_TREE_VIEW_COLUMN_AUTOSIZE
);
2007 gtk_tree_view_column_set_title (column
, dgettext (GETTEXT_PACKAGE
, "Available Plugins"));
2009 renderer
= gtk_cell_renderer_pixbuf_new ();
2010 gtk_tree_view_column_pack_start (column
, renderer
, FALSE
);
2011 gtk_tree_view_column_add_attribute (column
, renderer
, "pixbuf",
2014 renderer
= gtk_cell_renderer_text_new ();
2015 gtk_tree_view_column_pack_start (column
, renderer
, TRUE
);
2016 gtk_tree_view_column_add_attribute (column
, renderer
, "markup",
2019 gtk_tree_view_append_column (GTK_TREE_VIEW (view
), column
);
2020 gtk_tree_view_set_expander_column (GTK_TREE_VIEW (view
), column
);
2022 g_signal_connect (view
, "row-activated",
2023 G_CALLBACK (on_plugin_list_row_activated
),
2025 selection
= gtk_tree_view_get_selection (GTK_TREE_VIEW (view
));
2026 g_signal_connect(selection
, "changed",
2027 G_CALLBACK(on_plugin_list_selection_changed
),
2029 g_signal_connect(view
, "focus",
2030 G_CALLBACK(on_plugin_list_show
),
2034 gtk_check_button_new_with_label (dgettext (GETTEXT_PACKAGE
, "Remember this selection"));
2035 gtk_container_set_border_width (GTK_CONTAINER (remember_checkbox
), 10);
2036 gtk_widget_show (remember_checkbox
);
2037 gtk_box_pack_start (GTK_BOX (content_area
), remember_checkbox
,
2040 node
= plugin_descriptions
;
2043 GdkPixbuf
*icon_pixbuf
= NULL
;
2044 gchar
*plugin_name
= NULL
;
2045 gchar
*plugin_desc
= NULL
;
2046 gchar
*icon_filename
= NULL
;
2047 gchar
*location
= NULL
;
2049 desc
= (AnjutaPluginDescription
*)node
->data
;
2051 if (anjuta_plugin_description_get_string (desc
,
2056 gchar
*icon_path
= NULL
;
2057 icon_path
= g_strconcat (PACKAGE_PIXMAPS_DIR
"/",
2058 icon_filename
, NULL
);
2059 g_free (icon_filename
);
2060 /* DEBUG_PRINT ("Icon: %s", icon_path); */
2062 gdk_pixbuf_new_from_file (icon_path
, NULL
);
2063 if (icon_pixbuf
== NULL
)
2065 g_warning ("Plugin pixmap not found: %s", plugin_name
);
2071 g_warning ("Plugin does not define Icon attribute");
2073 if (!anjuta_plugin_description_get_locale_string (desc
,
2078 g_warning ("Plugin does not define Name attribute");
2080 if (!anjuta_plugin_description_get_locale_string (desc
,
2085 g_warning ("Plugin does not define Description attribute");
2087 if (plugin_name
&& plugin_desc
)
2092 if (!anjuta_plugin_description_get_string (desc
,
2097 g_warning ("Plugin does not define Location attribute");
2101 text
= g_markup_printf_escaped ("<span size=\"larger\" weight=\"bold\">%s</span>\n%s", plugin_name
, plugin_desc
);
2103 gtk_list_store_append (GTK_LIST_STORE (model
), &iter
);
2104 gtk_list_store_set (GTK_LIST_STORE (model
), &iter
,
2105 PLUGIN_COLUMN
, text
,
2106 PLUGIN_DESCRIPTION_COLUMN
, desc
, -1);
2108 gtk_list_store_set (GTK_LIST_STORE (model
), &iter
,
2109 PIXBUF_COLUMN
, icon_pixbuf
, -1);
2110 g_object_unref (icon_pixbuf
);
2114 selection_ids
= g_list_prepend (selection_ids
, location
);
2116 g_free (plugin_name
);
2117 g_free (plugin_desc
);
2118 node
= g_list_next (node
);
2121 /* Prepare remembering key */
2122 selection_ids
= g_list_sort (selection_ids
,
2123 (GCompareFunc
)strcmp
);
2124 node
= selection_ids
;
2127 g_string_append (remember_key
, (gchar
*)node
->data
);
2128 g_string_append (remember_key
, ",");
2129 node
= g_list_next (node
);
2131 g_list_foreach (selection_ids
, (GFunc
) g_free
, NULL
);
2132 g_list_free (selection_ids
);
2134 /* Find if the selection is remembered */
2135 desc
= g_hash_table_lookup (priv
->remember_plugins
, remember_key
->str
);
2138 g_string_free (remember_key
, TRUE
);
2139 gtk_widget_destroy (dlg
);
2144 response
= gtk_dialog_run (GTK_DIALOG (dlg
));
2147 case GTK_RESPONSE_OK
:
2148 selection
= gtk_tree_view_get_selection (GTK_TREE_VIEW (view
));
2149 if (gtk_tree_selection_get_selected (selection
, &store
,
2152 gtk_tree_model_get (model
, &selected
,
2153 PLUGIN_DESCRIPTION_COLUMN
, &desc
, -1);
2156 /* Remember selection */
2157 if (gtk_toggle_button_get_active
2158 (GTK_TOGGLE_BUTTON (remember_checkbox
)))
2160 /* DEBUG_PRINT ("Remembering selection '%s'",
2161 remember_key->str);*/
2162 g_hash_table_insert (priv
->remember_plugins
,
2163 g_strdup (remember_key
->str
), desc
);
2165 g_string_free (remember_key
, TRUE
);
2166 gtk_widget_destroy (dlg
);
2172 g_string_free (remember_key
, TRUE
);
2173 gtk_widget_destroy (dlg
);
2178 anjuta_plugin_manager_select_and_activate (AnjutaPluginManager
*plugin_manager
,
2181 GList
*plugin_descriptions
)
2183 AnjutaPluginDescription
*d
;
2185 g_return_val_if_fail (ANJUTA_IS_PLUGIN_MANAGER (plugin_manager
), NULL
);
2187 d
= anjuta_plugin_manager_select (plugin_manager
, title
, description
,
2188 plugin_descriptions
);
2191 GObject
*plugin
= NULL
;
2192 gchar
*location
= NULL
;
2194 anjuta_plugin_description_get_string (d
,
2198 g_return_val_if_fail (location
!= NULL
, NULL
);
2200 anjuta_plugin_manager_get_plugin_by_id (plugin_manager
, location
);
2207 /* Plugin manager */
2210 anjuta_plugin_manager_init (AnjutaPluginManager
*object
)
2212 object
->priv
= g_new0 (AnjutaPluginManagerPriv
, 1);
2213 object
->priv
->plugins_by_name
= g_hash_table_new (g_str_hash
, g_str_equal
);
2214 object
->priv
->plugins_by_interfaces
= g_hash_table_new_full (g_str_hash
,
2217 (GDestroyNotify
) g_list_free
);
2218 object
->priv
->plugins_by_description
= g_hash_table_new (g_direct_hash
,
2220 object
->priv
->activated_plugins
= g_hash_table_new (g_direct_hash
,
2222 object
->priv
->plugins_cache
= g_hash_table_new (g_direct_hash
,
2224 object
->priv
->remember_plugins
= g_hash_table_new_full (g_str_hash
,
2230 anjuta_plugin_manager_finalize (GObject
*object
)
2232 AnjutaPluginManagerPriv
*priv
;
2233 priv
= ANJUTA_PLUGIN_MANAGER (object
)->priv
;
2234 if (priv
->available_plugins
)
2236 /* anjuta_plugin_manager_unload_all_plugins (ANJUTA_PLUGIN_MANAGER (object)); */
2237 g_list_foreach (priv
->available_plugins
, (GFunc
)g_object_unref
, NULL
);
2238 g_list_free (priv
->available_plugins
);
2239 priv
->available_plugins
= NULL
;
2241 if (priv
->activated_plugins
)
2243 g_hash_table_destroy (priv
->activated_plugins
);
2244 priv
->activated_plugins
= NULL
;
2246 if (priv
->plugins_cache
)
2248 g_hash_table_destroy (priv
->plugins_cache
);
2249 priv
->plugins_cache
= NULL
;
2251 if (priv
->plugins_by_name
)
2253 g_hash_table_destroy (priv
->plugins_by_name
);
2254 priv
->plugins_by_name
= NULL
;
2256 if (priv
->plugins_by_description
)
2258 g_hash_table_destroy (priv
->plugins_by_description
);
2259 priv
->plugins_by_description
= NULL
;
2261 if (priv
->plugins_by_interfaces
)
2263 g_hash_table_destroy (priv
->plugins_by_interfaces
);
2264 priv
->plugins_by_interfaces
= NULL
;
2266 if (priv
->plugin_dirs
)
2268 g_list_foreach (priv
->plugin_dirs
, (GFunc
)g_free
, NULL
);
2269 g_list_free (priv
->plugin_dirs
);
2270 priv
->plugin_dirs
= NULL
;
2273 if (anjuta_c_plugin_factory
)
2275 g_object_unref (anjuta_c_plugin_factory
);
2276 anjuta_c_plugin_factory
= NULL
;
2279 G_OBJECT_CLASS (parent_class
)->finalize (object
);
2283 anjuta_plugin_manager_set_property (GObject
*object
, guint prop_id
,
2284 const GValue
*value
, GParamSpec
*pspec
)
2286 AnjutaPluginManagerPriv
*priv
;
2288 g_return_if_fail (ANJUTA_IS_PLUGIN_MANAGER (object
));
2289 priv
= ANJUTA_PLUGIN_MANAGER (object
)->priv
;
2294 priv
->status
= g_value_get_object (value
);
2297 priv
->shell
= g_value_get_object (value
);
2300 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
2306 anjuta_plugin_manager_get_property (GObject
*object
, guint prop_id
,
2307 GValue
*value
, GParamSpec
*pspec
)
2309 AnjutaPluginManagerPriv
*priv
;
2311 g_return_if_fail (ANJUTA_IS_PLUGIN_MANAGER (object
));
2312 priv
= ANJUTA_PLUGIN_MANAGER (object
)->priv
;
2317 g_value_set_object (value
, priv
->shell
);
2320 g_value_set_object (value
, priv
->status
);
2322 case PROP_AVAILABLE_PLUGINS
:
2323 g_value_set_pointer (value
, priv
->available_plugins
);
2325 case PROP_ACTIVATED_PLUGINS
:
2326 g_value_set_pointer (value
, priv
->activated_plugins
);
2329 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
2334 anjuta_plugin_manager_plugin_activated (AnjutaPluginManager
*self
,
2335 AnjutaPluginDescription
* plugin_desc
,
2338 /* TODO: Add default signal handler implementation here */
2342 anjuta_plugin_manager_plugin_deactivated (AnjutaPluginManager
*self
,
2343 AnjutaPluginDescription
* plugin_desc
,
2346 /* TODO: Add default signal handler implementation here */
2350 anjuta_plugin_manager_class_init (AnjutaPluginManagerClass
*klass
)
2352 GObjectClass
* object_class
= G_OBJECT_CLASS (klass
);
2353 parent_class
= G_OBJECT_CLASS (g_type_class_peek_parent (klass
));
2355 object_class
->finalize
= anjuta_plugin_manager_finalize
;
2356 object_class
->set_property
= anjuta_plugin_manager_set_property
;
2357 object_class
->get_property
= anjuta_plugin_manager_get_property
;
2359 klass
->plugin_activated
= anjuta_plugin_manager_plugin_activated
;
2360 klass
->plugin_deactivated
= anjuta_plugin_manager_plugin_deactivated
;
2362 g_object_class_install_property (object_class
,
2364 g_param_spec_pointer ("profiles",
2365 dgettext (GETTEXT_PACKAGE
, "Profiles"),
2366 dgettext (GETTEXT_PACKAGE
, "Current stack of profiles"),
2368 g_object_class_install_property (object_class
,
2369 PROP_AVAILABLE_PLUGINS
,
2370 g_param_spec_pointer ("available-plugins",
2371 dgettext (GETTEXT_PACKAGE
, "Available plugins"),
2372 dgettext (GETTEXT_PACKAGE
, "Currently available plugins found in plugin paths"),
2375 g_object_class_install_property (object_class
,
2376 PROP_ACTIVATED_PLUGINS
,
2377 g_param_spec_pointer ("activated-plugins",
2378 dgettext (GETTEXT_PACKAGE
, "Activated plugins"),
2379 dgettext (GETTEXT_PACKAGE
, "Currently activated plugins"),
2381 g_object_class_install_property (object_class
,
2383 g_param_spec_object ("shell",
2384 dgettext (GETTEXT_PACKAGE
, "Anjuta Shell"),
2385 dgettext (GETTEXT_PACKAGE
, "Anjuta shell for which the plugins are made"),
2389 G_PARAM_CONSTRUCT
));
2390 g_object_class_install_property (object_class
,
2392 g_param_spec_object ("status",
2393 dgettext (GETTEXT_PACKAGE
, "Anjuta Status"),
2394 dgettext (GETTEXT_PACKAGE
, "Anjuta status to use in loading and unloading of plugins"),
2398 G_PARAM_CONSTRUCT
));
2400 plugin_manager_signals
[PLUGIN_ACTIVATED
] =
2401 g_signal_new ("plugin-activated",
2402 G_OBJECT_CLASS_TYPE (klass
),
2404 G_STRUCT_OFFSET (AnjutaPluginManagerClass
,
2407 anjuta_cclosure_marshal_VOID__POINTER_OBJECT
,
2409 G_TYPE_POINTER
, ANJUTA_TYPE_PLUGIN
);
2411 plugin_manager_signals
[PLUGIN_DEACTIVATED
] =
2412 g_signal_new ("plugin-deactivated",
2413 G_OBJECT_CLASS_TYPE (klass
),
2415 G_STRUCT_OFFSET (AnjutaPluginManagerClass
,
2416 plugin_deactivated
),
2418 anjuta_cclosure_marshal_VOID__POINTER_OBJECT
,
2420 G_TYPE_POINTER
, ANJUTA_TYPE_PLUGIN
);
2424 anjuta_plugin_manager_get_type (void)
2426 static GType our_type
= 0;
2430 static const GTypeInfo our_info
=
2432 sizeof (AnjutaPluginManagerClass
), /* class_size */
2433 (GBaseInitFunc
) NULL
, /* base_init */
2434 (GBaseFinalizeFunc
) NULL
, /* base_finalize */
2435 (GClassInitFunc
) anjuta_plugin_manager_class_init
, /* class_init */
2436 (GClassFinalizeFunc
) NULL
, /* class_finalize */
2437 NULL
/* class_data */,
2438 sizeof (AnjutaPluginManager
), /* instance_size */
2439 0, /* n_preallocs */
2440 (GInstanceInitFunc
) anjuta_plugin_manager_init
, /* instance_init */
2441 NULL
/* value_table */
2443 our_type
= g_type_register_static (G_TYPE_OBJECT
,
2444 "AnjutaPluginManager",
2451 AnjutaPluginManager
*
2452 anjuta_plugin_manager_new (GObject
*shell
, AnjutaStatus
*status
,
2453 GList
* plugins_directories
)
2455 GObject
*manager_object
;
2456 AnjutaPluginManager
*plugin_manager
;
2457 GList
*cycles
= NULL
;
2458 const char *gnome2_path
;
2462 GList
*plugin_dirs
= NULL
;
2464 /* Initialize the anjuta plugin system */
2465 manager_object
= g_object_new (ANJUTA_TYPE_PLUGIN_MANAGER
,
2466 "shell", shell
, "status", status
, NULL
);
2467 plugin_manager
= ANJUTA_PLUGIN_MANAGER (manager_object
);
2469 if (anjuta_plugin_factory
== NULL
)
2471 anjuta_plugin_factory
= anjuta_c_plugin_factory_new ();
2474 gnome2_path
= g_getenv ("GNOME2_PATH");
2476 pathv
= g_strsplit (gnome2_path
, ":", 1);
2478 for (p
= pathv
; *p
!= NULL
; p
++) {
2479 char *path
= g_strdup (*p
);
2480 plugin_dirs
= g_list_prepend (plugin_dirs
, path
);
2485 node
= plugins_directories
;
2489 char *path
= g_strdup (node
->data
);
2490 plugin_dirs
= g_list_prepend (plugin_dirs
, path
);
2491 node
= g_list_next (node
);
2493 plugin_dirs
= g_list_reverse (plugin_dirs
);
2494 /* load_plugins (); */
2499 load_plugins_from_directory (plugin_manager
, (char*)node
->data
);
2500 node
= g_list_next (node
);
2502 resolve_dependencies (plugin_manager
, &cycles
);
2503 g_list_foreach(plugin_dirs
, (GFunc
) g_free
, NULL
);
2504 g_list_free(plugin_dirs
);
2505 return plugin_manager
;
2509 anjuta_plugin_manager_activate_plugins (AnjutaPluginManager
*plugin_manager
,
2510 GList
*plugins_to_activate
)
2512 AnjutaPluginManagerPriv
*priv
;
2513 GdkPixbuf
*icon_pixbuf
;
2516 priv
= plugin_manager
->priv
;
2518 /* Freeze shell operations */
2519 anjuta_shell_freeze (ANJUTA_SHELL (priv
->shell
), NULL
);
2520 if (plugins_to_activate
)
2522 anjuta_status_progress_add_ticks (ANJUTA_STATUS (priv
->status
),
2523 g_list_length (plugins_to_activate
));
2525 node
= plugins_to_activate
;
2528 AnjutaPluginDescription
*d
;
2530 gchar
*icon_filename
, *label
;
2531 gchar
*icon_path
= NULL
;
2537 if (anjuta_plugin_description_get_string (d
, "Anjuta Plugin",
2541 gchar
*title
/*, *description */;
2542 anjuta_plugin_description_get_locale_string (d
, "Anjuta Plugin",
2546 anjuta_plugin_description_get_locale_string (d, "Anjuta Plugin",
2550 icon_path
= g_strconcat (PACKAGE_PIXMAPS_DIR
"/",
2551 icon_filename
, NULL
);
2552 /* DEBUG_PRINT ("Icon: %s", icon_path); */
2553 /* Avoid space in translated string */
2554 label
= g_strconcat (dgettext (GETTEXT_PACKAGE
, "Loading:"), " ", title
, "...", NULL
);
2555 icon_pixbuf
= gdk_pixbuf_new_from_file (icon_path
, NULL
);
2557 g_warning ("Plugin does not define Icon: No such file %s",
2560 g_free (icon_filename
);
2564 anjuta_status_progress_tick (ANJUTA_STATUS (priv
->status
),
2565 icon_pixbuf
, label
);
2568 g_object_unref (icon_pixbuf
);
2570 if (anjuta_plugin_description_get_string (d
, "Anjuta Plugin",
2571 "Location", &plugin_id
))
2573 GObject
*plugin_obj
;
2576 anjuta_plugin_manager_get_plugin_by_id (plugin_manager
,
2581 node
= g_list_next (node
);
2584 /* Thaw shell operations */
2585 anjuta_shell_thaw (ANJUTA_SHELL (priv
->shell
), NULL
);
2589 on_collect (gpointer key
, gpointer value
, gpointer user_data
)
2592 gchar
*query
= (gchar
*) key
;
2593 AnjutaPluginDescription
*desc
= (AnjutaPluginDescription
*) value
;
2594 GString
*write_buffer
= (GString
*) user_data
;
2596 anjuta_plugin_description_get_string (desc
, "Anjuta Plugin", "Location",
2598 g_string_append_printf (write_buffer
, "%s=%s;", query
, id
);
2603 * anjuta_plugin_manager_get_remembered_plugins:
2604 * @plugin_manager: A #AnjutaPluginManager object
2606 * Get the list of plugins loaded when there is a choice between several
2607 * ones without asking the user.
2609 * The list format is returned as a string with the format detailed in
2610 * anjuta_plugin_manager_set_remembered_plugins().
2612 * Return value: a newly-allocated string that must be freed with g_free().
2616 anjuta_plugin_manager_get_remembered_plugins (AnjutaPluginManager
*plugin_manager
)
2618 AnjutaPluginManagerPriv
*priv
;
2619 GString
*write_buffer
= g_string_new ("");
2621 g_return_val_if_fail (ANJUTA_IS_PLUGIN_MANAGER (plugin_manager
), FALSE
);
2623 priv
= plugin_manager
->priv
;
2624 g_hash_table_foreach (priv
->remember_plugins
, on_collect
,
2626 return g_string_free (write_buffer
, FALSE
);
2630 on_foreach_remove_true (gpointer k
, gpointer v
, gpointer d
)
2636 * anjuta_plugin_manager_set_remembered_plugins:
2637 * @plugin_manager: A #AnjutaPluginManager object
2638 * @remembered_plugins: A list of prefered plugins
2640 * Set the list of plugins loaded when there is a choice between several
2641 * ones without asking the user.
2642 * The list is a string composed of elements separated by ';'. Each element
2643 * is defined with "key=value", where key is the list of possible plugins and
2644 * the value is the choosen plugin.
2646 * By the example the following element
2648 * anjuta-symbol-browser:SymbolBrowserPlugin,anjuta-symbol-db:SymbolDBPlugin,=anjuta-symbol-db:SymbolDBPlugin;
2650 * means if Anjuta has to choose between SymbolBrowserPlugin and
2651 * SymbolDBPlugin, it will choose SymbolDBPlugin.
2654 anjuta_plugin_manager_set_remembered_plugins (AnjutaPluginManager
*plugin_manager
,
2655 const gchar
*remembered_plugins
)
2657 AnjutaPluginManagerPriv
*priv
;
2658 gchar
**strv_lines
, **line_idx
;
2660 g_return_if_fail (ANJUTA_IS_PLUGIN_MANAGER (plugin_manager
));
2661 g_return_if_fail (remembered_plugins
!= NULL
);
2663 priv
= plugin_manager
->priv
;
2665 g_hash_table_foreach_remove (priv
->remember_plugins
,
2666 on_foreach_remove_true
, NULL
);
2668 strv_lines
= g_strsplit (remembered_plugins
, ";", -1);
2669 line_idx
= strv_lines
;
2672 gchar
**strv_keyvals
;
2673 strv_keyvals
= g_strsplit (*line_idx
, "=", -1);
2674 if (strv_keyvals
&& strv_keyvals
[0] && strv_keyvals
[1])
2676 AnjutaPluginHandle
*plugin
;
2677 plugin
= g_hash_table_lookup (priv
->plugins_by_name
,
2681 AnjutaPluginDescription
*desc
;
2682 desc
= anjuta_plugin_handle_get_description (plugin
);
2684 DEBUG_PRINT ("Restoring remember plugin: %s=%s",
2688 g_hash_table_insert (priv
->remember_plugins
,
2689 g_strdup (strv_keyvals
[0]), desc
);
2691 g_strfreev (strv_keyvals
);
2695 g_strfreev (strv_lines
);