pidgin/pidginpluginsdialog.c

branch
gtk4
changeset 41538
48e7927980ec
parent 41030
ec8b76f3bf0a
child 41593
6928f02e807a
equal deleted inserted replaced
41537:9e61c1a7dcb1 41538:48e7927980ec
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);
301 48
302 gtk_widget_class_set_template_from_resource( 49 gtk_widget_class_set_template_from_resource(
303 widget_class, 50 widget_class,
304 "/im/pidgin/Pidgin3/Plugins/dialog.ui" 51 "/im/pidgin/Pidgin3/Plugins/dialog.ui"
305 ); 52 );
306
307 gtk_widget_class_bind_template_child(widget_class, PidginPluginsDialog, tree_view);
308 gtk_widget_class_bind_template_child(widget_class, PidginPluginsDialog, configure_plugin_button);
309 gtk_widget_class_bind_template_child(widget_class, PidginPluginsDialog, plugin_info);
310 gtk_widget_class_bind_template_child(widget_class, PidginPluginsDialog, plugin_store);
311
312 gtk_widget_class_bind_template_callback(widget_class, pidgin_plugins_dialog_selection_cb);
313 gtk_widget_class_bind_template_callback(widget_class, pidgin_plugins_dialog_config_plugin_cb);
314 } 53 }
315 54
316 static void 55 static void
317 pidgin_plugins_dialog_init(PidginPluginsDialog *dialog) { 56 pidgin_plugins_dialog_init(PidginPluginsDialog *dialog) {
318 gtk_widget_init_template(GTK_WIDGET(dialog)); 57 gtk_widget_init_template(GTK_WIDGET(dialog));
319
320 /* set the sort column for the plugin_store */
321 gtk_tree_sortable_set_sort_column_id(
322 GTK_TREE_SORTABLE(dialog->plugin_store),
323 GPLUGIN_GTK_STORE_MARKUP_COLUMN,
324 GTK_SORT_ASCENDING
325 );
326 } 58 }
327 59
328 /****************************************************************************** 60 /******************************************************************************
329 * Public API 61 * Public API
330 *****************************************************************************/ 62 *****************************************************************************/
331 GtkWidget * 63 GtkWidget *
332 pidgin_plugins_dialog_new(void) { 64 pidgin_plugins_dialog_new(void) {
333 return GTK_WIDGET(g_object_new(PIDGIN_TYPE_PLUGINS_DIALOG, NULL)); 65 return GTK_WIDGET(g_object_new(PIDGIN_TYPE_PLUGINS_DIALOG, NULL));
334 } 66 }
335

mercurial