# HG changeset patch # User Eric Warmenhoven # Date 991129565 0 # Node ID db3104dda736305c46c1f4760a1936382e7f4db1 # Parent 1cfc79c126fe6f4637aa7ad747019940bfd22608 [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 diff -r 1cfc79c126fe -r db3104dda736 ChangeLog --- a/ChangeLog Tue May 29 01:49:35 2001 +0000 +++ b/ChangeLog Tue May 29 09:46:05 2001 +0000 @@ -22,6 +22,7 @@ * Can receive buddy icons in Oscar (requires gdk_pixbuf, which GNOME depends on. If you --disable-pixbuf, it will disable this.) + * Redesigned plugins dialog (thanks Mike Heffner) version 0.11.0-pre11 (04/30/2001): * Zephyr updates and additions, thanks Neil Sanchala (nsanch) diff -r 1cfc79c126fe -r db3104dda736 src/plugins.c --- a/src/plugins.c Tue May 29 01:49:35 2001 +0000 +++ b/src/plugins.c Tue May 29 09:46:05 2001 +0000 @@ -50,6 +50,15 @@ #include +#include "pixmaps/gnome_add.xpm" +#include "pixmaps/gnome_remove.xpm" +#include "pixmaps/gnome_preferences.xpm" +#include "pixmaps/refresh.xpm" +#include "pixmaps/cancel.xpm" + +#define PATHSIZE 1024 /* XXX: stolen from dialogs.c */ + + /* ------------------ Global Variables ----------------------- */ GList *plugins = NULL; @@ -59,9 +68,12 @@ static GtkWidget *plugin_dialog = NULL; -static GtkWidget *pluglist; -static GtkWidget *plugtext; -static GtkWidget *plugwindow; +static GtkWidget *pluglist = NULL; +static GtkWidget *plugtext = NULL; +static GtkWidget *plugwindow = NULL; +static GtkWidget *plugentry = NULL; + +static GtkTooltips *tooltips = NULL; static GtkWidget *config = NULL; static guint confighandle = 0; @@ -76,6 +88,14 @@ void gaim_signal_disconnect(GModule *, enum gaim_event, void *); void gaim_plugin_unload(GModule *); +/* UI button callbacks */ +static void plugin_reload_cb(GtkWidget *, gpointer); + +static const gchar *plugin_makelistname(GModule *); +static void plugin_remove_callbacks(GModule *); + +static void plugin_reload(struct gaim_plugin *p); + static void destroy_plugins(GtkWidget *, gpointer); static void load_file(GtkWidget *, gpointer); static void load_which_plugin(GtkWidget *, gpointer); @@ -163,13 +183,9 @@ while (filename && c) { plug = (struct gaim_plugin *)c->data; if (!strcmp(filename, g_module_name(plug->handle))) { - void (*gaim_plugin_remove)(); - if (g_module_symbol(plug->handle, "gaim_plugin_remove", - (gpointer *)&gaim_plugin_remove)) - (*gaim_plugin_remove)(); - - unload_immediate(plug->handle); - c = plugins; + /* just need to reload plugin */ + plugin_reload(plug); + return; } else c = g_list_next(c); } @@ -198,23 +214,9 @@ } retval = (*gaim_plugin_init)(plug->handle); - debug_printf("loaded plugin returned %d\n", retval); + debug_printf("loaded plugin returned %s\n", retval ? retval : "NULL"); if (retval) { - GList *c = callbacks; - struct gaim_callback *g; - while (c) { - g = (struct gaim_callback *)c->data; - if (g->handle == plug->handle) { - callbacks = g_list_remove(callbacks, c->data); - debug_printf("Removing callback, %d remain\n", g_list_length(callbacks)); - c = callbacks; - if (c == NULL) { - break; - } - } else { - c = g_list_next(c); - } - } + plugin_remove_callbacks(plug->handle); do_error_dialog(retval, _("Plugin Error")); g_module_close(plug->handle); g_free(plug); @@ -249,19 +251,19 @@ void show_plugins(GtkWidget *w, gpointer data) { - /* most of this code was shamelessly stolen from prefs.c */ - GtkWidget *page; - GtkWidget *topbox; - GtkWidget *botbox; - GtkWidget *sw; + /* most of this code was shamelessly stolen from Glade */ + GtkWidget *mainvbox; + GtkWidget *tophbox; + GtkWidget *bothbox; + GtkWidget *hbox; + GtkWidget *vbox; + GtkWidget *frame; + GtkWidget *scrolledwindow; GtkWidget *label; - GtkWidget *list_item; - GtkWidget *sw2; GtkWidget *add; + GtkWidget *reload; GtkWidget *remove; GtkWidget *close; - GList *plugs = plugins; - struct gaim_plugin *p; if (plugwindow) return; @@ -270,95 +272,110 @@ gtk_window_set_wmclass(GTK_WINDOW(plugwindow), "plugins", "Gaim"); gtk_widget_realize(plugwindow); aol_icon(plugwindow->window); - gtk_container_border_width(GTK_CONTAINER(plugwindow), 5); gtk_window_set_title(GTK_WINDOW(plugwindow), _("Gaim - Plugins")); - gtk_widget_set_usize(plugwindow, 400, 250); + gtk_widget_set_usize(plugwindow, 515, 300); gtk_signal_connect(GTK_OBJECT(plugwindow), "destroy", GTK_SIGNAL_FUNC(hide_plugins), NULL); - page = gtk_vbox_new(FALSE, 5); - topbox = gtk_hbox_new(FALSE, 5); - botbox = gtk_hbox_new(FALSE, 5); + mainvbox = gtk_vbox_new(FALSE, 0); + gtk_container_add(GTK_CONTAINER(plugwindow), mainvbox); + gtk_widget_show(mainvbox); + + /* Build the top */ + tophbox = gtk_hbox_new(FALSE, 0); + gtk_box_pack_start(GTK_BOX(mainvbox), tophbox, TRUE, TRUE, 0); + gtk_widget_show(tophbox); - /* Left side: list of plugin file names */ - sw2 = gtk_scrolled_window_new(NULL, NULL); - gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw2), - GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + /* Left side: frame with list of plugin file names */ + frame = gtk_frame_new(_("Plugins")); + gtk_box_pack_start(GTK_BOX(tophbox), frame, FALSE, FALSE, 0); + gtk_widget_set_usize(frame, 140, -1); + gtk_container_set_border_width(GTK_CONTAINER(frame), 6); + gtk_frame_set_label_align(GTK_FRAME(frame), 0.05, 0.5); + gtk_widget_show(frame); + + scrolledwindow = gtk_scrolled_window_new(NULL, NULL); + gtk_container_add(GTK_CONTAINER(frame), scrolledwindow); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledwindow), + GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_widget_show(scrolledwindow); pluglist = gtk_list_new(); - gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(sw2), pluglist); - gtk_box_pack_start(GTK_BOX(topbox), sw2, TRUE, TRUE, 0); + gtk_list_set_selection_mode(GTK_LIST(pluglist), GTK_SELECTION_BROWSE); + gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolledwindow), pluglist); + gtk_widget_show(pluglist); - /* Right side: the text description of the plugin */ - sw = gtk_scrolled_window_new(NULL, NULL); - gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), - GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + /* Right side: frame with description and the filepath of plugin */ + frame = gtk_frame_new(_("Description")); + gtk_box_pack_start(GTK_BOX(tophbox), frame, TRUE, TRUE, 0); + gtk_container_set_border_width(GTK_CONTAINER(frame), 6); + gtk_frame_set_label_align(GTK_FRAME(frame), 0.05, 0.5); + gtk_widget_show(frame); + + vbox = gtk_vbox_new(FALSE, 0); + gtk_container_add(GTK_CONTAINER(frame), vbox); + gtk_widget_show(vbox); + + scrolledwindow = gtk_scrolled_window_new(NULL, NULL); + gtk_box_pack_start(GTK_BOX(vbox), scrolledwindow, TRUE, TRUE, 0); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledwindow), + GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + gtk_widget_show(scrolledwindow); plugtext = gtk_text_new(NULL, NULL); - gtk_container_add(GTK_CONTAINER(sw), plugtext); - gtk_box_pack_start(GTK_BOX(topbox), sw, TRUE, TRUE, 0); + gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolledwindow), plugtext); gtk_text_set_word_wrap(GTK_TEXT(plugtext), TRUE); gtk_text_set_editable(GTK_TEXT(plugtext), FALSE); + gtk_widget_show(plugtext); + + hbox = gtk_hbox_new(FALSE, 5); + gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); + gtk_container_set_border_width(GTK_CONTAINER(hbox), 6); + gtk_widget_show(hbox); + + label = gtk_label_new(_("Filepath:")); + gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); + gtk_widget_show(label); + + plugentry = gtk_entry_new(); + gtk_box_pack_start(GTK_BOX(hbox), plugentry, TRUE, TRUE, 0); + gtk_entry_set_editable(GTK_ENTRY(plugentry), FALSE); + gtk_widget_show(plugentry); /* Build the bottom button bar */ - add = gtk_button_new_with_label(_("Load Plugin")); - gtk_signal_connect(GTK_OBJECT(add), "clicked", GTK_SIGNAL_FUNC(load_file), NULL); - gtk_box_pack_start(GTK_BOX(botbox), add, TRUE, TRUE, 0); - if (display_options & OPT_DISP_COOL_LOOK) - gtk_button_set_relief(GTK_BUTTON(add), GTK_RELIEF_NONE); - - config = gtk_button_new_with_label(_("Configure Plugin")); - gtk_widget_set_sensitive(config, 0); - gtk_box_pack_start(GTK_BOX(botbox), config, TRUE, TRUE, 0); - if (display_options & OPT_DISP_COOL_LOOK) - gtk_button_set_relief(GTK_BUTTON(config), GTK_RELIEF_NONE); + bothbox = gtk_hbox_new(TRUE, 10); + gtk_box_pack_start(GTK_BOX(mainvbox), bothbox, FALSE, FALSE, 0); + gtk_container_set_border_width(GTK_CONTAINER(hbox), 5); + gtk_widget_show(bothbox); - remove = gtk_button_new_with_label(_("Unload Plugin")); - gtk_signal_connect(GTK_OBJECT(remove), "clicked", GTK_SIGNAL_FUNC(unload), pluglist); - gtk_box_pack_start(GTK_BOX(botbox), remove, TRUE, TRUE, 0); - if (display_options & OPT_DISP_COOL_LOOK) - gtk_button_set_relief(GTK_BUTTON(remove), GTK_RELIEF_NONE); + if (!tooltips) + tooltips = gtk_tooltips_new(); - close = gtk_button_new_with_label(_("Close")); - gtk_signal_connect(GTK_OBJECT(close), "clicked", GTK_SIGNAL_FUNC(hide_plugins), NULL); - gtk_box_pack_start(GTK_BOX(botbox), close, TRUE, TRUE, 0); - if (display_options & OPT_DISP_COOL_LOOK) - gtk_button_set_relief(GTK_BUTTON(close), GTK_RELIEF_NONE); - - gtk_box_pack_start(GTK_BOX(page), topbox, TRUE, TRUE, 0); - gtk_box_pack_start(GTK_BOX(page), botbox, FALSE, FALSE, 0); + add = picture_button(plugwindow, _("Load"), gnome_add_xpm); + gtk_signal_connect(GTK_OBJECT(add), "clicked", GTK_SIGNAL_FUNC(load_file), NULL); + gtk_box_pack_start(GTK_BOX(bothbox), add, TRUE, TRUE, 0); + gtk_tooltips_set_tip(tooltips, add, _("Load a plugin from a file"), ""); - while (plugs) { - p = (struct gaim_plugin *)plugs->data; - label = gtk_label_new(g_module_name(p->handle)); - list_item = gtk_list_item_new(); - gtk_container_add(GTK_CONTAINER(list_item), label); - gtk_signal_connect(GTK_OBJECT(list_item), "select", GTK_SIGNAL_FUNC(list_clicked), p); - gtk_object_set_user_data(GTK_OBJECT(list_item), p); + config = picture_button(plugwindow, _("Configure"), gnome_preferences_xpm); + gtk_widget_set_sensitive(config, FALSE); + gtk_box_pack_start(GTK_BOX(bothbox), config, TRUE, TRUE, 0); + gtk_tooltips_set_tip(tooltips, config, _("Configure settings of the selected plugin"), ""); - gtk_widget_show(label); - gtk_container_add(GTK_CONTAINER(pluglist), list_item); - gtk_widget_show(list_item); - - plugs = g_list_next(plugs); - } + reload = picture_button(plugwindow, _("Reload"), refresh_xpm); + gtk_signal_connect(GTK_OBJECT(reload), "clicked", GTK_SIGNAL_FUNC(plugin_reload_cb), NULL); + gtk_box_pack_start(GTK_BOX(bothbox), reload, TRUE, TRUE, 0); + gtk_tooltips_set_tip(tooltips, reload, _("Reload the selected plugin"), ""); - /* Make the first item selected */ - if (plugins != NULL) - gtk_list_select_item(GTK_LIST(pluglist), 0); + remove = picture_button(plugwindow, _("Unload"), gnome_remove_xpm); + gtk_signal_connect(GTK_OBJECT(remove), "clicked", GTK_SIGNAL_FUNC(unload), pluglist); + gtk_box_pack_start(GTK_BOX(bothbox), remove, TRUE, TRUE, 0); + gtk_tooltips_set_tip(tooltips, remove, _("Unload the selected plugin"), ""); - gtk_widget_show(page); - gtk_widget_show(topbox); - gtk_widget_show(botbox); - gtk_widget_show(sw); - gtk_widget_show(sw2); - gtk_widget_show(pluglist); - gtk_widget_show(plugtext); - gtk_widget_show(add); - gtk_widget_show(config); - gtk_widget_show(remove); - gtk_widget_show(close); + close = picture_button(plugwindow, _("Close"), cancel_xpm); + gtk_signal_connect(GTK_OBJECT(close), "clicked", GTK_SIGNAL_FUNC(hide_plugins), NULL); + gtk_box_pack_start(GTK_BOX(bothbox), close, TRUE, TRUE, 0); + gtk_tooltips_set_tip(tooltips, close, _("Close this window"), ""); - gtk_container_add(GTK_CONTAINER(plugwindow), page); + update_show_plugins(); gtk_widget_show(plugwindow); } @@ -368,6 +385,7 @@ struct gaim_plugin *p; GtkWidget *label; GtkWidget *list_item; + GtkWidget *hbox; if (plugwindow == NULL) return; @@ -375,23 +393,22 @@ gtk_list_clear_items(GTK_LIST(pluglist), 0, -1); while (plugs) { p = (struct gaim_plugin *)plugs->data; - label = gtk_label_new(g_module_name(p->handle)); + label = gtk_label_new(plugin_makelistname(p->handle)); + hbox = gtk_hbox_new(FALSE, 0); /* for left justification */ + gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); + list_item = gtk_list_item_new(); - gtk_container_add(GTK_CONTAINER(list_item), label); + gtk_container_add(GTK_CONTAINER(list_item), hbox); gtk_signal_connect(GTK_OBJECT(list_item), "select", GTK_SIGNAL_FUNC(list_clicked), p); gtk_object_set_user_data(GTK_OBJECT(list_item), p); + gtk_widget_show(hbox); gtk_widget_show(label); gtk_container_add(GTK_CONTAINER(pluglist), list_item); gtk_widget_show(list_item); + plugs = g_list_next(plugs); } - if (plugins != NULL) - gtk_list_select_item(GTK_LIST(pluglist), 0); - else { - gtk_text_set_point(GTK_TEXT(plugtext), 0); - gtk_text_forward_delete(GTK_TEXT(plugtext), gtk_text_get_length(GTK_TEXT(plugtext))); - } } void unload(GtkWidget *w, gpointer data) @@ -412,14 +429,13 @@ (*gaim_plugin_remove)(); unload_immediate(p->handle); + update_show_plugins(); } static void unload_for_real(void *handle) { GList *i; struct gaim_plugin *p = NULL; - GList *c = callbacks; - struct gaim_callback *g; i = plugins; while (i) { @@ -435,27 +451,10 @@ debug_printf("Unloading %s\n", g_module_name(p->handle)); - debug_printf("%d callbacks to search\n", g_list_length(callbacks)); - - while (c) { - g = (struct gaim_callback *)c->data; - if (g->handle == p->handle) { - callbacks = g_list_remove(callbacks, c->data); - g_free(g); - debug_printf("Removing callback, %d remain\n", g_list_length(callbacks)); - c = callbacks; - if (c == NULL) { - break; - } - } else { - c = g_list_next(c); - } - } + plugin_remove_callbacks(p->handle); plugins = g_list_remove(plugins, p); g_free(p); - if (config) - gtk_widget_set_sensitive(config, 0); update_show_plugins(); save_prefs(); } @@ -478,6 +477,52 @@ gtk_timeout_add(5000, (GtkFunction)unload_timeout, handle); } +static void plugin_reload_cb(GtkWidget *w, gpointer data) +{ + GList *i; + + i = GTK_LIST(pluglist)->selection; + if (i == NULL) + return; + + /* Just pass off plugin to the actual function */ + plugin_reload(gtk_object_get_user_data(GTK_OBJECT(i->data))); +} + +/* Do unload/load cycle of plugin. */ +static void plugin_reload(struct gaim_plugin *p) +{ + char file[PATHSIZE]; + void (*gaim_plugin_remove)(); + GModule *handle = p->handle; + struct gaim_plugin *plug; + GList *plugs; + + strncpy(file, g_module_name(handle), sizeof(file)); + file[sizeof(file) - 1] = '\0'; + + debug_printf("Reloading %s\n", file); + + /* Unload */ + if (g_module_symbol(handle, "gaim_plugin_remove", (gpointer *)&gaim_plugin_remove)) + (*gaim_plugin_remove)(); + unload_immediate(handle); + + /* Load */ + load_plugin(file); + + /* Try and reselect the plugin in list */ + plugs = plugins; + while (plugs) { + plug = plugs->data; + if (!strcmp(file, g_module_name(plug->handle))) { + gtk_list_select_item(GTK_LIST(pluglist), g_list_index(plugins, plug)); + return; + } + plugs = plugs->next; + } +} + void list_clicked(GtkWidget *w, struct gaim_plugin *p) { gchar *temp; @@ -486,22 +531,26 @@ if (confighandle != 0) gtk_signal_disconnect(GTK_OBJECT(config), confighandle); + text_len = gtk_text_get_length(GTK_TEXT(plugtext)); gtk_text_set_point(GTK_TEXT(plugtext), 0); gtk_text_forward_delete(GTK_TEXT(plugtext), text_len); - temp = g_strdup_printf("%s\n%s", p->name, p->description); + temp = g_strdup_printf("Name: %s\n\nDescription:\n%s", + (p->name != NULL) ? p->name : "", + (p->description != NULL) ? p->description : ""); gtk_text_insert(GTK_TEXT(plugtext), NULL, NULL, NULL, temp, -1); g_free(temp); + gtk_entry_set_text(GTK_ENTRY(plugentry), g_module_name(p->handle)); /* Find out if this plug-in has a configuration function */ if (g_module_symbol(p->handle, "gaim_plugin_config", (gpointer *)&gaim_plugin_config)) { confighandle = gtk_signal_connect(GTK_OBJECT(config), "clicked", GTK_SIGNAL_FUNC(gaim_plugin_config), NULL); - gtk_widget_set_sensitive(config, 1); + gtk_widget_set_sensitive(config, TRUE); } else { confighandle = 0; - gtk_widget_set_sensitive(config, 0); + gtk_widget_set_sensitive(config, FALSE); } } @@ -514,6 +563,48 @@ confighandle = 0; } +static const gchar *plugin_makelistname(GModule *module) +{ + static gchar filename[PATHSIZE]; + gchar *filepath = g_module_name(module); + char *cp; + + if (filepath == NULL || strlen(filepath) == 0) + return NULL; + + if ((cp = strrchr(filepath, '/')) == NULL || *++cp == '\0') + cp = filepath; + + strncpy(filename, cp, sizeof(filename)); + filename[sizeof(filename) - 1] = '\0'; + + /* Try to pretty name by removing any trailing ".so" */ + if (strlen(filename) > 3 && + strncmp(filename + strlen(filename) - 3, ".so", 3) == 0) + filename[strlen(filename) - 3] = '\0'; + + return filename; +} + +/* Remove all callbacks associated with plugin handle */ +static void plugin_remove_callbacks(GModule *handle) +{ + GList *c = callbacks; + struct gaim_callback *g; + + debug_printf("%d callbacks to search\n", g_list_length(callbacks)); + + while (c) { + g = (struct gaim_callback *)c->data; + if (g->handle == handle) { + c = g_list_next(c); + callbacks = g_list_remove(callbacks, (gpointer)g); + debug_printf("Removing callback, %d remain\n", g_list_length(callbacks)); + } else + c = g_list_next(c); + } +} + void gaim_signal_connect(GModule *handle, enum gaim_event which, void *func, void *data) { struct gaim_callback *call = g_new0(struct gaim_callback, 1);