Mercurial > pidgin.yaz
comparison src/gtkplugin.c @ 12927:3cc18baeaca3
[gaim-migrate @ 15280]
I've added a confirmation dialog when unloading a plugin on which other
plugins depend. Also, I've add plugin-load/plugin-unload signal handlers
to update the dialog. This fixes problems that occur when you load a plugin
with dependencies (causing the core to load additional plugins).
committer: Tailor Script <tailor@pidgin.im>
author | Richard Laager <rlaager@wiktel.com> |
---|---|
date | Wed, 18 Jan 2006 18:27:06 +0000 |
parents | bba0faa37f3a |
children | 71fbe885c50b |
comparison
equal
deleted
inserted
replaced
12926:2c4f20ff387c | 12927:3cc18baeaca3 |
---|---|
26 #include "gtkgaim.h" | 26 #include "gtkgaim.h" |
27 #include "gtkplugin.h" | 27 #include "gtkplugin.h" |
28 #include "gtkpluginpref.h" | 28 #include "gtkpluginpref.h" |
29 #include "debug.h" | 29 #include "debug.h" |
30 #include "prefs.h" | 30 #include "prefs.h" |
31 #include "request.h" | |
31 | 32 |
32 #include <string.h> | 33 #include <string.h> |
33 | 34 |
34 #define GAIM_RESPONSE_CONFIGURE 98121 | 35 #define GAIM_RESPONSE_CONFIGURE 98121 |
36 | |
37 static void plugin_toggled_stage_two(GaimPlugin *plug, GtkTreeModel *model, | |
38 GtkTreeIter *iter, gboolean unload); | |
35 | 39 |
36 static GtkWidget *expander = NULL; | 40 static GtkWidget *expander = NULL; |
37 static GtkWidget *plugin_dialog = NULL; | 41 static GtkWidget *plugin_dialog = NULL; |
38 static GtkWidget *plugin_details = NULL; | 42 static GtkWidget *plugin_details = NULL; |
39 static GtkWidget *pref_button = NULL; | 43 static GtkWidget *pref_button = NULL; |
149 2, plug, | 153 2, plug, |
150 3, gaim_plugin_is_unloadable(plug), | 154 3, gaim_plugin_is_unloadable(plug), |
151 -1); | 155 -1); |
152 g_free(desc); | 156 g_free(desc); |
153 } | 157 } |
158 } | |
159 | |
160 static void plugin_loading_common(GaimPlugin *plugin, GtkTreeView *view, gboolean loaded) | |
161 { | |
162 GtkTreeIter iter; | |
163 GtkTreeModel *model = gtk_tree_view_get_model(view); | |
164 | |
165 if (gtk_tree_model_get_iter_first(model, &iter)) { | |
166 do { | |
167 GaimPlugin *plug; | |
168 GtkTreeSelection *sel; | |
169 | |
170 gtk_tree_model_get(model, &iter, 2, &plug, -1); | |
171 | |
172 if (plug != plugin) | |
173 continue; | |
174 | |
175 gtk_list_store_set(GTK_LIST_STORE(model), &iter, 0, loaded, -1); | |
176 | |
177 /* If the loaded/unloaded plugin is the selected row, | |
178 * update the pref_button. */ | |
179 sel = gtk_tree_view_get_selection(view); | |
180 if (gtk_tree_selection_get_selected(sel, &model, &iter)) | |
181 { | |
182 gtk_tree_model_get(model, &iter, 2, &plug, -1); | |
183 if (plug == plugin) | |
184 { | |
185 gtk_widget_set_sensitive(pref_button, | |
186 loaded | |
187 && ((GAIM_IS_GTK_PLUGIN(plug) && plug->info->ui_info | |
188 && GAIM_GTK_PLUGIN_UI_INFO(plug)->get_config_frame) | |
189 || (plug->info->prefs_info | |
190 && plug->info->prefs_info->get_plugin_pref_frame))); | |
191 } | |
192 } | |
193 | |
194 break; | |
195 } while (gtk_tree_model_iter_next(model, &iter)); | |
196 } | |
197 } | |
198 | |
199 static void plugin_load_cb(GaimPlugin *plugin, gpointer data) | |
200 { | |
201 GtkTreeView *view = (GtkTreeView *)data; | |
202 plugin_loading_common(plugin, view, TRUE); | |
203 } | |
204 | |
205 static void plugin_unload_cb(GaimPlugin *plugin, gpointer data) | |
206 { | |
207 GtkTreeView *view = (GtkTreeView *)data; | |
208 plugin_loading_common(plugin, view, FALSE); | |
154 } | 209 } |
155 | 210 |
156 static void pref_dialog_response_cb(GtkWidget *d, int response, GaimPlugin *plug) | 211 static void pref_dialog_response_cb(GtkWidget *d, int response, GaimPlugin *plug) |
157 { | 212 { |
158 switch (response) { | 213 switch (response) { |
166 gtk_widget_destroy(d); | 221 gtk_widget_destroy(d); |
167 break; | 222 break; |
168 } | 223 } |
169 } | 224 } |
170 | 225 |
171 static void plugin_load (GtkCellRendererToggle *cell, gchar *pth, gpointer data) | 226 static void plugin_unload_confirm_cb(gpointer *data) |
227 { | |
228 GaimPlugin *plugin = (GaimPlugin *)data[0]; | |
229 GtkTreeModel *model = (GtkTreeModel *)data[1]; | |
230 GtkTreeIter *iter = (GtkTreeIter *)data[2]; | |
231 | |
232 plugin_toggled_stage_two(plugin, model, iter, TRUE); | |
233 | |
234 g_free(data); | |
235 } | |
236 | |
237 static void plugin_toggled(GtkCellRendererToggle *cell, gchar *pth, gpointer data) | |
172 { | 238 { |
173 GtkTreeModel *model = (GtkTreeModel *)data; | 239 GtkTreeModel *model = (GtkTreeModel *)data; |
174 GtkTreeIter iter; | 240 GtkTreeIter *iter = g_new(GtkTreeIter, 1); |
175 GtkTreePath *path = gtk_tree_path_new_from_string(pth); | 241 GtkTreePath *path = gtk_tree_path_new_from_string(pth); |
176 GaimPlugin *plug; | 242 GaimPlugin *plug; |
177 gchar buf[1024]; | |
178 gchar *name = NULL, *description = NULL; | |
179 GtkWidget *dialog = NULL; | 243 GtkWidget *dialog = NULL; |
180 GdkCursor *wait; | 244 |
181 | 245 gtk_tree_model_get_iter(model, iter, path); |
182 gtk_tree_model_get_iter (model, &iter, path); | 246 gtk_tree_path_free(path); |
183 gtk_tree_model_get (model, &iter, 2, &plug, -1); | 247 gtk_tree_model_get(model, iter, 2, &plug, -1); |
184 | 248 |
185 /* Apparently, GTK+ won't honor the sensitive flag on cell renderers for booleans. */ | 249 /* Apparently, GTK+ won't honor the sensitive flag on cell renderers for booleans. */ |
186 if (gaim_plugin_is_unloadable(plug)) | 250 if (gaim_plugin_is_unloadable(plug)) |
251 { | |
252 g_free(iter); | |
187 return; | 253 return; |
188 | 254 } |
189 wait = gdk_cursor_new (GDK_WATCH); | |
190 gdk_window_set_cursor(plugin_dialog->window, wait); | |
191 gdk_cursor_unref(wait); | |
192 | 255 |
193 if (!gaim_plugin_is_loaded(plug)) | 256 if (!gaim_plugin_is_loaded(plug)) |
257 { | |
258 GdkCursor *wait = gdk_cursor_new (GDK_WATCH); | |
259 gdk_window_set_cursor(plugin_dialog->window, wait); | |
260 gdk_cursor_unref(wait); | |
261 | |
194 gaim_plugin_load(plug); | 262 gaim_plugin_load(plug); |
195 else { | 263 plugin_toggled_stage_two(plug, model, iter, FALSE); |
264 | |
265 gdk_window_set_cursor(plugin_dialog->window, NULL); | |
266 } | |
267 else | |
268 { | |
196 if (plugin_pref_dialogs != NULL && | 269 if (plugin_pref_dialogs != NULL && |
197 (dialog = g_hash_table_lookup(plugin_pref_dialogs, plug))) | 270 (dialog = g_hash_table_lookup(plugin_pref_dialogs, plug))) |
198 pref_dialog_response_cb(dialog, GTK_RESPONSE_DELETE_EVENT, plug); | 271 pref_dialog_response_cb(dialog, GTK_RESPONSE_DELETE_EVENT, plug); |
272 | |
273 if (plug->dependent_plugins != NULL) | |
274 { | |
275 GString *tmp = g_string_new(_("The following plugins will be unloaded.")); | |
276 GList *l; | |
277 gpointer *cb_data; | |
278 | |
279 for (l = plug->dependent_plugins ; l != NULL ; l = l->next) | |
280 { | |
281 const char *dep_name = (const char *)l->data; | |
282 GaimPlugin *dep_plugin = gaim_plugins_find_with_id(dep_name); | |
283 g_return_if_fail(dep_plugin != NULL); | |
284 | |
285 g_string_append_printf(tmp, "\n\t%s\n", _(dep_plugin->info->name)); | |
286 } | |
287 | |
288 cb_data = g_new(gpointer, 3); | |
289 cb_data[0] = plug; | |
290 cb_data[1] = model; | |
291 cb_data[2] = iter; | |
292 | |
293 gaim_request_action(plugin_dialog, NULL, | |
294 _("Multiple plugins will be unloaded."), | |
295 tmp->str, 0, cb_data, 2, | |
296 _("Unload Plugins"), G_CALLBACK(plugin_unload_confirm_cb), | |
297 _("Cancel"), NULL); | |
298 g_string_free(tmp, TRUE); | |
299 } | |
300 else | |
301 plugin_toggled_stage_two(plug, model, iter, TRUE); | |
302 } | |
303 } | |
304 | |
305 static void plugin_toggled_stage_two(GaimPlugin *plug, GtkTreeModel *model, GtkTreeIter *iter, gboolean unload) | |
306 { | |
307 gchar *name = NULL; | |
308 gchar *description = NULL; | |
309 | |
310 if (unload) | |
311 { | |
312 GdkCursor *wait = gdk_cursor_new (GDK_WATCH); | |
313 gdk_window_set_cursor(plugin_dialog->window, wait); | |
314 gdk_cursor_unref(wait); | |
315 | |
199 gaim_plugin_unload(plug); | 316 gaim_plugin_unload(plug); |
317 | |
318 gdk_window_set_cursor(plugin_dialog->window, NULL); | |
200 } | 319 } |
201 | 320 |
202 gtk_widget_set_sensitive(pref_button, | 321 gtk_widget_set_sensitive(pref_button, |
203 gaim_plugin_is_loaded(plug) | 322 gaim_plugin_is_loaded(plug) |
204 && ((GAIM_IS_GTK_PLUGIN(plug) && plug->info->ui_info | 323 && ((GAIM_IS_GTK_PLUGIN(plug) && plug->info->ui_info |
205 && GAIM_GTK_PLUGIN_UI_INFO(plug)->get_config_frame) | 324 && GAIM_GTK_PLUGIN_UI_INFO(plug)->get_config_frame) |
206 || (plug->info->prefs_info | 325 || (plug->info->prefs_info |
207 && plug->info->prefs_info->get_plugin_pref_frame))); | 326 && plug->info->prefs_info->get_plugin_pref_frame))); |
208 | 327 |
209 gdk_window_set_cursor(plugin_dialog->window, NULL); | |
210 | |
211 name = g_markup_escape_text(_(plug->info->name), -1); | 328 name = g_markup_escape_text(_(plug->info->name), -1); |
212 description = g_markup_escape_text(_(plug->info->description), -1); | 329 description = g_markup_escape_text(_(plug->info->description), -1); |
213 | 330 |
214 if (plug->error != NULL) { | 331 if (plug->error != NULL) { |
215 gchar *error = g_markup_escape_text(plug->error, -1); | 332 gchar *error = g_markup_escape_text(plug->error, -1); |
216 gchar *desc; | 333 gchar *desc; |
217 g_snprintf(buf, sizeof(buf), | 334 gchar *text = g_strdup_printf( |
218 "<span size=\"larger\">%s %s</span>\n\n" | 335 "<span size=\"larger\">%s %s</span>\n\n" |
219 "<span weight=\"bold\" color=\"red\">%s</span>\n\n" | 336 "<span weight=\"bold\" color=\"red\">%s</span>\n\n" |
220 "%s", | 337 "%s", |
221 name, plug->info->version, error, description); | 338 name, plug->info->version, error, description); |
222 desc = g_strdup_printf("<b>%s</b> %s\n<span weight=\"bold\" color=\"red\"%s</span>", | 339 desc = g_strdup_printf("<b>%s</b> %s\n<span weight=\"bold\" color=\"red\"%s</span>", |
223 plug->info->name, plug->info->version, error); | 340 plug->info->name, plug->info->version, error); |
224 gtk_list_store_set (GTK_LIST_STORE (model), &iter, | 341 gtk_list_store_set(GTK_LIST_STORE (model), iter, |
225 1, desc, | 342 1, desc, |
226 -1); | 343 -1); |
227 g_free(desc); | 344 g_free(desc); |
228 g_free(error); | 345 g_free(error); |
229 gtk_label_set_markup(GTK_LABEL(plugin_details), buf); | 346 gtk_label_set_markup(GTK_LABEL(plugin_details), text); |
347 g_free(text); | |
230 } | 348 } |
231 g_free(name); | 349 g_free(name); |
232 g_free(description); | 350 g_free(description); |
233 | 351 |
234 | 352 |
235 gtk_list_store_set (GTK_LIST_STORE (model), &iter, | 353 gtk_list_store_set(GTK_LIST_STORE (model), iter, |
236 0, gaim_plugin_is_loaded(plug), | 354 0, gaim_plugin_is_loaded(plug), |
237 -1); | 355 -1); |
238 | 356 g_free(iter); |
239 gtk_tree_path_free(path); | 357 |
240 gaim_gtk_plugins_save(); | 358 gaim_gtk_plugins_save(); |
241 } | 359 } |
242 | 360 |
243 static gboolean ensure_plugin_visible(void *data) | 361 static gboolean ensure_plugin_visible(void *data) |
244 { | 362 { |
339 GtkTreeIter iter; | 457 GtkTreeIter iter; |
340 | 458 |
341 switch (response) { | 459 switch (response) { |
342 case GTK_RESPONSE_CLOSE: | 460 case GTK_RESPONSE_CLOSE: |
343 case GTK_RESPONSE_DELETE_EVENT: | 461 case GTK_RESPONSE_DELETE_EVENT: |
462 gaim_request_close_with_handle(plugin_dialog); | |
463 gaim_signals_disconnect_by_handle(plugin_dialog); | |
344 gtk_widget_destroy(d); | 464 gtk_widget_destroy(d); |
345 if (plugin_pref_dialogs != NULL) { | 465 if (plugin_pref_dialogs != NULL) { |
346 g_hash_table_destroy(plugin_pref_dialogs); | 466 g_hash_table_destroy(plugin_pref_dialogs); |
347 plugin_pref_dialogs = NULL; | 467 plugin_pref_dialogs = NULL; |
348 } | 468 } |
433 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS); | 553 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS); |
434 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW(sw), GTK_SHADOW_IN); | 554 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW(sw), GTK_SHADOW_IN); |
435 | 555 |
436 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(plugin_dialog)->vbox), sw, TRUE, TRUE, 0); | 556 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(plugin_dialog)->vbox), sw, TRUE, TRUE, 0); |
437 | 557 |
438 ls = gtk_list_store_new (4, G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_BOOLEAN); | 558 ls = gtk_list_store_new(4, G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_BOOLEAN); |
439 gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(ls), | 559 gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(ls), |
440 1, GTK_SORT_ASCENDING); | 560 1, GTK_SORT_ASCENDING); |
441 | 561 |
442 update_plugin_list(ls); | 562 update_plugin_list(ls); |
443 | 563 |
444 event_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL(ls)); | 564 event_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(ls)); |
445 | 565 |
446 g_signal_connect(G_OBJECT(event_view), "row-activated", | 566 g_signal_connect(G_OBJECT(event_view), "row-activated", |
447 G_CALLBACK(show_plugin_prefs_cb), event_view); | 567 G_CALLBACK(show_plugin_prefs_cb), event_view); |
568 | |
569 gaim_signal_connect(gaim_plugins_get_handle(), "plugin-load", plugin_dialog, | |
570 GAIM_CALLBACK(plugin_load_cb), event_view); | |
571 gaim_signal_connect(gaim_plugins_get_handle(), "plugin-unload", plugin_dialog, | |
572 GAIM_CALLBACK(plugin_unload_cb), event_view); | |
448 | 573 |
449 rend = gtk_cell_renderer_toggle_new(); | 574 rend = gtk_cell_renderer_toggle_new(); |
450 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (event_view)); | 575 sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (event_view)); |
451 | 576 |
452 col = gtk_tree_view_column_new_with_attributes (_("Enabled"), | 577 col = gtk_tree_view_column_new_with_attributes (_("Enabled"), |
453 rend, | 578 rend, |
454 "active", 0, | 579 "active", 0, |
455 NULL); | 580 NULL); |
456 gtk_tree_view_append_column (GTK_TREE_VIEW(event_view), col); | 581 gtk_tree_view_append_column (GTK_TREE_VIEW(event_view), col); |
457 gtk_tree_view_column_set_sort_column_id(col, 0); | 582 gtk_tree_view_column_set_sort_column_id(col, 0); |
458 g_signal_connect (G_OBJECT(rend), "toggled", | 583 g_signal_connect(G_OBJECT(rend), "toggled", |
459 G_CALLBACK(plugin_load), ls); | 584 G_CALLBACK(plugin_toggled), ls); |
460 | 585 |
461 rendt = gtk_cell_renderer_text_new(); | 586 rendt = gtk_cell_renderer_text_new(); |
462 g_object_set(rendt, | 587 g_object_set(rendt, |
463 "foreground", "#c0c0c0", | 588 "foreground", "#c0c0c0", |
464 NULL); | 589 NULL); |