Mercurial > pidgin
comparison src/plugins.c @ 1911:db3104dda736
[gaim-migrate @ 1921]
Mike Heffner's redesigned UI.
I changed around a lot of things from his patch, not because they weren't good or needed or anything like that; most of the changes I made just made the patch smaller. I moved functions back to where they originally where and renamed them back to what they originally were. Granted the names aren't as... good as the changes Mike made, but eh, it made my life a lot easier when I could see the meat of the changes without all the cosmetic details.
The only thing I really changed about his patch was I made the list BROWSE instead of SINGLE so that there wouldn't be need for a deselect callback. Oh yeah, and update_show_plugins is called from different places (so that plugins can call load_plugin and have the window update properly).
committer: Tailor Script <tailor@pidgin.im>
| author | Eric Warmenhoven <eric@warmenhoven.org> |
|---|---|
| date | Tue, 29 May 2001 09:46:05 +0000 |
| parents | 1e33bd2d7780 |
| children | 5028a07250c7 |
comparison
equal
deleted
inserted
replaced
| 1910:1cfc79c126fe | 1911:db3104dda736 |
|---|---|
| 48 | 48 |
| 49 #ifdef GAIM_PLUGINS | 49 #ifdef GAIM_PLUGINS |
| 50 | 50 |
| 51 #include <dlfcn.h> | 51 #include <dlfcn.h> |
| 52 | 52 |
| 53 #include "pixmaps/gnome_add.xpm" | |
| 54 #include "pixmaps/gnome_remove.xpm" | |
| 55 #include "pixmaps/gnome_preferences.xpm" | |
| 56 #include "pixmaps/refresh.xpm" | |
| 57 #include "pixmaps/cancel.xpm" | |
| 58 | |
| 59 #define PATHSIZE 1024 /* XXX: stolen from dialogs.c */ | |
| 60 | |
| 61 | |
| 53 /* ------------------ Global Variables ----------------------- */ | 62 /* ------------------ Global Variables ----------------------- */ |
| 54 | 63 |
| 55 GList *plugins = NULL; | 64 GList *plugins = NULL; |
| 56 GList *callbacks = NULL; | 65 GList *callbacks = NULL; |
| 57 | 66 |
| 58 /* ------------------ Local Variables ------------------------ */ | 67 /* ------------------ Local Variables ------------------------ */ |
| 59 | 68 |
| 60 static GtkWidget *plugin_dialog = NULL; | 69 static GtkWidget *plugin_dialog = NULL; |
| 61 | 70 |
| 62 static GtkWidget *pluglist; | 71 static GtkWidget *pluglist = NULL; |
| 63 static GtkWidget *plugtext; | 72 static GtkWidget *plugtext = NULL; |
| 64 static GtkWidget *plugwindow; | 73 static GtkWidget *plugwindow = NULL; |
| 74 static GtkWidget *plugentry = NULL; | |
| 75 | |
| 76 static GtkTooltips *tooltips = NULL; | |
| 65 | 77 |
| 66 static GtkWidget *config = NULL; | 78 static GtkWidget *config = NULL; |
| 67 static guint confighandle = 0; | 79 static guint confighandle = 0; |
| 68 static char *last_dir = NULL; | 80 static char *last_dir = NULL; |
| 69 | 81 |
| 73 void load_plugin(char *); | 85 void load_plugin(char *); |
| 74 | 86 |
| 75 void gaim_signal_connect(GModule *, enum gaim_event, void *, void *); | 87 void gaim_signal_connect(GModule *, enum gaim_event, void *, void *); |
| 76 void gaim_signal_disconnect(GModule *, enum gaim_event, void *); | 88 void gaim_signal_disconnect(GModule *, enum gaim_event, void *); |
| 77 void gaim_plugin_unload(GModule *); | 89 void gaim_plugin_unload(GModule *); |
| 90 | |
| 91 /* UI button callbacks */ | |
| 92 static void plugin_reload_cb(GtkWidget *, gpointer); | |
| 93 | |
| 94 static const gchar *plugin_makelistname(GModule *); | |
| 95 static void plugin_remove_callbacks(GModule *); | |
| 96 | |
| 97 static void plugin_reload(struct gaim_plugin *p); | |
| 78 | 98 |
| 79 static void destroy_plugins(GtkWidget *, gpointer); | 99 static void destroy_plugins(GtkWidget *, gpointer); |
| 80 static void load_file(GtkWidget *, gpointer); | 100 static void load_file(GtkWidget *, gpointer); |
| 81 static void load_which_plugin(GtkWidget *, gpointer); | 101 static void load_which_plugin(GtkWidget *, gpointer); |
| 82 static void unload(GtkWidget *, gpointer); | 102 static void unload(GtkWidget *, gpointer); |
| 161 return; | 181 return; |
| 162 | 182 |
| 163 while (filename && c) { | 183 while (filename && c) { |
| 164 plug = (struct gaim_plugin *)c->data; | 184 plug = (struct gaim_plugin *)c->data; |
| 165 if (!strcmp(filename, g_module_name(plug->handle))) { | 185 if (!strcmp(filename, g_module_name(plug->handle))) { |
| 166 void (*gaim_plugin_remove)(); | 186 /* just need to reload plugin */ |
| 167 if (g_module_symbol(plug->handle, "gaim_plugin_remove", | 187 plugin_reload(plug); |
| 168 (gpointer *)&gaim_plugin_remove)) | 188 return; |
| 169 (*gaim_plugin_remove)(); | |
| 170 | |
| 171 unload_immediate(plug->handle); | |
| 172 c = plugins; | |
| 173 } else | 189 } else |
| 174 c = g_list_next(c); | 190 c = g_list_next(c); |
| 175 } | 191 } |
| 176 plug = g_malloc(sizeof *plug); | 192 plug = g_malloc(sizeof *plug); |
| 177 | 193 |
| 196 g_free(plug); | 212 g_free(plug); |
| 197 return; | 213 return; |
| 198 } | 214 } |
| 199 | 215 |
| 200 retval = (*gaim_plugin_init)(plug->handle); | 216 retval = (*gaim_plugin_init)(plug->handle); |
| 201 debug_printf("loaded plugin returned %d\n", retval); | 217 debug_printf("loaded plugin returned %s\n", retval ? retval : "NULL"); |
| 202 if (retval) { | 218 if (retval) { |
| 203 GList *c = callbacks; | 219 plugin_remove_callbacks(plug->handle); |
| 204 struct gaim_callback *g; | |
| 205 while (c) { | |
| 206 g = (struct gaim_callback *)c->data; | |
| 207 if (g->handle == plug->handle) { | |
| 208 callbacks = g_list_remove(callbacks, c->data); | |
| 209 debug_printf("Removing callback, %d remain\n", g_list_length(callbacks)); | |
| 210 c = callbacks; | |
| 211 if (c == NULL) { | |
| 212 break; | |
| 213 } | |
| 214 } else { | |
| 215 c = g_list_next(c); | |
| 216 } | |
| 217 } | |
| 218 do_error_dialog(retval, _("Plugin Error")); | 220 do_error_dialog(retval, _("Plugin Error")); |
| 219 g_module_close(plug->handle); | 221 g_module_close(plug->handle); |
| 220 g_free(plug); | 222 g_free(plug); |
| 221 return; | 223 return; |
| 222 } | 224 } |
| 247 return NULL; | 249 return NULL; |
| 248 } | 250 } |
| 249 | 251 |
| 250 void show_plugins(GtkWidget *w, gpointer data) | 252 void show_plugins(GtkWidget *w, gpointer data) |
| 251 { | 253 { |
| 252 /* most of this code was shamelessly stolen from prefs.c */ | 254 /* most of this code was shamelessly stolen from Glade */ |
| 253 GtkWidget *page; | 255 GtkWidget *mainvbox; |
| 254 GtkWidget *topbox; | 256 GtkWidget *tophbox; |
| 255 GtkWidget *botbox; | 257 GtkWidget *bothbox; |
| 256 GtkWidget *sw; | 258 GtkWidget *hbox; |
| 259 GtkWidget *vbox; | |
| 260 GtkWidget *frame; | |
| 261 GtkWidget *scrolledwindow; | |
| 257 GtkWidget *label; | 262 GtkWidget *label; |
| 258 GtkWidget *list_item; | |
| 259 GtkWidget *sw2; | |
| 260 GtkWidget *add; | 263 GtkWidget *add; |
| 264 GtkWidget *reload; | |
| 261 GtkWidget *remove; | 265 GtkWidget *remove; |
| 262 GtkWidget *close; | 266 GtkWidget *close; |
| 263 GList *plugs = plugins; | |
| 264 struct gaim_plugin *p; | |
| 265 | 267 |
| 266 if (plugwindow) | 268 if (plugwindow) |
| 267 return; | 269 return; |
| 268 | 270 |
| 269 plugwindow = gtk_window_new(GTK_WINDOW_DIALOG); | 271 plugwindow = gtk_window_new(GTK_WINDOW_DIALOG); |
| 270 gtk_window_set_wmclass(GTK_WINDOW(plugwindow), "plugins", "Gaim"); | 272 gtk_window_set_wmclass(GTK_WINDOW(plugwindow), "plugins", "Gaim"); |
| 271 gtk_widget_realize(plugwindow); | 273 gtk_widget_realize(plugwindow); |
| 272 aol_icon(plugwindow->window); | 274 aol_icon(plugwindow->window); |
| 273 gtk_container_border_width(GTK_CONTAINER(plugwindow), 5); | |
| 274 gtk_window_set_title(GTK_WINDOW(plugwindow), _("Gaim - Plugins")); | 275 gtk_window_set_title(GTK_WINDOW(plugwindow), _("Gaim - Plugins")); |
| 275 gtk_widget_set_usize(plugwindow, 400, 250); | 276 gtk_widget_set_usize(plugwindow, 515, 300); |
| 276 gtk_signal_connect(GTK_OBJECT(plugwindow), "destroy", GTK_SIGNAL_FUNC(hide_plugins), NULL); | 277 gtk_signal_connect(GTK_OBJECT(plugwindow), "destroy", GTK_SIGNAL_FUNC(hide_plugins), NULL); |
| 277 | 278 |
| 278 page = gtk_vbox_new(FALSE, 5); | 279 mainvbox = gtk_vbox_new(FALSE, 0); |
| 279 topbox = gtk_hbox_new(FALSE, 5); | 280 gtk_container_add(GTK_CONTAINER(plugwindow), mainvbox); |
| 280 botbox = gtk_hbox_new(FALSE, 5); | 281 gtk_widget_show(mainvbox); |
| 281 | 282 |
| 282 /* Left side: list of plugin file names */ | 283 /* Build the top */ |
| 283 sw2 = gtk_scrolled_window_new(NULL, NULL); | 284 tophbox = gtk_hbox_new(FALSE, 0); |
| 284 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw2), | 285 gtk_box_pack_start(GTK_BOX(mainvbox), tophbox, TRUE, TRUE, 0); |
| 285 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); | 286 gtk_widget_show(tophbox); |
| 287 | |
| 288 /* Left side: frame with list of plugin file names */ | |
| 289 frame = gtk_frame_new(_("Plugins")); | |
| 290 gtk_box_pack_start(GTK_BOX(tophbox), frame, FALSE, FALSE, 0); | |
| 291 gtk_widget_set_usize(frame, 140, -1); | |
| 292 gtk_container_set_border_width(GTK_CONTAINER(frame), 6); | |
| 293 gtk_frame_set_label_align(GTK_FRAME(frame), 0.05, 0.5); | |
| 294 gtk_widget_show(frame); | |
| 295 | |
| 296 scrolledwindow = gtk_scrolled_window_new(NULL, NULL); | |
| 297 gtk_container_add(GTK_CONTAINER(frame), scrolledwindow); | |
| 298 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledwindow), | |
| 299 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); | |
| 300 gtk_widget_show(scrolledwindow); | |
| 286 | 301 |
| 287 pluglist = gtk_list_new(); | 302 pluglist = gtk_list_new(); |
| 288 gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(sw2), pluglist); | 303 gtk_list_set_selection_mode(GTK_LIST(pluglist), GTK_SELECTION_BROWSE); |
| 289 gtk_box_pack_start(GTK_BOX(topbox), sw2, TRUE, TRUE, 0); | 304 gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolledwindow), pluglist); |
| 290 | 305 gtk_widget_show(pluglist); |
| 291 /* Right side: the text description of the plugin */ | 306 |
| 292 sw = gtk_scrolled_window_new(NULL, NULL); | 307 /* Right side: frame with description and the filepath of plugin */ |
| 293 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), | 308 frame = gtk_frame_new(_("Description")); |
| 294 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); | 309 gtk_box_pack_start(GTK_BOX(tophbox), frame, TRUE, TRUE, 0); |
| 310 gtk_container_set_border_width(GTK_CONTAINER(frame), 6); | |
| 311 gtk_frame_set_label_align(GTK_FRAME(frame), 0.05, 0.5); | |
| 312 gtk_widget_show(frame); | |
| 313 | |
| 314 vbox = gtk_vbox_new(FALSE, 0); | |
| 315 gtk_container_add(GTK_CONTAINER(frame), vbox); | |
| 316 gtk_widget_show(vbox); | |
| 317 | |
| 318 scrolledwindow = gtk_scrolled_window_new(NULL, NULL); | |
| 319 gtk_box_pack_start(GTK_BOX(vbox), scrolledwindow, TRUE, TRUE, 0); | |
| 320 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledwindow), | |
| 321 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); | |
| 322 gtk_widget_show(scrolledwindow); | |
| 295 | 323 |
| 296 plugtext = gtk_text_new(NULL, NULL); | 324 plugtext = gtk_text_new(NULL, NULL); |
| 297 gtk_container_add(GTK_CONTAINER(sw), plugtext); | 325 gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolledwindow), plugtext); |
| 298 gtk_box_pack_start(GTK_BOX(topbox), sw, TRUE, TRUE, 0); | |
| 299 gtk_text_set_word_wrap(GTK_TEXT(plugtext), TRUE); | 326 gtk_text_set_word_wrap(GTK_TEXT(plugtext), TRUE); |
| 300 gtk_text_set_editable(GTK_TEXT(plugtext), FALSE); | 327 gtk_text_set_editable(GTK_TEXT(plugtext), FALSE); |
| 328 gtk_widget_show(plugtext); | |
| 329 | |
| 330 hbox = gtk_hbox_new(FALSE, 5); | |
| 331 gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); | |
| 332 gtk_container_set_border_width(GTK_CONTAINER(hbox), 6); | |
| 333 gtk_widget_show(hbox); | |
| 334 | |
| 335 label = gtk_label_new(_("Filepath:")); | |
| 336 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); | |
| 337 gtk_widget_show(label); | |
| 338 | |
| 339 plugentry = gtk_entry_new(); | |
| 340 gtk_box_pack_start(GTK_BOX(hbox), plugentry, TRUE, TRUE, 0); | |
| 341 gtk_entry_set_editable(GTK_ENTRY(plugentry), FALSE); | |
| 342 gtk_widget_show(plugentry); | |
| 301 | 343 |
| 302 /* Build the bottom button bar */ | 344 /* Build the bottom button bar */ |
| 303 add = gtk_button_new_with_label(_("Load Plugin")); | 345 bothbox = gtk_hbox_new(TRUE, 10); |
| 346 gtk_box_pack_start(GTK_BOX(mainvbox), bothbox, FALSE, FALSE, 0); | |
| 347 gtk_container_set_border_width(GTK_CONTAINER(hbox), 5); | |
| 348 gtk_widget_show(bothbox); | |
| 349 | |
| 350 if (!tooltips) | |
| 351 tooltips = gtk_tooltips_new(); | |
| 352 | |
| 353 add = picture_button(plugwindow, _("Load"), gnome_add_xpm); | |
| 304 gtk_signal_connect(GTK_OBJECT(add), "clicked", GTK_SIGNAL_FUNC(load_file), NULL); | 354 gtk_signal_connect(GTK_OBJECT(add), "clicked", GTK_SIGNAL_FUNC(load_file), NULL); |
| 305 gtk_box_pack_start(GTK_BOX(botbox), add, TRUE, TRUE, 0); | 355 gtk_box_pack_start(GTK_BOX(bothbox), add, TRUE, TRUE, 0); |
| 306 if (display_options & OPT_DISP_COOL_LOOK) | 356 gtk_tooltips_set_tip(tooltips, add, _("Load a plugin from a file"), ""); |
| 307 gtk_button_set_relief(GTK_BUTTON(add), GTK_RELIEF_NONE); | 357 |
| 308 | 358 config = picture_button(plugwindow, _("Configure"), gnome_preferences_xpm); |
| 309 config = gtk_button_new_with_label(_("Configure Plugin")); | 359 gtk_widget_set_sensitive(config, FALSE); |
| 310 gtk_widget_set_sensitive(config, 0); | 360 gtk_box_pack_start(GTK_BOX(bothbox), config, TRUE, TRUE, 0); |
| 311 gtk_box_pack_start(GTK_BOX(botbox), config, TRUE, TRUE, 0); | 361 gtk_tooltips_set_tip(tooltips, config, _("Configure settings of the selected plugin"), ""); |
| 312 if (display_options & OPT_DISP_COOL_LOOK) | 362 |
| 313 gtk_button_set_relief(GTK_BUTTON(config), GTK_RELIEF_NONE); | 363 reload = picture_button(plugwindow, _("Reload"), refresh_xpm); |
| 314 | 364 gtk_signal_connect(GTK_OBJECT(reload), "clicked", GTK_SIGNAL_FUNC(plugin_reload_cb), NULL); |
| 315 remove = gtk_button_new_with_label(_("Unload Plugin")); | 365 gtk_box_pack_start(GTK_BOX(bothbox), reload, TRUE, TRUE, 0); |
| 366 gtk_tooltips_set_tip(tooltips, reload, _("Reload the selected plugin"), ""); | |
| 367 | |
| 368 remove = picture_button(plugwindow, _("Unload"), gnome_remove_xpm); | |
| 316 gtk_signal_connect(GTK_OBJECT(remove), "clicked", GTK_SIGNAL_FUNC(unload), pluglist); | 369 gtk_signal_connect(GTK_OBJECT(remove), "clicked", GTK_SIGNAL_FUNC(unload), pluglist); |
| 317 gtk_box_pack_start(GTK_BOX(botbox), remove, TRUE, TRUE, 0); | 370 gtk_box_pack_start(GTK_BOX(bothbox), remove, TRUE, TRUE, 0); |
| 318 if (display_options & OPT_DISP_COOL_LOOK) | 371 gtk_tooltips_set_tip(tooltips, remove, _("Unload the selected plugin"), ""); |
| 319 gtk_button_set_relief(GTK_BUTTON(remove), GTK_RELIEF_NONE); | 372 |
| 320 | 373 close = picture_button(plugwindow, _("Close"), cancel_xpm); |
| 321 close = gtk_button_new_with_label(_("Close")); | |
| 322 gtk_signal_connect(GTK_OBJECT(close), "clicked", GTK_SIGNAL_FUNC(hide_plugins), NULL); | 374 gtk_signal_connect(GTK_OBJECT(close), "clicked", GTK_SIGNAL_FUNC(hide_plugins), NULL); |
| 323 gtk_box_pack_start(GTK_BOX(botbox), close, TRUE, TRUE, 0); | 375 gtk_box_pack_start(GTK_BOX(bothbox), close, TRUE, TRUE, 0); |
| 324 if (display_options & OPT_DISP_COOL_LOOK) | 376 gtk_tooltips_set_tip(tooltips, close, _("Close this window"), ""); |
| 325 gtk_button_set_relief(GTK_BUTTON(close), GTK_RELIEF_NONE); | 377 |
| 326 | 378 update_show_plugins(); |
| 327 gtk_box_pack_start(GTK_BOX(page), topbox, TRUE, TRUE, 0); | |
| 328 gtk_box_pack_start(GTK_BOX(page), botbox, FALSE, FALSE, 0); | |
| 329 | |
| 330 while (plugs) { | |
| 331 p = (struct gaim_plugin *)plugs->data; | |
| 332 label = gtk_label_new(g_module_name(p->handle)); | |
| 333 list_item = gtk_list_item_new(); | |
| 334 gtk_container_add(GTK_CONTAINER(list_item), label); | |
| 335 gtk_signal_connect(GTK_OBJECT(list_item), "select", GTK_SIGNAL_FUNC(list_clicked), p); | |
| 336 gtk_object_set_user_data(GTK_OBJECT(list_item), p); | |
| 337 | |
| 338 gtk_widget_show(label); | |
| 339 gtk_container_add(GTK_CONTAINER(pluglist), list_item); | |
| 340 gtk_widget_show(list_item); | |
| 341 | |
| 342 plugs = g_list_next(plugs); | |
| 343 } | |
| 344 | |
| 345 /* Make the first item selected */ | |
| 346 if (plugins != NULL) | |
| 347 gtk_list_select_item(GTK_LIST(pluglist), 0); | |
| 348 | |
| 349 gtk_widget_show(page); | |
| 350 gtk_widget_show(topbox); | |
| 351 gtk_widget_show(botbox); | |
| 352 gtk_widget_show(sw); | |
| 353 gtk_widget_show(sw2); | |
| 354 gtk_widget_show(pluglist); | |
| 355 gtk_widget_show(plugtext); | |
| 356 gtk_widget_show(add); | |
| 357 gtk_widget_show(config); | |
| 358 gtk_widget_show(remove); | |
| 359 gtk_widget_show(close); | |
| 360 | |
| 361 gtk_container_add(GTK_CONTAINER(plugwindow), page); | |
| 362 gtk_widget_show(plugwindow); | 379 gtk_widget_show(plugwindow); |
| 363 } | 380 } |
| 364 | 381 |
| 365 void update_show_plugins() | 382 void update_show_plugins() |
| 366 { | 383 { |
| 367 GList *plugs = plugins; | 384 GList *plugs = plugins; |
| 368 struct gaim_plugin *p; | 385 struct gaim_plugin *p; |
| 369 GtkWidget *label; | 386 GtkWidget *label; |
| 370 GtkWidget *list_item; | 387 GtkWidget *list_item; |
| 388 GtkWidget *hbox; | |
| 371 | 389 |
| 372 if (plugwindow == NULL) | 390 if (plugwindow == NULL) |
| 373 return; | 391 return; |
| 374 | 392 |
| 375 gtk_list_clear_items(GTK_LIST(pluglist), 0, -1); | 393 gtk_list_clear_items(GTK_LIST(pluglist), 0, -1); |
| 376 while (plugs) { | 394 while (plugs) { |
| 377 p = (struct gaim_plugin *)plugs->data; | 395 p = (struct gaim_plugin *)plugs->data; |
| 378 label = gtk_label_new(g_module_name(p->handle)); | 396 label = gtk_label_new(plugin_makelistname(p->handle)); |
| 397 hbox = gtk_hbox_new(FALSE, 0); /* for left justification */ | |
| 398 gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); | |
| 399 | |
| 379 list_item = gtk_list_item_new(); | 400 list_item = gtk_list_item_new(); |
| 380 gtk_container_add(GTK_CONTAINER(list_item), label); | 401 gtk_container_add(GTK_CONTAINER(list_item), hbox); |
| 381 gtk_signal_connect(GTK_OBJECT(list_item), "select", GTK_SIGNAL_FUNC(list_clicked), p); | 402 gtk_signal_connect(GTK_OBJECT(list_item), "select", GTK_SIGNAL_FUNC(list_clicked), p); |
| 382 gtk_object_set_user_data(GTK_OBJECT(list_item), p); | 403 gtk_object_set_user_data(GTK_OBJECT(list_item), p); |
| 383 | 404 |
| 405 gtk_widget_show(hbox); | |
| 384 gtk_widget_show(label); | 406 gtk_widget_show(label); |
| 385 gtk_container_add(GTK_CONTAINER(pluglist), list_item); | 407 gtk_container_add(GTK_CONTAINER(pluglist), list_item); |
| 386 gtk_widget_show(list_item); | 408 gtk_widget_show(list_item); |
| 409 | |
| 387 plugs = g_list_next(plugs); | 410 plugs = g_list_next(plugs); |
| 388 } | |
| 389 if (plugins != NULL) | |
| 390 gtk_list_select_item(GTK_LIST(pluglist), 0); | |
| 391 else { | |
| 392 gtk_text_set_point(GTK_TEXT(plugtext), 0); | |
| 393 gtk_text_forward_delete(GTK_TEXT(plugtext), gtk_text_get_length(GTK_TEXT(plugtext))); | |
| 394 } | 411 } |
| 395 } | 412 } |
| 396 | 413 |
| 397 void unload(GtkWidget *w, gpointer data) | 414 void unload(GtkWidget *w, gpointer data) |
| 398 { | 415 { |
| 410 /* Attempt to call the plugin's remove function (if there) */ | 427 /* Attempt to call the plugin's remove function (if there) */ |
| 411 if (g_module_symbol(p->handle, "gaim_plugin_remove", (gpointer *)&gaim_plugin_remove)) | 428 if (g_module_symbol(p->handle, "gaim_plugin_remove", (gpointer *)&gaim_plugin_remove)) |
| 412 (*gaim_plugin_remove)(); | 429 (*gaim_plugin_remove)(); |
| 413 | 430 |
| 414 unload_immediate(p->handle); | 431 unload_immediate(p->handle); |
| 432 update_show_plugins(); | |
| 415 } | 433 } |
| 416 | 434 |
| 417 static void unload_for_real(void *handle) | 435 static void unload_for_real(void *handle) |
| 418 { | 436 { |
| 419 GList *i; | 437 GList *i; |
| 420 struct gaim_plugin *p = NULL; | 438 struct gaim_plugin *p = NULL; |
| 421 GList *c = callbacks; | |
| 422 struct gaim_callback *g; | |
| 423 | 439 |
| 424 i = plugins; | 440 i = plugins; |
| 425 while (i) { | 441 while (i) { |
| 426 p = (struct gaim_plugin *)i->data; | 442 p = (struct gaim_plugin *)i->data; |
| 427 if (handle == p->handle) | 443 if (handle == p->handle) |
| 433 if (!p) | 449 if (!p) |
| 434 return; | 450 return; |
| 435 | 451 |
| 436 debug_printf("Unloading %s\n", g_module_name(p->handle)); | 452 debug_printf("Unloading %s\n", g_module_name(p->handle)); |
| 437 | 453 |
| 438 debug_printf("%d callbacks to search\n", g_list_length(callbacks)); | 454 plugin_remove_callbacks(p->handle); |
| 439 | |
| 440 while (c) { | |
| 441 g = (struct gaim_callback *)c->data; | |
| 442 if (g->handle == p->handle) { | |
| 443 callbacks = g_list_remove(callbacks, c->data); | |
| 444 g_free(g); | |
| 445 debug_printf("Removing callback, %d remain\n", g_list_length(callbacks)); | |
| 446 c = callbacks; | |
| 447 if (c == NULL) { | |
| 448 break; | |
| 449 } | |
| 450 } else { | |
| 451 c = g_list_next(c); | |
| 452 } | |
| 453 } | |
| 454 | 455 |
| 455 plugins = g_list_remove(plugins, p); | 456 plugins = g_list_remove(plugins, p); |
| 456 g_free(p); | 457 g_free(p); |
| 457 if (config) | |
| 458 gtk_widget_set_sensitive(config, 0); | |
| 459 update_show_plugins(); | 458 update_show_plugins(); |
| 460 save_prefs(); | 459 save_prefs(); |
| 461 } | 460 } |
| 462 | 461 |
| 463 void unload_immediate(GModule *handle) | 462 void unload_immediate(GModule *handle) |
| 474 | 473 |
| 475 void gaim_plugin_unload(GModule *handle) | 474 void gaim_plugin_unload(GModule *handle) |
| 476 { | 475 { |
| 477 unload_for_real(handle); | 476 unload_for_real(handle); |
| 478 gtk_timeout_add(5000, (GtkFunction)unload_timeout, handle); | 477 gtk_timeout_add(5000, (GtkFunction)unload_timeout, handle); |
| 478 } | |
| 479 | |
| 480 static void plugin_reload_cb(GtkWidget *w, gpointer data) | |
| 481 { | |
| 482 GList *i; | |
| 483 | |
| 484 i = GTK_LIST(pluglist)->selection; | |
| 485 if (i == NULL) | |
| 486 return; | |
| 487 | |
| 488 /* Just pass off plugin to the actual function */ | |
| 489 plugin_reload(gtk_object_get_user_data(GTK_OBJECT(i->data))); | |
| 490 } | |
| 491 | |
| 492 /* Do unload/load cycle of plugin. */ | |
| 493 static void plugin_reload(struct gaim_plugin *p) | |
| 494 { | |
| 495 char file[PATHSIZE]; | |
| 496 void (*gaim_plugin_remove)(); | |
| 497 GModule *handle = p->handle; | |
| 498 struct gaim_plugin *plug; | |
| 499 GList *plugs; | |
| 500 | |
| 501 strncpy(file, g_module_name(handle), sizeof(file)); | |
| 502 file[sizeof(file) - 1] = '\0'; | |
| 503 | |
| 504 debug_printf("Reloading %s\n", file); | |
| 505 | |
| 506 /* Unload */ | |
| 507 if (g_module_symbol(handle, "gaim_plugin_remove", (gpointer *)&gaim_plugin_remove)) | |
| 508 (*gaim_plugin_remove)(); | |
| 509 unload_immediate(handle); | |
| 510 | |
| 511 /* Load */ | |
| 512 load_plugin(file); | |
| 513 | |
| 514 /* Try and reselect the plugin in list */ | |
| 515 plugs = plugins; | |
| 516 while (plugs) { | |
| 517 plug = plugs->data; | |
| 518 if (!strcmp(file, g_module_name(plug->handle))) { | |
| 519 gtk_list_select_item(GTK_LIST(pluglist), g_list_index(plugins, plug)); | |
| 520 return; | |
| 521 } | |
| 522 plugs = plugs->next; | |
| 523 } | |
| 479 } | 524 } |
| 480 | 525 |
| 481 void list_clicked(GtkWidget *w, struct gaim_plugin *p) | 526 void list_clicked(GtkWidget *w, struct gaim_plugin *p) |
| 482 { | 527 { |
| 483 gchar *temp; | 528 gchar *temp; |
| 484 guint text_len; | 529 guint text_len; |
| 485 void (*gaim_plugin_config)(); | 530 void (*gaim_plugin_config)(); |
| 486 | 531 |
| 487 if (confighandle != 0) | 532 if (confighandle != 0) |
| 488 gtk_signal_disconnect(GTK_OBJECT(config), confighandle); | 533 gtk_signal_disconnect(GTK_OBJECT(config), confighandle); |
| 534 | |
| 489 text_len = gtk_text_get_length(GTK_TEXT(plugtext)); | 535 text_len = gtk_text_get_length(GTK_TEXT(plugtext)); |
| 490 gtk_text_set_point(GTK_TEXT(plugtext), 0); | 536 gtk_text_set_point(GTK_TEXT(plugtext), 0); |
| 491 gtk_text_forward_delete(GTK_TEXT(plugtext), text_len); | 537 gtk_text_forward_delete(GTK_TEXT(plugtext), text_len); |
| 492 | 538 |
| 493 temp = g_strdup_printf("%s\n%s", p->name, p->description); | 539 temp = g_strdup_printf("Name: %s\n\nDescription:\n%s", |
| 540 (p->name != NULL) ? p->name : "", | |
| 541 (p->description != NULL) ? p->description : ""); | |
| 494 gtk_text_insert(GTK_TEXT(plugtext), NULL, NULL, NULL, temp, -1); | 542 gtk_text_insert(GTK_TEXT(plugtext), NULL, NULL, NULL, temp, -1); |
| 495 g_free(temp); | 543 g_free(temp); |
| 544 gtk_entry_set_text(GTK_ENTRY(plugentry), g_module_name(p->handle)); | |
| 496 | 545 |
| 497 /* Find out if this plug-in has a configuration function */ | 546 /* Find out if this plug-in has a configuration function */ |
| 498 if (g_module_symbol(p->handle, "gaim_plugin_config", (gpointer *)&gaim_plugin_config)) { | 547 if (g_module_symbol(p->handle, "gaim_plugin_config", (gpointer *)&gaim_plugin_config)) { |
| 499 confighandle = gtk_signal_connect(GTK_OBJECT(config), "clicked", | 548 confighandle = gtk_signal_connect(GTK_OBJECT(config), "clicked", |
| 500 GTK_SIGNAL_FUNC(gaim_plugin_config), NULL); | 549 GTK_SIGNAL_FUNC(gaim_plugin_config), NULL); |
| 501 gtk_widget_set_sensitive(config, 1); | 550 gtk_widget_set_sensitive(config, TRUE); |
| 502 } else { | 551 } else { |
| 503 confighandle = 0; | 552 confighandle = 0; |
| 504 gtk_widget_set_sensitive(config, 0); | 553 gtk_widget_set_sensitive(config, FALSE); |
| 505 } | 554 } |
| 506 } | 555 } |
| 507 | 556 |
| 508 void hide_plugins(GtkWidget *w, gpointer data) | 557 void hide_plugins(GtkWidget *w, gpointer data) |
| 509 { | 558 { |
| 510 if (plugwindow) | 559 if (plugwindow) |
| 511 gtk_widget_destroy(plugwindow); | 560 gtk_widget_destroy(plugwindow); |
| 512 plugwindow = NULL; | 561 plugwindow = NULL; |
| 513 config = NULL; | 562 config = NULL; |
| 514 confighandle = 0; | 563 confighandle = 0; |
| 564 } | |
| 565 | |
| 566 static const gchar *plugin_makelistname(GModule *module) | |
| 567 { | |
| 568 static gchar filename[PATHSIZE]; | |
| 569 gchar *filepath = g_module_name(module); | |
| 570 char *cp; | |
| 571 | |
| 572 if (filepath == NULL || strlen(filepath) == 0) | |
| 573 return NULL; | |
| 574 | |
| 575 if ((cp = strrchr(filepath, '/')) == NULL || *++cp == '\0') | |
| 576 cp = filepath; | |
| 577 | |
| 578 strncpy(filename, cp, sizeof(filename)); | |
| 579 filename[sizeof(filename) - 1] = '\0'; | |
| 580 | |
| 581 /* Try to pretty name by removing any trailing ".so" */ | |
| 582 if (strlen(filename) > 3 && | |
| 583 strncmp(filename + strlen(filename) - 3, ".so", 3) == 0) | |
| 584 filename[strlen(filename) - 3] = '\0'; | |
| 585 | |
| 586 return filename; | |
| 587 } | |
| 588 | |
| 589 /* Remove all callbacks associated with plugin handle */ | |
| 590 static void plugin_remove_callbacks(GModule *handle) | |
| 591 { | |
| 592 GList *c = callbacks; | |
| 593 struct gaim_callback *g; | |
| 594 | |
| 595 debug_printf("%d callbacks to search\n", g_list_length(callbacks)); | |
| 596 | |
| 597 while (c) { | |
| 598 g = (struct gaim_callback *)c->data; | |
| 599 if (g->handle == handle) { | |
| 600 c = g_list_next(c); | |
| 601 callbacks = g_list_remove(callbacks, (gpointer)g); | |
| 602 debug_printf("Removing callback, %d remain\n", g_list_length(callbacks)); | |
| 603 } else | |
| 604 c = g_list_next(c); | |
| 605 } | |
| 515 } | 606 } |
| 516 | 607 |
| 517 void gaim_signal_connect(GModule *handle, enum gaim_event which, void *func, void *data) | 608 void gaim_signal_connect(GModule *handle, enum gaim_event which, void *func, void *data) |
| 518 { | 609 { |
| 519 struct gaim_callback *call = g_new0(struct gaim_callback, 1); | 610 struct gaim_callback *call = g_new0(struct gaim_callback, 1); |
