1 /* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * plugin-manager.c: Dialog used to load plugins into the Gnumeric
8 * Dom Lachowicz (dominicl@seas.upenn.edu)
9 * Tom Dyas (tdyas@romulus.rutgers.edu)
11 * Zbigniew Chyla (cyba@gnome.pl)
12 * Andreas J. Guelzow (aguelzow@pyrshep.ca)
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, see <https://www.gnu.org/licenses/>.
28 #include <gnumeric-config.h>
29 #include <glib/gi18n-lib.h>
32 #include <application.h>
34 #include <gnumeric-conf.h>
38 #include <goffice/goffice.h>
41 #include <gsf/gsf-impl-utils.h>
45 #define PLUGIN_MANAGER_DIALOG_KEY "plugin-manager-dialog"
49 GtkWindow
*parent_window
;
52 GtkNotebook
*gnotebook
;
53 GtkListStore
*model_plugins
;
54 GtkTreeView
*list_plugins
;
55 GtkTreeStore
*model_details
;
56 GtkTreeView
*view_details
;
57 GtkTreeSelection
*selection
;
58 GtkButton
*button_rescan_directories
;
59 GtkButton
*button_directory_add
, *button_directory_delete
;
60 GtkButton
*button_activate_all
;
61 GtkCheckButton
*checkbutton_install_new
;
62 GtkWidget
*frame_mark_for_deactivation
;
63 GtkWidget
*checkbutton_mark_for_deactivation
;
64 GtkEntry
*entry_directory
;
65 GtkTextBuffer
*text_description
;
66 GtkListStore
*model_directories
;
67 GtkTreeView
*list_directories
;
68 GtkTreeSelection
*selection_directory
;
91 plugin_compare_name (gconstpointer a
, gconstpointer b
)
93 GOPlugin
*plugin_a
= (GOPlugin
*) a
, *plugin_b
= (GOPlugin
*) b
;
95 return g_utf8_collate (go_plugin_get_name (plugin_a
),
96 go_plugin_get_name (plugin_b
));
100 model_get_plugin_iter (GtkTreeModel
*model
, gpointer plugin
, GtkTreeIter
*ret_iter
)
104 for (has_iter
= gtk_tree_model_get_iter_first (model
, ret_iter
);
105 has_iter
; has_iter
= gtk_tree_model_iter_next (model
, ret_iter
)) {
108 gtk_tree_model_get (model
, ret_iter
, PLUGIN_POINTER
, ¤t
, -1);
109 if (current
== plugin
) {
118 cb_plugin_changed (GOPlugin
*plugin
, PluginManagerGUI
*pm_gui
)
122 if (model_get_plugin_iter (GTK_TREE_MODEL (pm_gui
->model_plugins
), plugin
, &iter
)) {
124 pm_gui
->model_plugins
, &iter
,
125 PLUGIN_ACTIVE
, go_plugin_is_active (plugin
),
126 PLUGIN_SWITCHABLE
, !go_plugin_is_active (plugin
) || go_plugin_can_deactivate (plugin
),
132 cb_plugin_destroyed (PluginManagerGUI
*pm_gui
, GObject
*ex_plugin
)
136 if (model_get_plugin_iter (GTK_TREE_MODEL (pm_gui
->model_plugins
), ex_plugin
, &iter
)) {
137 gtk_list_store_remove (pm_gui
->model_plugins
, &iter
);
142 set_plugin_model_row (PluginManagerGUI
*pm_gui
, GtkTreeIter
*iter
, GOPlugin
*plugin
)
145 pm_gui
->model_plugins
, iter
,
146 PLUGIN_NAME
, _(go_plugin_get_name (plugin
)),
147 PLUGIN_ACTIVE
, go_plugin_is_active (plugin
),
148 PLUGIN_SWITCHABLE
, !go_plugin_is_active (plugin
) || go_plugin_can_deactivate (plugin
),
149 PLUGIN_POINTER
, plugin
,
152 G_OBJECT (plugin
), "state_changed",
153 G_CALLBACK (cb_plugin_changed
), pm_gui
);
155 G_OBJECT (plugin
), "can_deactivate_changed",
156 G_CALLBACK (cb_plugin_changed
), pm_gui
);
158 G_OBJECT (plugin
), (GWeakNotify
) cb_plugin_destroyed
, pm_gui
);
162 cb_pm_button_rescan_directories_clicked (PluginManagerGUI
*pm_gui
)
165 GSList
*new_plugins
, *l
;
166 GtkTreeModel
*model
= GTK_TREE_MODEL (pm_gui
->model_plugins
);
167 GtkTreeIter iter
, new_iter
;
170 go_plugins_rescan (&error
, &new_plugins
);
172 go_cmd_context_error_info (pm_gui
->cc
, error
);
173 go_error_info_free (error
);
175 GO_SLIST_SORT (new_plugins
, plugin_compare_name
);
176 for (has_iter
= gtk_tree_model_get_iter_first (model
, &iter
), l
= new_plugins
;
177 has_iter
&& l
!= NULL
;
178 has_iter
= gtk_tree_model_iter_next (model
, &iter
)) {
179 GOPlugin
*old_plugin
, *new_plugin
;
181 gtk_tree_model_get (model
, &iter
, PLUGIN_POINTER
, &old_plugin
, -1);
182 while (new_plugin
= l
->data
, plugin_compare_name (old_plugin
, new_plugin
) > 0) {
183 gtk_list_store_insert_before (pm_gui
->model_plugins
, &new_iter
, &iter
);
184 set_plugin_model_row (pm_gui
, &new_iter
, new_plugin
);
191 gtk_list_store_append (pm_gui
->model_plugins
, &new_iter
);
192 set_plugin_model_row (pm_gui
, &new_iter
, GO_PLUGIN (l
->data
));
195 g_slist_free (new_plugins
);
199 cb_pm_checkbutton_install_new_toggled (GtkCheckButton
*checkbutton
,
200 G_GNUC_UNUSED PluginManagerGUI
*pm_gui
)
202 gnm_conf_set_plugins_activate_newplugins (
203 gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (checkbutton
)));
207 pm_gui_load_directories (PluginManagerGUI
*pm_gui
,
208 GSList
const *plugin_dirs
, gboolean is_conf
)
210 for (; plugin_dirs
; plugin_dirs
= plugin_dirs
->next
) {
212 gtk_list_store_append (pm_gui
->model_directories
, &iter
);
213 gtk_list_store_set (pm_gui
->model_directories
, &iter
,
214 DIR_NAME
, (char *) plugin_dirs
->data
,
215 DIR_IS_SYSTEM
, !is_conf
,
221 pm_gui_load_directory_page (PluginManagerGUI
*pm_gui
)
224 char * sys_plugins
= g_build_filename (gnm_sys_lib_dir (), PLUGIN_SUBDIR
, NULL
);
225 char * usr_plugins
= (gnm_usr_dir (TRUE
) == NULL
? NULL
:
226 g_build_filename (gnm_usr_dir (TRUE
), PLUGIN_SUBDIR
, NULL
));
227 char * go_plugins
= go_plugins_get_plugin_dir ();
229 gchar
const *plugin_path_env
;
231 gtk_list_store_clear (pm_gui
->model_directories
);
233 gtk_list_store_append (pm_gui
->model_directories
, &iter
);
234 gtk_list_store_set (pm_gui
->model_directories
, &iter
,
235 DIR_NAME
, sys_plugins
,
238 g_free (sys_plugins
);
239 gtk_list_store_append (pm_gui
->model_directories
, &iter
);
240 gtk_list_store_set (pm_gui
->model_directories
, &iter
,
241 DIR_NAME
, usr_plugins
,
244 g_free (usr_plugins
);
245 gtk_list_store_append (pm_gui
->model_directories
, &iter
);
246 gtk_list_store_set (pm_gui
->model_directories
, &iter
,
247 DIR_NAME
, go_plugins
,
252 plugin_path_env
= g_getenv ("GNUMERIC_PLUGIN_PATH");
253 if (plugin_path_env
!= NULL
) {
254 plugin_dirs
= go_strsplit_to_slist (plugin_path_env
, G_SEARCHPATH_SEPARATOR
);
255 pm_gui_load_directories (pm_gui
, plugin_dirs
, FALSE
);
256 g_slist_free_full (plugin_dirs
, g_free
);
258 pm_gui_load_directories (pm_gui
, gnm_conf_get_plugins_extra_dirs (), TRUE
);
262 cb_pm_button_directory_add_clicked (PluginManagerGUI
*pm_gui
)
264 GtkFileChooser
*fsel
;
266 fsel
= GTK_FILE_CHOOSER
267 (g_object_new (GTK_TYPE_FILE_CHOOSER_DIALOG
,
268 "action", GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER
,
269 "title", _("Select Directory"),
270 /* We need to force local-only as plugins
271 won't work over the network. */
274 gtk_dialog_add_buttons (GTK_DIALOG (fsel
),
275 _("Cancel"), GTK_RESPONSE_CANCEL
,
276 _("Add"), GTK_RESPONSE_OK
,
278 gtk_dialog_set_default_response (GTK_DIALOG (fsel
), GTK_RESPONSE_OK
);
280 if (go_gtk_file_sel_dialog (pm_gui
->parent_window
, GTK_WIDGET (fsel
))) {
281 char *path
= gtk_file_chooser_get_filename (fsel
);
283 if (!g_file_test (path
, G_FILE_TEST_IS_DIR
)) {
284 char *dir_name
= g_path_get_dirname (path
);
289 if (g_slist_find_custom (gnm_conf_get_plugins_extra_dirs (),
290 path
, go_str_compare
) == NULL
) {
291 GSList
*extra_dirs
= go_string_slist_copy
292 (gnm_conf_get_plugins_extra_dirs ());
294 GO_SLIST_PREPEND (extra_dirs
, path
);
296 gnm_conf_set_plugins_extra_dirs (extra_dirs
);
297 g_slist_free_full (extra_dirs
, g_free
);
299 pm_gui_load_directory_page (pm_gui
);
300 cb_pm_button_rescan_directories_clicked (pm_gui
);
305 gtk_widget_destroy (GTK_WIDGET (fsel
));
309 cb_pm_button_directory_delete_clicked (PluginManagerGUI
*pm_gui
)
312 char *dir_name
= NULL
;
313 gboolean is_system
= TRUE
;
314 GSList
*extra_dirs
, *res
;
316 if (!gtk_tree_selection_get_selected (pm_gui
->selection_directory
, NULL
, &iter
))
319 gtk_tree_model_get (GTK_TREE_MODEL (pm_gui
->model_directories
), &iter
,
321 DIR_IS_SYSTEM
, &is_system
,
324 extra_dirs
= go_string_slist_copy (gnm_conf_get_plugins_extra_dirs ());
327 : g_slist_find_custom (extra_dirs
, dir_name
, go_str_compare
);
330 extra_dirs
= g_slist_remove_link (extra_dirs
, res
);
332 g_slist_free_1 (res
);
334 gnm_conf_set_plugins_extra_dirs (extra_dirs
);
336 pm_gui_load_directory_page (pm_gui
);
337 cb_pm_button_rescan_directories_clicked (pm_gui
);
340 g_slist_free_full (extra_dirs
, g_free
);
345 cb_checkbutton_mark_for_deactivation_toggled (GtkCheckButton
*cbtn
, GOPlugin
*plugin
)
347 go_plugin_db_mark_plugin_for_deactivation (
348 plugin
, gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (cbtn
)));
352 cb_pm_selection_changed (GtkTreeSelection
*selection
, PluginManagerGUI
*pm_gui
)
356 const char *plugin_desc
;
358 g_return_if_fail (pm_gui
!= NULL
);
360 g_signal_handlers_disconnect_matched (
361 pm_gui
->checkbutton_mark_for_deactivation
,
362 G_SIGNAL_MATCH_FUNC
, 0, 0, NULL
,
363 cb_checkbutton_mark_for_deactivation_toggled
, NULL
);
365 if (!gtk_tree_selection_get_selected (selection
, NULL
, &iter
)) {
366 gtk_text_buffer_set_text (pm_gui
->text_description
, "", 0);
367 gtk_entry_set_text (pm_gui
->entry_directory
, "");
368 gtk_tree_store_clear (pm_gui
->model_details
);
369 gtk_widget_hide (pm_gui
->frame_mark_for_deactivation
);
371 GtkTreeIter iter2
, iter3
;
372 GSList
*dep_ids
, *services
;
374 gtk_tree_model_get (GTK_TREE_MODEL (pm_gui
->model_plugins
),
375 &iter
, PLUGIN_POINTER
, &pinfo
, -1);
376 plugin_desc
= _(go_plugin_get_description (pinfo
));
377 if (plugin_desc
== NULL
) {
380 gtk_text_buffer_set_text (
381 pm_gui
->text_description
, plugin_desc
, strlen (plugin_desc
));
382 gtk_entry_set_text (pm_gui
->entry_directory
, go_plugin_get_dir_name (pinfo
));
384 gtk_tree_store_clear (pm_gui
->model_details
);
385 gtk_tree_store_append (pm_gui
->model_details
, &iter
, NULL
);
387 pm_gui
->model_details
, &iter
,
388 DETAILS_DESC
, go_plugin_get_name (pinfo
),
389 DETAILS_ID
, go_plugin_get_id (pinfo
),
391 dep_ids
= go_plugin_get_dependencies_ids (pinfo
);
392 if (dep_ids
!= NULL
) {
393 gtk_tree_store_append (pm_gui
->model_details
, &iter2
, &iter
);
395 pm_gui
->model_details
, &iter2
,
396 DETAILS_DESC
, _("Plugin dependencies"),
399 GO_SLIST_FOREACH (dep_ids
, char, dep_id
,
400 GOPlugin
*dep_plugin
;
403 dep_plugin
= go_plugins_get_plugin_by_id (dep_id
);
404 name
= dep_plugin
!= NULL
? (char *) go_plugin_get_name (dep_plugin
) : _("Unknown plugin");
405 gtk_tree_store_append (pm_gui
->model_details
, &iter3
, &iter2
);
407 pm_gui
->model_details
, &iter3
,
413 g_slist_free_full (dep_ids
, g_free
);
415 gtk_tree_store_append (pm_gui
->model_details
, &iter2
, &iter
);
417 pm_gui
->model_details
, &iter2
,
418 DETAILS_DESC
, _("Plugin services"),
421 services
= go_plugin_get_services (pinfo
);
422 GO_SLIST_FOREACH (services
, GOPluginService
, service
,
423 gtk_tree_store_append (pm_gui
->model_details
, &iter3
, &iter2
);
425 pm_gui
->model_details
, &iter3
,
426 DETAILS_DESC
, go_plugin_service_get_description (service
),
427 DETAILS_ID
, go_plugin_service_get_id (service
),
430 gtk_tree_view_expand_all (pm_gui
->view_details
);
432 if (go_plugin_is_active (pinfo
) && !go_plugin_can_deactivate (pinfo
)) {
433 gtk_toggle_button_set_active (
434 GTK_TOGGLE_BUTTON (pm_gui
->checkbutton_mark_for_deactivation
),
435 go_plugin_db_is_plugin_marked_for_deactivation (pinfo
));
437 pm_gui
->checkbutton_mark_for_deactivation
, "toggled",
438 G_CALLBACK (cb_checkbutton_mark_for_deactivation_toggled
),
440 gtk_widget_show (pm_gui
->frame_mark_for_deactivation
);
442 gtk_widget_hide (pm_gui
->frame_mark_for_deactivation
);
448 cb_pm_dialog_free (PluginManagerGUI
*pm_gui
)
450 GtkTreeModel
*model
= GTK_TREE_MODEL (pm_gui
->model_plugins
);
454 for (has_iter
= gtk_tree_model_get_iter_first (model
, &iter
);
455 has_iter
; has_iter
= gtk_tree_model_iter_next (model
, &iter
)) {
458 gtk_tree_model_get (model
, &iter
, PLUGIN_POINTER
, &plugin
, -1);
459 g_signal_handlers_disconnect_by_func (
460 G_OBJECT (plugin
), G_CALLBACK (cb_plugin_changed
), pm_gui
);
461 g_signal_handlers_disconnect_by_func (
462 G_OBJECT (plugin
), G_CALLBACK (cb_plugin_changed
), pm_gui
);
463 g_object_weak_unref (
464 G_OBJECT (plugin
), (GWeakNotify
) cb_plugin_destroyed
, pm_gui
);
467 if (pm_gui
->gui
!= NULL
)
468 g_object_unref (pm_gui
->gui
);
469 if (pm_gui
->model_plugins
!= NULL
)
470 g_object_unref (pm_gui
->model_plugins
);
471 if (pm_gui
->model_details
!= NULL
)
472 g_object_unref (pm_gui
->model_details
);
473 if (pm_gui
->model_directories
!= NULL
)
474 g_object_unref (pm_gui
->model_directories
);
479 cb_pm_button_activate_all_clicked (G_GNUC_UNUSED GtkButton
*button
,
480 PluginManagerGUI
*pm_gui
)
482 GOErrorInfo
*activation_error
, *error
;
484 go_plugin_db_activate_plugin_list (
485 go_plugins_get_available_plugins (), &activation_error
);
486 if (activation_error
!= NULL
) {
487 error
= go_error_info_new_str_with_details (
488 _("Errors while activating plugins"), activation_error
);
489 gnm_go_error_info_dialog_show (
490 GTK_WINDOW (pm_gui
->dialog_pm
), error
);
491 go_error_info_free (error
);
496 pm_dialog_init (PluginManagerGUI
*pm_gui
)
498 GSList
*sorted_plugin_list
;
501 g_signal_connect (G_OBJECT (pm_gui
->button_activate_all
),
503 G_CALLBACK (cb_pm_button_activate_all_clicked
), pm_gui
);
504 g_signal_connect_swapped (G_OBJECT (pm_gui
->button_rescan_directories
),
506 G_CALLBACK (cb_pm_button_rescan_directories_clicked
), pm_gui
);
507 g_signal_connect_swapped (G_OBJECT (pm_gui
->button_directory_add
),
509 G_CALLBACK (cb_pm_button_directory_add_clicked
), pm_gui
);
510 g_signal_connect_swapped (G_OBJECT (pm_gui
->button_directory_delete
),
512 G_CALLBACK (cb_pm_button_directory_delete_clicked
), pm_gui
);
513 g_signal_connect (G_OBJECT (pm_gui
->checkbutton_install_new
),
515 G_CALLBACK (cb_pm_checkbutton_install_new_toggled
), pm_gui
);
517 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (pm_gui
->checkbutton_install_new
),
518 gnm_conf_get_plugins_activate_newplugins ());
520 /* initialize plugin list */
521 gtk_list_store_clear (pm_gui
->model_plugins
);
522 sorted_plugin_list
= g_slist_sort (
523 g_slist_copy (go_plugins_get_available_plugins ()),
524 &plugin_compare_name
);
525 GO_SLIST_FOREACH (sorted_plugin_list
, GOPlugin
, plugin
,
526 gtk_list_store_append (pm_gui
->model_plugins
, &iter
);
527 set_plugin_model_row (pm_gui
, &iter
, plugin
);
529 g_slist_free (sorted_plugin_list
);
531 cb_pm_selection_changed (pm_gui
->selection
, pm_gui
);
532 g_object_set_data_full (G_OBJECT (pm_gui
->dialog_pm
),
533 "state", pm_gui
, (GDestroyNotify
) cb_pm_dialog_free
);
537 cb_pm_dir_selection_changed (PluginManagerGUI
*pm_gui
)
542 if (!gtk_tree_selection_get_selected (pm_gui
->selection_directory
, NULL
, &iter
)) {
543 gtk_widget_set_sensitive (GTK_WIDGET (pm_gui
->button_directory_delete
), FALSE
);
547 gtk_tree_model_get (GTK_TREE_MODEL (pm_gui
->model_directories
), &iter
,
548 DIR_IS_SYSTEM
, &is_system
,
551 gtk_widget_set_sensitive (GTK_WIDGET (pm_gui
->button_directory_delete
), !is_system
);
556 cb_active_toggled (G_GNUC_UNUSED GtkCellRendererToggle
*celltoggle
,
558 PluginManagerGUI
*pm_gui
)
566 model
= gtk_tree_view_get_model (pm_gui
->list_plugins
);
567 has_iter
= gtk_tree_model_get_iter_from_string (model
, &iter
, path
);
569 g_return_if_fail (has_iter
);
571 gtk_tree_model_get (model
, &iter
, PLUGIN_POINTER
, &plugin
, -1);
573 g_return_if_fail (plugin
!= NULL
);
575 if (go_plugin_is_active (plugin
)) {
576 go_plugin_deactivate (plugin
, &error
);
579 int n_inactive_deps
= 0;
580 gboolean want_activate
= TRUE
;
582 dep_ids
= go_plugin_get_dependencies_ids (plugin
);
583 if (dep_ids
!= NULL
) {
586 s
= g_string_new (_("The following extra plugins must be activated in order to activate this one:\n\n"));
587 GO_SLIST_FOREACH (dep_ids
, char, plugin_id
,
590 plugin
= go_plugins_get_plugin_by_id (plugin_id
);
591 if (plugin
== NULL
) {
592 g_string_append_printf (s
, _("Unknown plugin with id=\"%s\"\n"), plugin_id
);
593 } else if (!go_plugin_is_active (plugin
)) {
594 g_string_append (s
, go_plugin_get_name (plugin
));
595 g_string_append_c (s
, '\n');
599 g_string_append (s
, _("\nDo you want to activate this plugin together with its dependencies?"));
600 if (n_inactive_deps
> 0) {
601 want_activate
= go_gtk_query_yes_no
602 (GTK_WINDOW (pm_gui
->dialog_pm
),
606 g_string_free (s
, TRUE
);
608 g_slist_free_full (dep_ids
, g_free
);
611 go_plugin_activate (plugin
, &error
);
617 GOErrorInfo
*new_error
;
619 if (go_plugin_is_active (plugin
)) {
620 new_error
= go_error_info_new_printf (
621 _("Error while deactivating plugin \"%s\"."),
622 go_plugin_get_name (plugin
));
624 new_error
= go_error_info_new_printf (
625 _("Error while activating plugin \"%s\"."),
626 go_plugin_get_name (plugin
));
628 go_error_info_add_details (new_error
, error
);
629 go_cmd_context_error_info (pm_gui
->cc
, new_error
);
634 cb_pm_close_clicked (PluginManagerGUI
*pm_gui
)
636 gtk_widget_destroy (GTK_WIDGET (pm_gui
->dialog_pm
));
640 dialog_plugin_manager (WBCGtk
*wbcg
)
642 PluginManagerGUI
*pm_gui
;
645 GtkWidget
*scrolled_directories
;
646 GtkTreeViewColumn
*column
;
647 GtkCellRenderer
*rend
;
649 g_return_if_fail (wbcg
!= NULL
);
650 g_return_if_fail (GNM_IS_WBC_GTK (wbcg
));
652 if (gnm_dialog_raise_if_exists (wbcg
, PLUGIN_MANAGER_DIALOG_KEY
))
655 gui
= gnm_gtk_builder_load ("res:ui/plugin-manager.ui", NULL
, GO_CMD_CONTEXT (wbcg
));
659 pm_gui
= g_new (PluginManagerGUI
, 1);
660 pm_gui
->cc
= GO_CMD_CONTEXT (wbcg
);
661 pm_gui
->parent_window
= wbcg_toplevel (wbcg
);
663 pm_gui
->dialog_pm
= GTK_DIALOG (go_gtk_builder_get_widget (gui
, "dialog_plugin_manager"));
665 /* Set-up plugin list page */
667 pm_gui
->button_activate_all
=
668 GTK_BUTTON (go_gtk_builder_get_widget (gui
, "button_activate_all"));
669 pm_gui
->button_rescan_directories
= GTK_BUTTON (go_gtk_builder_get_widget
670 (gui
, "button_rescan_directories"));
671 pm_gui
->checkbutton_install_new
= GTK_CHECK_BUTTON (go_gtk_builder_get_widget
672 (gui
, "checkbutton_install_new"));
674 pm_gui
->model_plugins
= gtk_list_store_new (
675 NUM_COLUMNS
, G_TYPE_STRING
, G_TYPE_BOOLEAN
, G_TYPE_BOOLEAN
, G_TYPE_POINTER
);
676 pm_gui
->list_plugins
= GTK_TREE_VIEW (
677 gtk_tree_view_new_with_model (GTK_TREE_MODEL (pm_gui
->model_plugins
)));
678 pm_gui
->selection
= gtk_tree_view_get_selection (pm_gui
->list_plugins
);
679 gtk_tree_selection_set_mode (pm_gui
->selection
, GTK_SELECTION_BROWSE
);
680 g_signal_connect (G_OBJECT (pm_gui
->selection
),
682 G_CALLBACK (cb_pm_selection_changed
), pm_gui
);
684 rend
= gtk_cell_renderer_toggle_new ();
685 g_signal_connect (G_OBJECT (rend
),
686 "toggled", G_CALLBACK (cb_active_toggled
), pm_gui
);
687 column
= gtk_tree_view_column_new_with_attributes (
689 "active", PLUGIN_ACTIVE
,
690 "activatable", PLUGIN_SWITCHABLE
,
692 gtk_tree_view_append_column (pm_gui
->list_plugins
, column
);
693 column
= gtk_tree_view_column_new_with_attributes (_("Plugin name"),
694 gtk_cell_renderer_text_new (),
695 "text", PLUGIN_NAME
, NULL
);
696 gtk_tree_view_column_set_sort_column_id (column
, PLUGIN_NAME
);
697 gtk_tree_view_append_column (pm_gui
->list_plugins
, column
);
698 scrolled
= go_gtk_builder_get_widget (gui
, "scrolled_plugin_list");
699 gtk_container_add (GTK_CONTAINER (scrolled
), GTK_WIDGET (pm_gui
->list_plugins
));
701 /* Set-up plugin details page */
703 pm_gui
->text_description
= gtk_text_view_get_buffer (GTK_TEXT_VIEW (
704 go_gtk_builder_get_widget (gui
, "textview_plugin_description")));
705 pm_gui
->entry_directory
= GTK_ENTRY (go_gtk_builder_get_widget (gui
, "entry_directory"));
707 pm_gui
->model_details
= gtk_tree_store_new (
708 DETAILS_NUM_COLUMNS
, G_TYPE_STRING
, G_TYPE_STRING
);
709 pm_gui
->view_details
= GTK_TREE_VIEW (
710 gtk_tree_view_new_with_model (GTK_TREE_MODEL (pm_gui
->model_details
)));
711 column
= gtk_tree_view_column_new_with_attributes (
712 _("Description"), gtk_cell_renderer_text_new (),
713 "text", DETAILS_DESC
, NULL
);
714 gtk_tree_view_append_column (pm_gui
->view_details
, column
);
715 column
= gtk_tree_view_column_new_with_attributes (
716 _("ID"), gtk_cell_renderer_text_new (),
717 "text", DETAILS_ID
, NULL
);
718 gtk_tree_view_append_column (pm_gui
->view_details
, column
);
719 scrolled
= go_gtk_builder_get_widget (gui
, "scrolled_plugin_details");
720 gtk_container_add (GTK_CONTAINER (scrolled
), GTK_WIDGET (pm_gui
->view_details
));
722 pm_gui
->frame_mark_for_deactivation
=
723 go_gtk_builder_get_widget (gui
, "mark-for-deactivation-grid");
724 pm_gui
->checkbutton_mark_for_deactivation
=
725 go_gtk_builder_get_widget (gui
, "checkbutton_mark_for_deactivation");
727 /* Set-up directories page */
729 pm_gui
->model_directories
= gtk_list_store_new (DIR_NUM_COLUMNS
, G_TYPE_STRING
,
731 pm_gui
->list_directories
= GTK_TREE_VIEW (
732 gtk_tree_view_new_with_model (GTK_TREE_MODEL (pm_gui
->model_directories
)));
733 pm_gui
->selection_directory
= gtk_tree_view_get_selection (pm_gui
->list_directories
);
734 gtk_tree_selection_set_mode (pm_gui
->selection_directory
, GTK_SELECTION_BROWSE
);
735 column
= gtk_tree_view_column_new_with_attributes (_("Directory"),
736 gtk_cell_renderer_text_new (),
739 gtk_tree_view_column_set_sort_column_id (column
, DIR_NAME
);
740 gtk_tree_view_append_column (pm_gui
->list_directories
, column
);
741 scrolled_directories
= go_gtk_builder_get_widget (gui
, "scrolled_directories");
742 gtk_container_add (GTK_CONTAINER (scrolled_directories
),
743 GTK_WIDGET (pm_gui
->list_directories
));
745 pm_gui
->button_directory_add
= GTK_BUTTON (go_gtk_builder_get_widget
746 (gui
, "button_directory_add"));
747 gtk_button_set_alignment (GTK_BUTTON (pm_gui
->button_directory_add
), 0., .5);
748 pm_gui
->button_directory_delete
= GTK_BUTTON (go_gtk_builder_get_widget
749 (gui
, "button_directory_delete"));
750 gtk_button_set_alignment (GTK_BUTTON (pm_gui
->button_directory_delete
), 0., .5);
752 cb_pm_dir_selection_changed (pm_gui
);
753 g_signal_connect_swapped (pm_gui
->selection_directory
,
755 G_CALLBACK (cb_pm_dir_selection_changed
), pm_gui
);
757 /* Done setting up pages */
759 pm_gui
->gnotebook
= GTK_NOTEBOOK (go_gtk_builder_get_widget (gui
, "notebook1"));
760 gtk_widget_show_all (GTK_WIDGET (pm_gui
->gnotebook
));
762 pm_gui_load_directory_page (pm_gui
);
764 pm_dialog_init (pm_gui
);
765 gnm_init_help_button (
766 go_gtk_builder_get_widget (gui
, "help_button"),
767 GNUMERIC_HELP_LINK_PLUGIN_MANAGER
);
768 g_signal_connect_swapped (go_gtk_builder_get_widget (gui
, "button_close_manager"),
770 G_CALLBACK (cb_pm_close_clicked
), pm_gui
);
772 gnm_keyed_dialog (wbcg
, GTK_WINDOW (pm_gui
->dialog_pm
),
773 PLUGIN_MANAGER_DIALOG_KEY
);
774 gtk_widget_show (GTK_WIDGET (pm_gui
->dialog_pm
));