pidgin/gtkplugin.c

changeset 34479
7d4651f1035e
parent 34477
86f6c431da7b
child 34480
26e7a3057f0c
equal deleted inserted replaced
34478:be28ca093028 34479:7d4651f1035e
37 37
38 #include "gtk3compat.h" 38 #include "gtk3compat.h"
39 39
40 #define PIDGIN_RESPONSE_CONFIGURE 98121 40 #define PIDGIN_RESPONSE_CONFIGURE 98121
41 41
42 typedef struct
43 {
44 enum
45 {
46 PIDGIN_PLUGIN_UI_DATA_TYPE_FRAME,
47 PIDGIN_PLUGIN_UI_DATA_TYPE_REQUEST
48 } type;
49
50 union
51 {
52 struct
53 {
54 GtkWidget *dialog;
55 PurplePluginPrefFrame *pref_frame;
56 } frame;
57
58 gpointer request_handle;
59 } u;
60 } PidginPluginUiData;
61
42 static void plugin_toggled_stage_two(PurplePlugin *plug, GtkTreeModel *model, 62 static void plugin_toggled_stage_two(PurplePlugin *plug, GtkTreeModel *model,
43 GtkTreeIter *iter, gboolean unload); 63 GtkTreeIter *iter, gboolean unload);
44 64
45 static GtkWidget *expander = NULL; 65 static GtkWidget *expander = NULL;
46 static GtkWidget *plugin_dialog = NULL; 66 static GtkWidget *plugin_dialog = NULL;
52 static GtkLabel *plugin_website = NULL; 72 static GtkLabel *plugin_website = NULL;
53 static gchar *plugin_website_uri = NULL; 73 static gchar *plugin_website_uri = NULL;
54 static GtkLabel *plugin_filename = NULL; 74 static GtkLabel *plugin_filename = NULL;
55 75
56 static GtkWidget *pref_button = NULL; 76 static GtkWidget *pref_button = NULL;
57 static GHashTable *plugin_pref_dialogs = NULL; 77
58 78 static gboolean
59 GtkWidget * 79 pidgin_plugin_has_prefs(PurplePlugin *plugin)
60 pidgin_plugin_get_config_frame(PurplePlugin *plugin) 80 {
81 PurplePluginUiInfo *pinfo;
82
83 g_return_val_if_fail(plugin != NULL, FALSE);
84
85 if (!purple_plugin_is_loaded(plugin))
86 return FALSE;
87
88 if (PIDGIN_IS_PIDGIN_PLUGIN(plugin) && plugin->info->ui_info &&
89 PIDGIN_PLUGIN_UI_INFO(plugin)->get_config_frame)
90 {
91 return TRUE;
92 }
93
94 pinfo = plugin->info->prefs_info;
95
96 if (!pinfo)
97 return FALSE;
98
99 return (pinfo->get_plugin_pref_frame || pinfo->get_plugin_pref_request);
100 }
101
102 static GtkWidget *
103 pidgin_plugin_get_config_frame(PurplePlugin *plugin,
104 PurplePluginPrefFrame **purple_pref_frame)
61 { 105 {
62 GtkWidget *config = NULL; 106 GtkWidget *config = NULL;
63 107
64 g_return_val_if_fail(plugin != NULL, NULL); 108 g_return_val_if_fail(plugin != NULL, NULL);
65 109
69 PidginPluginUiInfo *ui_info; 113 PidginPluginUiInfo *ui_info;
70 114
71 ui_info = PIDGIN_PLUGIN_UI_INFO(plugin); 115 ui_info = PIDGIN_PLUGIN_UI_INFO(plugin);
72 116
73 config = ui_info->get_config_frame(plugin); 117 config = ui_info->get_config_frame(plugin);
74
75 if (plugin->info->prefs_info
76 && plugin->info->prefs_info->get_plugin_pref_frame)
77 {
78 purple_debug_warning("gtkplugin",
79 "Plugin %s contains both, ui_info and "
80 "prefs_info preferences; prefs_info will be "
81 "ignored.", plugin->info->name);
82 }
83 } 118 }
84 119
85 if (config == NULL && plugin->info->prefs_info 120 if (config == NULL && plugin->info->prefs_info
86 && plugin->info->prefs_info->get_plugin_pref_frame) 121 && plugin->info->prefs_info->get_plugin_pref_frame)
87 { 122 {
89 124
90 frame = plugin->info->prefs_info->get_plugin_pref_frame(plugin); 125 frame = plugin->info->prefs_info->get_plugin_pref_frame(plugin);
91 126
92 config = pidgin_plugin_pref_create_frame(frame); 127 config = pidgin_plugin_pref_create_frame(frame);
93 128
94 plugin->ui_data = frame; 129 *purple_pref_frame = frame;
95 } 130 }
96 131
97 return config; 132 return config;
133 }
134
135 static void
136 pref_dialog_close(PurplePlugin *plugin)
137 {
138 PidginPluginUiData *ui_data;
139
140 g_return_if_fail(plugin != NULL);
141
142 ui_data = plugin->ui_data;
143 if (ui_data == NULL)
144 return;
145
146 if (ui_data->type == PIDGIN_PLUGIN_UI_DATA_TYPE_REQUEST) {
147 purple_request_close(PURPLE_REQUEST_FIELDS,
148 ui_data->u.request_handle);
149 return;
150 }
151
152 g_return_if_fail(ui_data->type == PIDGIN_PLUGIN_UI_DATA_TYPE_FRAME);
153
154 gtk_widget_destroy(ui_data->u.frame.dialog);
155
156 if (ui_data->u.frame.pref_frame)
157 purple_plugin_pref_frame_destroy(ui_data->u.frame.pref_frame);
158
159 g_free(ui_data);
160 plugin->ui_data = NULL;
161 }
162
163
164 static void
165 pref_dialog_response_cb(GtkWidget *dialog, int response, PurplePlugin *plugin)
166 {
167 if (response == GTK_RESPONSE_CLOSE ||
168 response == GTK_RESPONSE_DELETE_EVENT)
169 {
170 pref_dialog_close(plugin);
171 }
172 }
173
174 static void
175 pidgin_plugin_open_config(PurplePlugin *plugin, GtkWindow *parent)
176 {
177 PurplePluginUiInfo *pinfo;
178 PidginPluginUiData *ui_data;
179 gboolean has_purple_frame, has_purple_request, has_pidgin_frame;
180 gint prefs_count;
181
182 g_return_if_fail(plugin != NULL);
183
184 if (!pidgin_plugin_has_prefs(plugin)) {
185 purple_debug_warning("gtkplugin", "Plugin has no prefs");
186 return;
187 }
188
189 if (plugin->ui_data != NULL)
190 return;
191
192 pinfo = plugin->info->prefs_info;
193 has_purple_frame = (pinfo->get_plugin_pref_frame != NULL);
194 has_purple_request = (pinfo->get_plugin_pref_request != NULL);
195 has_pidgin_frame = (PIDGIN_IS_PIDGIN_PLUGIN(plugin) &&
196 plugin->info->ui_info &&
197 PIDGIN_PLUGIN_UI_INFO(plugin)->get_config_frame);
198
199 prefs_count = 0;
200 if (has_purple_frame)
201 prefs_count++;
202 if (has_purple_request)
203 prefs_count++;
204 if (has_pidgin_frame)
205 prefs_count++;
206
207 if (prefs_count > 1) {
208 purple_debug_warning("gtkplugin", "Plugin %s contains more than"
209 " one prefs callback, some will be ignored.",
210 plugin->info->name);
211 }
212 g_return_if_fail(prefs_count > 0);
213
214 plugin->ui_data = ui_data = g_new0(PidginPluginUiData, 1);
215
216 /* Priority: pidgin frame > purple request > purple frame
217 * Purple frame could be replaced with purple request some day.
218 */
219 if (has_purple_request && !has_pidgin_frame) {
220 ui_data->type = PIDGIN_PLUGIN_UI_DATA_TYPE_REQUEST;
221 ui_data->u.request_handle =
222 pinfo->get_plugin_pref_request(plugin);
223 purple_request_add_close_notify(ui_data->u.request_handle,
224 purple_callback_set_zero, &plugin->ui_data);
225 purple_request_add_close_notify(ui_data->u.request_handle,
226 g_free, ui_data);
227 } else {
228 GtkWidget *box, *dialog;
229
230 ui_data->type = PIDGIN_PLUGIN_UI_DATA_TYPE_FRAME;
231
232 box = pidgin_plugin_get_config_frame(plugin,
233 &ui_data->u.frame.pref_frame);
234 if (box == NULL) {
235 purple_debug_error("gtkplugin",
236 "Failed to display prefs frame");
237 g_free(ui_data);
238 plugin->ui_data = NULL;
239 return;
240 }
241
242 ui_data->u.frame.dialog = dialog = gtk_dialog_new_with_buttons(
243 PIDGIN_ALERT_TITLE, parent,
244 GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_CLOSE,
245 GTK_RESPONSE_CLOSE, NULL);
246
247 g_signal_connect(G_OBJECT(dialog), "response",
248 G_CALLBACK(pref_dialog_response_cb), plugin);
249 gtk_container_add(GTK_CONTAINER(
250 gtk_dialog_get_content_area(GTK_DIALOG(dialog))), box);
251 gtk_window_set_role(GTK_WINDOW(dialog), "plugin_config");
252 gtk_window_set_title(GTK_WINDOW(dialog),
253 _(purple_plugin_get_name(plugin)));
254 gtk_widget_show_all(dialog);
255 }
98 } 256 }
99 257
100 void 258 void
101 pidgin_plugins_save(void) 259 pidgin_plugins_save(void)
102 { 260 {
188 { 346 {
189 gtk_tree_model_get(model, &iter, 2, &plug, -1); 347 gtk_tree_model_get(model, &iter, 2, &plug, -1);
190 if (plug == plugin) 348 if (plug == plugin)
191 { 349 {
192 gtk_widget_set_sensitive(pref_button, 350 gtk_widget_set_sensitive(pref_button,
193 loaded 351 pidgin_plugin_has_prefs(plug));
194 && ((PIDGIN_IS_PIDGIN_PLUGIN(plug) && plug->info->ui_info
195 && PIDGIN_PLUGIN_UI_INFO(plug)->get_config_frame)
196 || (plug->info->prefs_info
197 && plug->info->prefs_info->get_plugin_pref_frame)));
198 } 352 }
199 } 353 }
200 354
201 break; 355 break;
202 } while (gtk_tree_model_iter_next(model, &iter)); 356 } while (gtk_tree_model_iter_next(model, &iter));
211 365
212 static void plugin_unload_cb(PurplePlugin *plugin, gpointer data) 366 static void plugin_unload_cb(PurplePlugin *plugin, gpointer data)
213 { 367 {
214 GtkTreeView *view = (GtkTreeView *)data; 368 GtkTreeView *view = (GtkTreeView *)data;
215 plugin_loading_common(plugin, view, FALSE); 369 plugin_loading_common(plugin, view, FALSE);
216 }
217
218 static void pref_dialog_response_cb(GtkWidget *d, int response, PurplePlugin *plug)
219 {
220 switch (response) {
221 case GTK_RESPONSE_CLOSE:
222 case GTK_RESPONSE_DELETE_EVENT:
223 g_hash_table_remove(plugin_pref_dialogs, plug);
224 if (g_hash_table_size(plugin_pref_dialogs) == 0) {
225 g_hash_table_destroy(plugin_pref_dialogs);
226 plugin_pref_dialogs = NULL;
227 }
228 gtk_widget_destroy(d);
229
230 if (plug->info->prefs_info && plug->ui_data) {
231 purple_plugin_pref_frame_destroy(plug->ui_data);
232 plug->ui_data = NULL;
233 }
234
235 break;
236 }
237 } 370 }
238 371
239 static void plugin_unload_confirm_cb(gpointer *data) 372 static void plugin_unload_confirm_cb(gpointer *data)
240 { 373 {
241 PurplePlugin *plugin = (PurplePlugin *)data[0]; 374 PurplePlugin *plugin = (PurplePlugin *)data[0];
251 { 384 {
252 GtkTreeModel *model = (GtkTreeModel *)data; 385 GtkTreeModel *model = (GtkTreeModel *)data;
253 GtkTreeIter *iter = g_new(GtkTreeIter, 1); 386 GtkTreeIter *iter = g_new(GtkTreeIter, 1);
254 GtkTreePath *path = gtk_tree_path_new_from_string(pth); 387 GtkTreePath *path = gtk_tree_path_new_from_string(pth);
255 PurplePlugin *plug; 388 PurplePlugin *plug;
256 GtkWidget *dialog = NULL;
257 389
258 gtk_tree_model_get_iter(model, iter, path); 390 gtk_tree_model_get_iter(model, iter, path);
259 gtk_tree_path_free(path); 391 gtk_tree_path_free(path);
260 gtk_tree_model_get(model, iter, 2, &plug, -1); 392 gtk_tree_model_get(model, iter, 2, &plug, -1);
261 393
275 407
276 pidgin_clear_cursor(plugin_dialog); 408 pidgin_clear_cursor(plugin_dialog);
277 } 409 }
278 else 410 else
279 { 411 {
280 if (plugin_pref_dialogs != NULL && 412 pref_dialog_close(plug);
281 (dialog = g_hash_table_lookup(plugin_pref_dialogs, plug)))
282 pref_dialog_response_cb(dialog, GTK_RESPONSE_DELETE_EVENT, plug);
283 413
284 if (plug->dependent_plugins != NULL) 414 if (plug->dependent_plugins != NULL)
285 { 415 {
286 GString *tmp = g_string_new(_("The following plugins will be unloaded.")); 416 GString *tmp = g_string_new(_("The following plugins will be unloaded."));
287 GList *l; 417 GList *l;
340 } 470 }
341 471
342 pidgin_clear_cursor(plugin_dialog); 472 pidgin_clear_cursor(plugin_dialog);
343 } 473 }
344 474
345 gtk_widget_set_sensitive(pref_button, 475 gtk_widget_set_sensitive(pref_button, pidgin_plugin_has_prefs(plug));
346 purple_plugin_is_loaded(plug)
347 && ((PIDGIN_IS_PIDGIN_PLUGIN(plug) && plug->info->ui_info
348 && PIDGIN_PLUGIN_UI_INFO(plug)->get_config_frame)
349 || (plug->info->prefs_info
350 && plug->info->prefs_info->get_plugin_pref_frame)));
351 476
352 if (plug->error != NULL) 477 if (plug->error != NULL)
353 { 478 {
354 gchar *name = g_markup_escape_text(purple_plugin_get_name(plug), -1); 479 gchar *name = g_markup_escape_text(purple_plugin_get_name(plug), -1);
355 480
468 gtk_label_set_markup(plugin_error, buf); 593 gtk_label_set_markup(plugin_error, buf);
469 g_free(buf); 594 g_free(buf);
470 g_free(tmp); 595 g_free(tmp);
471 } 596 }
472 597
473 gtk_widget_set_sensitive(pref_button, 598 gtk_widget_set_sensitive(pref_button, pidgin_plugin_has_prefs(plug));
474 purple_plugin_is_loaded(plug)
475 && ((PIDGIN_IS_PIDGIN_PLUGIN(plug) && plug->info->ui_info
476 && PIDGIN_PLUGIN_UI_INFO(plug)->get_config_frame)
477 || (plug->info->prefs_info
478 && plug->info->prefs_info->get_plugin_pref_frame)));
479 599
480 /* Make sure the selected plugin is still visible */ 600 /* Make sure the selected plugin is still visible */
481 g_idle_add(ensure_plugin_visible, sel); 601 g_idle_add(ensure_plugin_visible, sel);
482 602
483 g_value_unset(&val); 603 g_value_unset(&val);
484 } 604 }
485 605
486 static void plugin_dialog_response_cb(GtkWidget *d, int response, GtkTreeSelection *sel) 606 static void plugin_dialog_response_cb(GtkWidget *d, int response, GtkTreeSelection *sel)
487 { 607 {
488 PurplePlugin *plug; 608 PurplePlugin *plugin;
489 GtkWidget *dialog, *box;
490 GtkTreeModel *model; 609 GtkTreeModel *model;
491 GValue val; 610 GValue val;
492 GtkTreeIter iter; 611 GtkTreeIter iter;
612 GList *it;
493 613
494 switch (response) { 614 switch (response) {
495 case GTK_RESPONSE_CLOSE: 615 case GTK_RESPONSE_CLOSE:
496 case GTK_RESPONSE_DELETE_EVENT: 616 case GTK_RESPONSE_DELETE_EVENT:
497 purple_request_close_with_handle(plugin_dialog); 617 purple_request_close_with_handle(plugin_dialog);
498 purple_signals_disconnect_by_handle(plugin_dialog); 618 purple_signals_disconnect_by_handle(plugin_dialog);
619 for (it = purple_plugins_get_all(); it; it = g_list_next(it))
620 pref_dialog_close(it->data);
499 gtk_widget_destroy(d); 621 gtk_widget_destroy(d);
500 if (plugin_pref_dialogs != NULL) {
501 g_hash_table_destroy(plugin_pref_dialogs);
502 plugin_pref_dialogs = NULL;
503 }
504 plugin_dialog = NULL; 622 plugin_dialog = NULL;
505 break; 623 break;
506 case PIDGIN_RESPONSE_CONFIGURE: 624 case PIDGIN_RESPONSE_CONFIGURE:
507 if (! gtk_tree_selection_get_selected (sel, &model, &iter)) 625 if (! gtk_tree_selection_get_selected (sel, &model, &iter))
508 return; 626 return;
509 val.g_type = 0; 627 val.g_type = 0;
510 gtk_tree_model_get_value(model, &iter, 2, &val); 628 gtk_tree_model_get_value(model, &iter, 2, &val);
511 plug = g_value_get_pointer(&val); 629 plugin = g_value_get_pointer(&val);
512 if (plug == NULL) 630 g_value_unset(&val);
631 if (plugin == NULL)
513 break; 632 break;
514 if (plugin_pref_dialogs != NULL && 633
515 g_hash_table_lookup(plugin_pref_dialogs, plug)) 634 pidgin_plugin_open_config(plugin, GTK_WINDOW(d));
516 break; 635
517 box = pidgin_plugin_get_config_frame(plug);
518 if (box == NULL)
519 break;
520
521 dialog = gtk_dialog_new_with_buttons(PIDGIN_ALERT_TITLE, GTK_WINDOW(d),
522 GTK_DIALOG_DESTROY_WITH_PARENT,
523 GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
524 NULL);
525 if (plugin_pref_dialogs == NULL)
526 plugin_pref_dialogs = g_hash_table_new(NULL, NULL);
527
528 g_hash_table_insert(plugin_pref_dialogs, plug, dialog);
529
530 g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK(pref_dialog_response_cb), plug);
531 gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), box);
532 gtk_window_set_role(GTK_WINDOW(dialog), "plugin_config");
533 gtk_window_set_title(GTK_WINDOW(dialog), _(purple_plugin_get_name(plug)));
534 gtk_widget_show_all(dialog);
535 g_value_unset(&val);
536 break; 636 break;
537 } 637 }
538 } 638 }
539 639
540 static void 640 static void

mercurial