1 /* Dia -- a diagram creation/manipulation program
2  * Copyright (C) 1998 Alexander Larsson
3  *
4  * plugin-manager.c: the dia plugin manager.
5  * Copyright (C) 2000 James Henstridge
6  * almost complete rewrite for gtk2
7  * Copyright (C) 2002 Hans Breuer
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22  */
23 
24 #ifdef HAVE_CONFIG_H
25 #  include <config.h>
26 #endif
27 
28 #include <string.h>
29 
30 #include <gtk/gtk.h>
31 
32 #include "plugin-manager.h"
33 #include "intl.h"
34 #include "plug-ins.h"
35 #include "message.h"
36 
37 static gint
pm_respond(GtkWidget * widget,gint response_id,gpointer data)38 pm_respond(GtkWidget *widget, gint response_id, gpointer data)
39 {
40   if (response_id != GTK_RESPONSE_APPLY)
41     gtk_widget_hide(widget);
42   return 0;
43 }
44 
45 enum
46 {
47   LOADED_COLUMN,
48   NAME_COLUMN,
49   DESC_COLUMN,
50   FILENAME_COLUMN,
51   AUTOLOAD_COLUMN,
52   PLUGIN_COLUMN,
53   NUM_COLUMNS
54 };
55 
56 static void
toggle_loaded_callback(GtkCellRendererToggle * celltoggle,gchar * path_string,GtkTreeView * tree_view)57 toggle_loaded_callback (GtkCellRendererToggle *celltoggle,
58                         gchar                 *path_string,
59                         GtkTreeView           *tree_view)
60 {
61   GtkTreeModel *model = gtk_tree_view_get_model (tree_view);
62   GtkTreePath *path;
63   GtkTreeIter iter;
64   gboolean loaded;
65   PluginInfo *info;
66 
67   path = gtk_tree_path_new_from_string (path_string);
68   if (!gtk_tree_model_get_iter (model, &iter, path))
69     {
70       g_warning ("%s: bad path?", G_STRLOC);
71       return;
72     }
73   gtk_tree_path_free (path);
74 
75   gtk_tree_model_get (GTK_TREE_MODEL (model), &iter,
76                       LOADED_COLUMN, &loaded, -1);
77   gtk_tree_model_get (GTK_TREE_MODEL (model), &iter,
78                       PLUGIN_COLUMN, &info, -1);
79 
80   if (loaded && dia_plugin_can_unload(info))
81     {
82       dia_plugin_unload(info);
83       loaded = FALSE;
84     }
85   else if (!loaded)
86     {
87       dia_plugin_load(info);
88       loaded = TRUE;
89     }
90   else
91     message_notice("Can't unload plug-in '%s'!", dia_plugin_get_name(info));
92   gtk_list_store_set (GTK_LIST_STORE (model), &iter,
93                       LOADED_COLUMN, loaded, -1);
94 }
95 
96 static void
can_unload(GtkTreeViewColumn * tree_column,GtkCellRenderer * cell,GtkTreeModel * tree_model,GtkTreeIter * iter,gpointer data)97 can_unload (GtkTreeViewColumn *tree_column,
98 	    GtkCellRenderer   *cell,
99 	    GtkTreeModel      *tree_model,
100 	    GtkTreeIter       *iter,
101 	    gpointer           data)
102 {
103   PluginInfo *info;
104   gboolean loaded;
105 
106   gtk_tree_model_get(tree_model, iter,
107                      PLUGIN_COLUMN, &info, -1);
108   gtk_tree_model_get(tree_model, iter,
109                      LOADED_COLUMN, &loaded, -1);
110   if (!loaded || (loaded && dia_plugin_can_unload(info)))
111     {
112       cell->mode = GTK_CELL_RENDERER_MODE_ACTIVATABLE;
113       GTK_CELL_RENDERER_TOGGLE(cell)->activatable = TRUE;
114     }
115   else
116     {
117       cell->mode = GTK_CELL_RENDERER_MODE_INERT;
118       GTK_CELL_RENDERER_TOGGLE(cell)->activatable = FALSE;
119     }
120 }
121 
122 static void
toggle_autoload_callback(GtkCellRendererToggle * celltoggle,gchar * path_string,GtkTreeView * tree_view)123 toggle_autoload_callback (GtkCellRendererToggle *celltoggle,
124                           gchar                 *path_string,
125                           GtkTreeView           *tree_view)
126 {
127   GtkTreeModel *model = gtk_tree_view_get_model (tree_view);
128   GtkTreePath *path;
129   GtkTreeIter iter;
130   gboolean load;
131   PluginInfo *info;
132 
133   path = gtk_tree_path_new_from_string (path_string);
134   if (!gtk_tree_model_get_iter (model, &iter, path))
135     {
136       g_warning ("%s: bad path?", G_STRLOC);
137       return;
138     }
139   gtk_tree_path_free (path);
140 
141   gtk_tree_model_get (GTK_TREE_MODEL (model), &iter,
142                       AUTOLOAD_COLUMN, &load, -1);
143   gtk_tree_model_get (GTK_TREE_MODEL (model), &iter,
144                       PLUGIN_COLUMN, &info, -1);
145 
146   /* Disabling 'Standard' is fatal at next startup, while
147    * disabling 'Internal' is simply impossible
148    */
149   if (   0 == strcmp(dia_plugin_get_name(info), "Standard")
150       || 0 == strcmp(dia_plugin_get_name(info), "Internal"))
151     message_notice("You don't want to inhibit loading\n"
152                    "of plug-in '%s'!", dia_plugin_get_name(info));
153   else {
154     dia_plugin_set_inhibit_load(info, load);
155     gtk_list_store_set (GTK_LIST_STORE (model), &iter,
156                         AUTOLOAD_COLUMN, !load, -1);
157   }
158 }
159 
160 static void
can_inhibit(GtkTreeViewColumn * tree_column,GtkCellRenderer * cell,GtkTreeModel * tree_model,GtkTreeIter * iter,gpointer data)161 can_inhibit (GtkTreeViewColumn *tree_column,
162 	     GtkCellRenderer   *cell,
163 	     GtkTreeModel      *tree_model,
164 	     GtkTreeIter       *iter,
165 	     gpointer           data)
166 {
167   PluginInfo *info;
168 
169   gtk_tree_model_get(tree_model, iter,
170                      PLUGIN_COLUMN, &info, -1);
171   if (   0 == strcmp(dia_plugin_get_name(info), "Standard")
172       || 0 == strcmp(dia_plugin_get_name(info), "Internal"))
173     {
174       cell->mode = GTK_CELL_RENDERER_MODE_INERT;
175       GTK_CELL_RENDERER_TOGGLE(cell)->activatable = FALSE;
176     }
177   else
178     {
179       cell->mode = GTK_CELL_RENDERER_MODE_ACTIVATABLE;
180       GTK_CELL_RENDERER_TOGGLE(cell)->activatable = TRUE;
181     }
182 }
183 
184 static GtkWidget *
get_plugin_manager(void)185 get_plugin_manager(void)
186 {
187   static GtkWidget *dialog = NULL;
188   GtkWidget *vbox, *scrolled_window, *tree_view;
189   GtkListStore *store;
190   GtkCellRenderer *renderer;
191   GtkTreeViewColumn *col;
192   GtkTreeIter iter;
193   GList *tmp;
194 
195   if (dialog)
196     return dialog;
197 
198   /* build up the user interface */
199   dialog = gtk_dialog_new_with_buttons(
200 		_("Plug-ins"),
201 		NULL, 0,
202 		GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
203 		NULL);
204 
205   gtk_dialog_set_default_response (GTK_DIALOG(dialog), GTK_RESPONSE_CLOSE);
206 
207   vbox = GTK_DIALOG(dialog)->vbox;
208 
209   /* don't destroy dialog when window manager close button pressed */
210   g_signal_connect(G_OBJECT (dialog), "response",
211 		   G_CALLBACK(pm_respond), NULL);
212   g_signal_connect(G_OBJECT(dialog), "delete_event",
213 		   G_CALLBACK(gtk_widget_hide), NULL);
214   g_signal_connect(GTK_OBJECT(dialog), "delete_event",
215 		   G_CALLBACK(gtk_true), NULL);
216   g_signal_connect(GTK_OBJECT(dialog), "destroy",
217 		   G_CALLBACK(gtk_widget_destroyed), &dialog);
218 
219   scrolled_window = gtk_scrolled_window_new (NULL, NULL);
220   gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window), GTK_SHADOW_ETCHED_IN);
221   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
222   gtk_box_pack_start (GTK_BOX (vbox), scrolled_window, TRUE, TRUE, 0);
223 
224   /* create the TreeStore */
225   store = gtk_list_store_new (NUM_COLUMNS,
226                               G_TYPE_BOOLEAN,
227                               G_TYPE_STRING,
228                               G_TYPE_STRING,
229                               G_TYPE_STRING,
230                               G_TYPE_BOOLEAN,
231                               G_TYPE_POINTER);
232   tree_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store));
233   gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (tree_view), TRUE);
234 
235   /* fill list */
236   for (tmp = dia_list_plugins(); tmp != NULL; tmp = tmp->next) {
237     PluginInfo *info = tmp->data;
238 
239     gtk_list_store_append (store, &iter);
240     gtk_list_store_set (store, &iter,
241                         LOADED_COLUMN, dia_plugin_is_loaded(info),
242 			NAME_COLUMN, dia_plugin_get_name(info),
243 			DESC_COLUMN, dia_plugin_get_description(info),
244 			FILENAME_COLUMN, dia_plugin_get_filename(info),
245                         AUTOLOAD_COLUMN, !dia_plugin_get_inhibit_load(info),
246                         PLUGIN_COLUMN, info,
247 			-1);
248   }
249 
250   /* setup renderers and view */
251   renderer = gtk_cell_renderer_toggle_new ();
252   g_signal_connect(G_OBJECT (renderer), "toggled",
253 		   G_CALLBACK (toggle_loaded_callback), tree_view);
254   col = gtk_tree_view_column_new_with_attributes(
255 		   _("Loaded"), renderer,
256 		   "active", LOADED_COLUMN, NULL);
257   gtk_tree_view_column_set_cell_data_func (
258   		   col, renderer, can_unload, NULL, NULL);
259   gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), col);
260 
261   col = gtk_tree_view_column_new_with_attributes(
262 		   _("Name"), gtk_cell_renderer_text_new (),
263 		   "text", NAME_COLUMN, NULL);
264   gtk_tree_view_column_set_sort_column_id (col, NAME_COLUMN);
265   gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), col);
266 
267   col = gtk_tree_view_column_new_with_attributes(
268 		   _("Description"), gtk_cell_renderer_text_new (),
269 		   "text", DESC_COLUMN, NULL);
270   gtk_tree_view_column_set_sort_column_id (col, DESC_COLUMN);
271   gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), col);
272 
273   renderer = gtk_cell_renderer_toggle_new ();
274   g_signal_connect(G_OBJECT (renderer), "toggled",
275 		   G_CALLBACK (toggle_autoload_callback), tree_view);
276   col = gtk_tree_view_column_new_with_attributes(
277 	      _("Load at Startup"), renderer,
278 	      "active", AUTOLOAD_COLUMN, NULL);
279   gtk_tree_view_column_set_cell_data_func (
280   		   col, renderer, can_inhibit, NULL, NULL);
281   gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), col);
282 
283   col = gtk_tree_view_column_new_with_attributes(
284 		   _("File Name"), gtk_cell_renderer_text_new (),
285 		   "text", FILENAME_COLUMN, NULL);
286   gtk_tree_view_column_set_sort_column_id (col, FILENAME_COLUMN);
287   gtk_tree_view_append_column (GTK_TREE_VIEW (tree_view), col);
288 
289   gtk_container_add (GTK_CONTAINER (scrolled_window), tree_view);
290   gtk_window_set_default_size (GTK_WINDOW (dialog), 480, 400);
291   gtk_widget_show_all (dialog);
292 
293   return dialog;
294 }
295 
296 void
file_plugins_callback(gpointer data,guint action,GtkWidget * widget)297 file_plugins_callback(gpointer data, guint action, GtkWidget *widget)
298 {
299   GtkWidget *pm = get_plugin_manager();
300 
301   gtk_widget_show(pm);
302 }
303