| 33 #include "gtkpluginpref.h" |
33 #include "gtkpluginpref.h" |
| 34 #include "pidgincore.h" |
34 #include "pidgincore.h" |
| 35 |
35 |
| 36 struct _PidginPluginsDialog { |
36 struct _PidginPluginsDialog { |
| 37 GtkDialog parent; |
37 GtkDialog parent; |
| 38 |
|
| 39 GtkWidget *tree_view; |
|
| 40 GtkWidget *configure_plugin_button; |
|
| 41 GtkWidget *plugin_info; |
|
| 42 |
|
| 43 GtkListStore *plugin_store; |
|
| 44 }; |
38 }; |
| 45 |
|
| 46 /* this has a short life left to it... */ |
|
| 47 typedef struct |
|
| 48 { |
|
| 49 enum |
|
| 50 { |
|
| 51 PIDGIN_PLUGIN_UI_DATA_TYPE_FRAME, |
|
| 52 PIDGIN_PLUGIN_UI_DATA_TYPE_REQUEST |
|
| 53 } type; |
|
| 54 |
|
| 55 union |
|
| 56 { |
|
| 57 struct |
|
| 58 { |
|
| 59 GtkWidget *dialog; |
|
| 60 PurplePluginPrefFrame *pref_frame; |
|
| 61 } frame; |
|
| 62 |
|
| 63 gpointer request_handle; |
|
| 64 } u; |
|
| 65 } PidginPluginUiData; |
|
| 66 |
|
| 67 /****************************************************************************** |
|
| 68 * Helpers |
|
| 69 *****************************************************************************/ |
|
| 70 static gboolean |
|
| 71 pidgin_plugins_dialog_plugin_has_config(GPluginPlugin *plugin) { |
|
| 72 GPluginPluginInfo *ginfo = gplugin_plugin_get_info(plugin); |
|
| 73 PurplePluginInfo *info = PURPLE_PLUGIN_INFO(ginfo); |
|
| 74 GPluginPluginState state; |
|
| 75 |
|
| 76 g_return_val_if_fail(GPLUGIN_IS_PLUGIN(plugin), FALSE); |
|
| 77 |
|
| 78 state = gplugin_plugin_get_state(plugin); |
|
| 79 |
|
| 80 if (state != GPLUGIN_PLUGIN_STATE_LOADED) { |
|
| 81 return FALSE; |
|
| 82 } |
|
| 83 |
|
| 84 return (purple_plugin_info_get_pref_frame_cb(info) || |
|
| 85 purple_plugin_info_get_pref_request_cb(info)); |
|
| 86 } |
|
| 87 |
|
| 88 static GPluginPlugin * |
|
| 89 pidgin_plugins_dialog_get_selected(PidginPluginsDialog *dialog) { |
|
| 90 GPluginPlugin *plugin = NULL; |
|
| 91 GtkTreeSelection *selection = NULL; |
|
| 92 GtkTreeModel *model = NULL; |
|
| 93 GtkTreeIter iter; |
|
| 94 |
|
| 95 g_return_val_if_fail(PIDGIN_IS_PLUGINS_DIALOG(dialog), NULL); |
|
| 96 |
|
| 97 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(dialog->tree_view)); |
|
| 98 /* not sure if this is necessary, but playing defense. - grim 20191112 */ |
|
| 99 if(selection == NULL) { |
|
| 100 return NULL; |
|
| 101 } |
|
| 102 |
|
| 103 if(gtk_tree_selection_get_selected(selection, &model, &iter)) { |
|
| 104 gtk_tree_model_get(model, &iter, |
|
| 105 GPLUGIN_GTK_STORE_PLUGIN_COLUMN, &plugin, |
|
| 106 -1); |
|
| 107 } |
|
| 108 |
|
| 109 return plugin; |
|
| 110 } |
|
| 111 |
|
| 112 static void |
|
| 113 pidgin_plugins_dialog_pref_dialog_close(GPluginPlugin *plugin) { |
|
| 114 GPluginPluginInfo *ginfo = gplugin_plugin_get_info(plugin); |
|
| 115 PurplePluginInfo *info = PURPLE_PLUGIN_INFO(ginfo); |
|
| 116 PidginPluginUiData *ui_data; |
|
| 117 |
|
| 118 ui_data = g_object_get_data(G_OBJECT(info), "pidgin-ui-data"); |
|
| 119 if (ui_data == NULL) { |
|
| 120 purple_debug_info("PidginPluginsDialog", "failed to find uidata\n"); |
|
| 121 return; |
|
| 122 } |
|
| 123 |
|
| 124 if (ui_data->type == PIDGIN_PLUGIN_UI_DATA_TYPE_REQUEST) { |
|
| 125 purple_request_close(PURPLE_REQUEST_FIELDS, |
|
| 126 ui_data->u.request_handle); |
|
| 127 return; |
|
| 128 } |
|
| 129 |
|
| 130 g_return_if_fail(ui_data->type == PIDGIN_PLUGIN_UI_DATA_TYPE_FRAME); |
|
| 131 |
|
| 132 gtk_widget_destroy(ui_data->u.frame.dialog); |
|
| 133 |
|
| 134 if (ui_data->u.frame.pref_frame) { |
|
| 135 purple_plugin_pref_frame_destroy(ui_data->u.frame.pref_frame); |
|
| 136 } |
|
| 137 |
|
| 138 g_object_set_data(G_OBJECT(info), "pidgin-ui-data", NULL); |
|
| 139 } |
|
| 140 |
|
| 141 /****************************************************************************** |
|
| 142 * Callbacks |
|
| 143 *****************************************************************************/ |
|
| 144 static void |
|
| 145 pidgin_plugins_dialog_selection_cb(GtkTreeSelection *sel, gpointer data) { |
|
| 146 PidginPluginsDialog *dialog = PIDGIN_PLUGINS_DIALOG(data); |
|
| 147 GPluginPlugin *plugin = NULL; |
|
| 148 GtkTreeModel *model = NULL; |
|
| 149 GtkTreeIter iter; |
|
| 150 |
|
| 151 if(gtk_tree_selection_get_selected(sel, &model, &iter)) { |
|
| 152 gtk_tree_model_get(model, &iter, |
|
| 153 GPLUGIN_GTK_STORE_PLUGIN_COLUMN, &plugin, |
|
| 154 -1); |
|
| 155 } |
|
| 156 |
|
| 157 gplugin_gtk_plugin_info_set_plugin( |
|
| 158 GPLUGIN_GTK_PLUGIN_INFO(dialog->plugin_info), |
|
| 159 plugin |
|
| 160 ); |
|
| 161 |
|
| 162 if(GPLUGIN_IS_PLUGIN(plugin)) { |
|
| 163 gtk_widget_set_sensitive( |
|
| 164 GTK_WIDGET(dialog->configure_plugin_button), |
|
| 165 pidgin_plugins_dialog_plugin_has_config(plugin) |
|
| 166 ); |
|
| 167 |
|
| 168 g_object_unref(G_OBJECT(plugin)); |
|
| 169 } |
|
| 170 } |
|
| 171 |
|
| 172 static void |
|
| 173 pidgin_plugins_dialog_pref_dialog_response_cb(GtkWidget *dialog, int response, |
|
| 174 gpointer data) |
|
| 175 { |
|
| 176 if (response == GTK_RESPONSE_CLOSE || |
|
| 177 response == GTK_RESPONSE_DELETE_EVENT) |
|
| 178 { |
|
| 179 pidgin_plugins_dialog_pref_dialog_close(GPLUGIN_PLUGIN(data)); |
|
| 180 } |
|
| 181 } |
|
| 182 |
|
| 183 static void |
|
| 184 pidgin_plugins_dialog_request_close_cb(PurplePluginInfo *info) |
|
| 185 { |
|
| 186 g_object_set_data(G_OBJECT(info), "pidgin-ui-data", NULL); |
|
| 187 } |
|
| 188 |
|
| 189 static void |
|
| 190 pidgin_plugins_dialog_config_plugin_cb(GtkWidget *button, gpointer data) { |
|
| 191 PidginPluginsDialog *dialog = PIDGIN_PLUGINS_DIALOG(data); |
|
| 192 PidginPluginUiData *ui_data; |
|
| 193 PurplePluginInfo *info; |
|
| 194 PurplePluginPrefFrameCb pref_frame_cb; |
|
| 195 PurplePluginPrefRequestCb pref_request_cb; |
|
| 196 GPluginPlugin *plugin = NULL; |
|
| 197 GPluginPluginInfo *ginfo = NULL; |
|
| 198 gint prefs_count; |
|
| 199 |
|
| 200 plugin = pidgin_plugins_dialog_get_selected(dialog); |
|
| 201 if(!GPLUGIN_IS_PLUGIN(plugin)) { |
|
| 202 return; |
|
| 203 } |
|
| 204 |
|
| 205 ginfo = gplugin_plugin_get_info(plugin); |
|
| 206 info = PURPLE_PLUGIN_INFO(ginfo); |
|
| 207 |
|
| 208 if (g_object_get_data(G_OBJECT(info), "pidgin-ui-data")) { |
|
| 209 g_object_unref(G_OBJECT(plugin)); |
|
| 210 return; |
|
| 211 } |
|
| 212 |
|
| 213 pref_frame_cb = purple_plugin_info_get_pref_frame_cb(info); |
|
| 214 pref_request_cb = purple_plugin_info_get_pref_request_cb(info); |
|
| 215 |
|
| 216 ui_data = g_new0(PidginPluginUiData, 1); |
|
| 217 g_object_set_data_full(G_OBJECT(info), "pidgin-ui-data", ui_data, g_free); |
|
| 218 |
|
| 219 prefs_count = 0; |
|
| 220 if (pref_frame_cb) { |
|
| 221 prefs_count++; |
|
| 222 |
|
| 223 ui_data->u.frame.pref_frame = pref_frame_cb(plugin); |
|
| 224 } |
|
| 225 |
|
| 226 if (pref_request_cb) { |
|
| 227 prefs_count++; |
|
| 228 } |
|
| 229 |
|
| 230 if (prefs_count > 1) { |
|
| 231 purple_debug_warning("gtkplugin", |
|
| 232 "Plugin %s contains more than one prefs " |
|
| 233 "callback, some will be ignored.", |
|
| 234 gplugin_plugin_info_get_name(ginfo)); |
|
| 235 } |
|
| 236 g_return_if_fail(prefs_count > 0); |
|
| 237 |
|
| 238 |
|
| 239 /* Priority: pidgin frame > purple request > purple frame |
|
| 240 * Purple frame could be replaced with purple request some day. |
|
| 241 */ |
|
| 242 if (pref_request_cb) { |
|
| 243 ui_data->type = PIDGIN_PLUGIN_UI_DATA_TYPE_REQUEST; |
|
| 244 ui_data->u.request_handle = pref_request_cb(plugin); |
|
| 245 purple_request_add_close_notify( |
|
| 246 ui_data->u.request_handle, |
|
| 247 (GDestroyNotify)pidgin_plugins_dialog_request_close_cb, info); |
|
| 248 } else { |
|
| 249 GtkWidget *box, *pdialog, *content, *sw; |
|
| 250 |
|
| 251 ui_data->type = PIDGIN_PLUGIN_UI_DATA_TYPE_FRAME; |
|
| 252 |
|
| 253 box = pidgin_plugin_pref_create_frame(ui_data->u.frame.pref_frame); |
|
| 254 if (box == NULL) { |
|
| 255 purple_debug_error("gtkplugin", |
|
| 256 "Failed to display prefs frame"); |
|
| 257 g_object_set_data(G_OBJECT(info), "pidgin-ui-data", NULL); |
|
| 258 g_object_unref(G_OBJECT(plugin)); |
|
| 259 return; |
|
| 260 } |
|
| 261 gtk_widget_set_vexpand(box, TRUE); |
|
| 262 |
|
| 263 ui_data->u.frame.dialog = pdialog = gtk_dialog_new_with_buttons( |
|
| 264 PIDGIN_ALERT_TITLE, GTK_WINDOW(dialog), |
|
| 265 GTK_DIALOG_DESTROY_WITH_PARENT, |
|
| 266 _("Close"), GTK_RESPONSE_CLOSE, |
|
| 267 NULL); |
|
| 268 |
|
| 269 g_signal_connect(G_OBJECT(pdialog), "response", |
|
| 270 G_CALLBACK(pidgin_plugins_dialog_pref_dialog_response_cb), plugin); |
|
| 271 |
|
| 272 content = gtk_dialog_get_content_area(GTK_DIALOG(pdialog)); |
|
| 273 |
|
| 274 sw = gtk_scrolled_window_new(NULL, NULL); |
|
| 275 gtk_container_add(GTK_CONTAINER(content), sw); |
|
| 276 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), |
|
| 277 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); |
|
| 278 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw), |
|
| 279 GTK_SHADOW_IN); |
|
| 280 gtk_widget_set_size_request(sw, 400, 400); |
|
| 281 |
|
| 282 gtk_container_add(GTK_CONTAINER(sw), box); |
|
| 283 |
|
| 284 gtk_window_set_role(GTK_WINDOW(pdialog), "plugin_config"); |
|
| 285 gtk_window_set_title(GTK_WINDOW(pdialog), |
|
| 286 _(gplugin_plugin_info_get_name( |
|
| 287 GPLUGIN_PLUGIN_INFO(info)))); |
|
| 288 gtk_widget_show_all(pdialog); |
|
| 289 } |
|
| 290 g_object_unref(G_OBJECT(plugin)); |
|
| 291 } |
|
| 292 |
39 |
| 293 /****************************************************************************** |
40 /****************************************************************************** |
| 294 * GObject Implementation |
41 * GObject Implementation |
| 295 *****************************************************************************/ |
42 *****************************************************************************/ |
| 296 G_DEFINE_TYPE(PidginPluginsDialog, pidgin_plugins_dialog, GTK_TYPE_DIALOG); |
43 G_DEFINE_TYPE(PidginPluginsDialog, pidgin_plugins_dialog, GTK_TYPE_DIALOG); |