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