GUI: Move .ui files from goffice resources to glib resources
[gnumeric.git] / src / dialogs / dialog-plugin-manager.c
blobafe45852fb79524de88b59a34f96bf76c4208c3d
1 /* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3 * plugin-manager.c: Dialog used to load plugins into the Gnumeric
4 * spreadsheet
6 * Authors:
7 * Old plugin manager:
8 * Dom Lachowicz (dominicl@seas.upenn.edu)
9 * Tom Dyas (tdyas@romulus.rutgers.edu)
10 * New plugin manager:
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>
30 #include "dialogs.h"
31 #include "help.h"
32 #include <application.h>
33 #include <wbc-gtk.h>
34 #include <gnumeric-conf.h>
35 #include <gutils.h>
36 #include <gui-util.h>
38 #include <goffice/goffice.h>
40 #include <gtk/gtk.h>
41 #include <gsf/gsf-impl-utils.h>
43 #include <string.h>
45 #define PLUGIN_MANAGER_DIALOG_KEY "plugin-manager-dialog"
47 typedef struct {
48 GOCmdContext *cc;
49 GtkWindow *parent_window;
50 GtkBuilder *gui;
51 GtkDialog *dialog_pm;
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;
69 } PluginManagerGUI;
71 enum {
72 PLUGIN_NAME,
73 PLUGIN_ACTIVE,
74 PLUGIN_SWITCHABLE,
75 PLUGIN_POINTER,
76 NUM_COLUMNS
78 enum {
79 DIR_NAME,
80 DIR_IS_SYSTEM,
81 DIR_NUM_COLUMNS
83 enum {
84 DETAILS_DESC,
85 DETAILS_ID,
86 DETAILS_NUM_COLUMNS
90 static int
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));
99 static gboolean
100 model_get_plugin_iter (GtkTreeModel *model, gpointer plugin, GtkTreeIter *ret_iter)
102 gboolean has_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)) {
106 gpointer current;
108 gtk_tree_model_get (model, ret_iter, PLUGIN_POINTER, &current, -1);
109 if (current == plugin) {
110 return TRUE;
114 return FALSE;
117 static void
118 cb_plugin_changed (GOPlugin *plugin, PluginManagerGUI *pm_gui)
120 GtkTreeIter iter;
122 if (model_get_plugin_iter (GTK_TREE_MODEL (pm_gui->model_plugins), plugin, &iter)) {
123 gtk_list_store_set (
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),
127 -1);
131 static void
132 cb_plugin_destroyed (PluginManagerGUI *pm_gui, GObject *ex_plugin)
134 GtkTreeIter iter;
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);
141 static void
142 set_plugin_model_row (PluginManagerGUI *pm_gui, GtkTreeIter *iter, GOPlugin *plugin)
144 gtk_list_store_set (
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,
150 -1);
151 g_signal_connect (
152 G_OBJECT (plugin), "state_changed",
153 G_CALLBACK (cb_plugin_changed), pm_gui);
154 g_signal_connect (
155 G_OBJECT (plugin), "can_deactivate_changed",
156 G_CALLBACK (cb_plugin_changed), pm_gui);
157 g_object_weak_ref (
158 G_OBJECT (plugin), (GWeakNotify) cb_plugin_destroyed, pm_gui);
161 static void
162 cb_pm_button_rescan_directories_clicked (PluginManagerGUI *pm_gui)
164 GOErrorInfo *error;
165 GSList *new_plugins, *l;
166 GtkTreeModel *model = GTK_TREE_MODEL (pm_gui->model_plugins);
167 GtkTreeIter iter, new_iter;
168 gboolean has_iter;
170 go_plugins_rescan (&error, &new_plugins);
171 if (error != NULL) {
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);
185 l = l->next;
186 if (l == NULL)
187 break;
190 while (l != NULL) {
191 gtk_list_store_append (pm_gui->model_plugins, &new_iter);
192 set_plugin_model_row (pm_gui, &new_iter, GO_PLUGIN (l->data));
193 l = l->next;
195 g_slist_free (new_plugins);
198 static void
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)));
206 static void
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) {
211 GtkTreeIter iter;
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,
216 -1);
220 static void
221 pm_gui_load_directory_page (PluginManagerGUI *pm_gui)
223 GtkTreeIter iter;
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 ();
228 GSList *plugin_dirs;
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,
236 DIR_IS_SYSTEM, TRUE,
237 -1);
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,
242 DIR_IS_SYSTEM, TRUE,
243 -1);
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,
248 DIR_IS_SYSTEM, TRUE,
249 -1);
250 g_free (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);
261 static void
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. */
272 "local-only", TRUE,
273 NULL));
274 gtk_dialog_add_buttons (GTK_DIALOG (fsel),
275 _("Cancel"), GTK_RESPONSE_CANCEL,
276 _("Add"), GTK_RESPONSE_OK,
277 NULL);
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);
285 g_free (path);
286 path = dir_name;
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);
301 } else
302 g_free (path);
305 gtk_widget_destroy (GTK_WIDGET (fsel));
308 static void
309 cb_pm_button_directory_delete_clicked (PluginManagerGUI *pm_gui)
311 GtkTreeIter iter;
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))
317 return;
319 gtk_tree_model_get (GTK_TREE_MODEL (pm_gui->model_directories), &iter,
320 DIR_NAME, &dir_name,
321 DIR_IS_SYSTEM, &is_system,
322 -1);
324 extra_dirs = go_string_slist_copy (gnm_conf_get_plugins_extra_dirs ());
325 res = is_system
326 ? NULL
327 : g_slist_find_custom (extra_dirs, dir_name, go_str_compare);
329 if (res) {
330 extra_dirs = g_slist_remove_link (extra_dirs, res);
331 g_free (res->data);
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);
341 g_free (dir_name);
344 static void
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)));
351 static void
352 cb_pm_selection_changed (GtkTreeSelection *selection, PluginManagerGUI *pm_gui)
354 GOPlugin *pinfo;
355 GtkTreeIter iter;
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);
370 } else {
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) {
378 plugin_desc = "";
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);
386 gtk_tree_store_set (
387 pm_gui->model_details, &iter,
388 DETAILS_DESC, go_plugin_get_name (pinfo),
389 DETAILS_ID, go_plugin_get_id (pinfo),
390 -1);
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);
394 gtk_tree_store_set (
395 pm_gui->model_details, &iter2,
396 DETAILS_DESC, _("Plugin dependencies"),
397 DETAILS_ID, "",
398 -1);
399 GO_SLIST_FOREACH (dep_ids, char, dep_id,
400 GOPlugin *dep_plugin;
401 const char *name;
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);
406 gtk_tree_store_set (
407 pm_gui->model_details, &iter3,
408 DETAILS_DESC, name,
409 DETAILS_ID, dep_id,
410 -1);
413 g_slist_free_full (dep_ids, g_free);
415 gtk_tree_store_append (pm_gui->model_details, &iter2, &iter);
416 gtk_tree_store_set (
417 pm_gui->model_details, &iter2,
418 DETAILS_DESC, _("Plugin services"),
419 DETAILS_ID, "",
420 -1);
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);
424 gtk_tree_store_set (
425 pm_gui->model_details, &iter3,
426 DETAILS_DESC, go_plugin_service_get_description (service),
427 DETAILS_ID, go_plugin_service_get_id (service),
428 -1);
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));
436 g_signal_connect (
437 pm_gui->checkbutton_mark_for_deactivation, "toggled",
438 G_CALLBACK (cb_checkbutton_mark_for_deactivation_toggled),
439 pinfo);
440 gtk_widget_show (pm_gui->frame_mark_for_deactivation);
441 } else {
442 gtk_widget_hide (pm_gui->frame_mark_for_deactivation);
447 static void
448 cb_pm_dialog_free (PluginManagerGUI *pm_gui)
450 GtkTreeModel *model = GTK_TREE_MODEL (pm_gui->model_plugins);
451 GtkTreeIter iter;
452 gboolean has_iter;
454 for (has_iter = gtk_tree_model_get_iter_first (model, &iter);
455 has_iter; has_iter = gtk_tree_model_iter_next (model, &iter)) {
456 gpointer plugin;
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);
475 g_free (pm_gui);
478 static void
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);
495 static void
496 pm_dialog_init (PluginManagerGUI *pm_gui)
498 GSList *sorted_plugin_list;
499 GtkTreeIter iter;
501 g_signal_connect (G_OBJECT (pm_gui->button_activate_all),
502 "clicked",
503 G_CALLBACK (cb_pm_button_activate_all_clicked), pm_gui);
504 g_signal_connect_swapped (G_OBJECT (pm_gui->button_rescan_directories),
505 "clicked",
506 G_CALLBACK (cb_pm_button_rescan_directories_clicked), pm_gui);
507 g_signal_connect_swapped (G_OBJECT (pm_gui->button_directory_add),
508 "clicked",
509 G_CALLBACK (cb_pm_button_directory_add_clicked), pm_gui);
510 g_signal_connect_swapped (G_OBJECT (pm_gui->button_directory_delete),
511 "clicked",
512 G_CALLBACK (cb_pm_button_directory_delete_clicked), pm_gui);
513 g_signal_connect (G_OBJECT (pm_gui->checkbutton_install_new),
514 "toggled",
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);
536 static void
537 cb_pm_dir_selection_changed (PluginManagerGUI *pm_gui)
539 GtkTreeIter iter;
540 gboolean is_system;
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);
544 return;
547 gtk_tree_model_get (GTK_TREE_MODEL (pm_gui->model_directories), &iter,
548 DIR_IS_SYSTEM, &is_system,
549 -1);
551 gtk_widget_set_sensitive (GTK_WIDGET (pm_gui->button_directory_delete), !is_system);
555 static void
556 cb_active_toggled (G_GNUC_UNUSED GtkCellRendererToggle *celltoggle,
557 char *path,
558 PluginManagerGUI *pm_gui)
560 GtkTreeModel *model;
561 GtkTreeIter iter;
562 GOPlugin *plugin;
563 GOErrorInfo *error;
564 gboolean has_iter;
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);
577 } else {
578 GSList *dep_ids;
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) {
584 GString *s;
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,
588 GOPlugin *plugin;
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');
596 n_inactive_deps++;
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),
603 TRUE,
604 "%s", s->str);
606 g_string_free (s, TRUE);
608 g_slist_free_full (dep_ids, g_free);
610 if (want_activate) {
611 go_plugin_activate (plugin, &error);
612 } else {
613 error = NULL;
616 if (error != NULL) {
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));
623 } else {
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);
633 static void
634 cb_pm_close_clicked (PluginManagerGUI *pm_gui)
636 gtk_widget_destroy (GTK_WIDGET (pm_gui->dialog_pm));
639 void
640 dialog_plugin_manager (WBCGtk *wbcg)
642 PluginManagerGUI *pm_gui;
643 GtkBuilder *gui;
644 GtkWidget *scrolled;
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))
653 return;
655 gui = gnm_gtk_builder_load ("res:ui/plugin-manager.ui", NULL, GO_CMD_CONTEXT (wbcg));
656 if (gui == NULL)
657 return;
659 pm_gui = g_new (PluginManagerGUI, 1);
660 pm_gui->cc = GO_CMD_CONTEXT (wbcg);
661 pm_gui->parent_window = wbcg_toplevel (wbcg);
662 pm_gui->gui = gui;
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),
681 "changed",
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 (
688 _("Active"), rend,
689 "active", PLUGIN_ACTIVE,
690 "activatable", PLUGIN_SWITCHABLE,
691 NULL);
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,
730 G_TYPE_BOOLEAN);
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 (),
737 "text", DIR_NAME,
738 NULL);
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,
754 "changed",
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"),
769 "clicked",
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));