4 * Copyright (C) 1998-1999, Mark Spencer <markster@marko.net>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 * Plugin support is currently being maintained by Mike Saraf
26 * Well, I didn't see any work done on it for a while, so I'm going to try
27 * my hand at it. - Eric warmenhoven@yahoo.com
29 * Mike is my roomate. I can assure you that he's lazy :-P -- Rob rob@marko.net
42 #include <sys/types.h>
51 #include "pixmaps/gnome_add.xpm"
52 #include "pixmaps/gnome_remove.xpm"
53 #include "pixmaps/gnome_preferences.xpm"
54 #include "pixmaps/refresh.xpm"
55 #include "pixmaps/cancel.xpm"
57 #define PATHSIZE 1024 /* XXX: stolen from dialogs.c */
60 /* ------------------ Local Variables ------------------------ */
62 static GtkWidget
*plugin_dialog
= NULL
;
64 static GtkWidget
*pluglist
= NULL
;
65 static GtkWidget
*plugtext
= NULL
;
66 static GtkWidget
*plugwindow
= NULL
;
67 static GtkWidget
*plugentry
= NULL
;
69 static GtkTooltips
*tooltips
= NULL
;
71 static GtkWidget
*config
= NULL
;
72 static guint confighandle
= 0;
73 static GtkWidget
*reload
= NULL
;
74 static GtkWidget
*unload
= NULL
;
75 extern char *last_dir
;
77 /* --------------- Function Declarations --------------------- */
79 void show_plugins(GtkWidget
*, gpointer
);
81 /* UI button callbacks */
82 static void unload_plugin_cb(GtkWidget
*, gpointer
);
83 static void plugin_reload_cb(GtkWidget
*, gpointer
);
85 static const gchar
*plugin_makelistname(GModule
*);
87 static void destroy_plugins(GtkWidget
*, gpointer
);
88 static void load_file(GtkWidget
*, gpointer
);
89 static void load_which_plugin(GtkWidget
*, gpointer
);
90 static void list_clicked(GtkWidget
*, struct gaim_plugin
*);
91 void update_show_plugins();
92 static void hide_plugins(GtkWidget
*, gpointer
);
94 /* ------------------ Code Below ---------------------------- */
96 static void destroy_plugins(GtkWidget
*w
, gpointer data
)
99 gtk_widget_destroy(plugin_dialog
);
100 plugin_dialog
= NULL
;
103 static void load_file(GtkWidget
*w
, gpointer data
)
108 gtk_widget_show(plugin_dialog
);
109 gdk_window_raise(plugin_dialog
->window
);
113 plugin_dialog
= gtk_file_selection_new(_("Gaim - Plugin List"));
115 gtk_file_selection_hide_fileop_buttons(GTK_FILE_SELECTION(plugin_dialog
));
118 buf
= g_strdup(LIBDIR
);
120 buf
= g_strconcat(last_dir
, G_DIR_SEPARATOR_S
, NULL
);
122 gtk_file_selection_set_filename(GTK_FILE_SELECTION(plugin_dialog
), buf
);
123 gtk_file_selection_complete(GTK_FILE_SELECTION(plugin_dialog
), "*.so");
124 gtk_signal_connect(GTK_OBJECT(plugin_dialog
), "destroy",
125 GTK_SIGNAL_FUNC(destroy_plugins
), plugin_dialog
);
127 gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(plugin_dialog
)->ok_button
),
128 "clicked", GTK_SIGNAL_FUNC(load_which_plugin
), NULL
);
130 gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(plugin_dialog
)->cancel_button
),
131 "clicked", GTK_SIGNAL_FUNC(destroy_plugins
), NULL
);
134 gtk_widget_show(plugin_dialog
);
135 gdk_window_raise(plugin_dialog
->window
);
138 static void load_which_plugin(GtkWidget
*w
, gpointer data
)
142 file
= gtk_file_selection_get_filename(GTK_FILE_SELECTION(plugin_dialog
));
143 if (file_is_dir(file
, plugin_dialog
)) {
151 gtk_widget_destroy(plugin_dialog
);
152 plugin_dialog
= NULL
;
154 update_show_plugins();
157 void show_plugins(GtkWidget
*w
, gpointer data
)
159 /* most of this code was shamelessly stolen from Glade */
166 GtkWidget
*scrolledwindow
;
174 GAIM_DIALOG(plugwindow
);
175 gtk_window_set_wmclass(GTK_WINDOW(plugwindow
), "plugins", "Gaim");
176 gtk_widget_realize(plugwindow
);
177 aol_icon(plugwindow
->window
);
178 gtk_window_set_title(GTK_WINDOW(plugwindow
), _("Gaim - Plugins"));
179 gtk_widget_set_usize(plugwindow
, 515, 300);
180 gtk_signal_connect(GTK_OBJECT(plugwindow
), "destroy", GTK_SIGNAL_FUNC(hide_plugins
), NULL
);
182 mainvbox
= gtk_vbox_new(FALSE
, 0);
183 gtk_container_add(GTK_CONTAINER(plugwindow
), mainvbox
);
184 gtk_widget_show(mainvbox
);
187 tophbox
= gtk_hbox_new(FALSE
, 0);
188 gtk_box_pack_start(GTK_BOX(mainvbox
), tophbox
, TRUE
, TRUE
, 0);
189 gtk_widget_show(tophbox
);
191 /* Left side: frame with list of plugin file names */
192 frame
= gtk_frame_new(_("Loaded Plugins"));
193 gtk_box_pack_start(GTK_BOX(tophbox
), frame
, FALSE
, FALSE
, 0);
194 gtk_widget_set_usize(frame
, 140, -1);
195 gtk_container_set_border_width(GTK_CONTAINER(frame
), 6);
196 gtk_frame_set_label_align(GTK_FRAME(frame
), 0.05, 0.5);
197 gtk_widget_show(frame
);
199 scrolledwindow
= gtk_scrolled_window_new(NULL
, NULL
);
200 gtk_container_add(GTK_CONTAINER(frame
), scrolledwindow
);
201 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledwindow
),
202 GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
203 gtk_widget_show(scrolledwindow
);
205 pluglist
= gtk_list_new();
206 gtk_list_set_selection_mode(GTK_LIST(pluglist
), GTK_SELECTION_BROWSE
);
207 gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolledwindow
), pluglist
);
208 gtk_widget_show(pluglist
);
210 /* Right side: frame with description and the filepath of plugin */
211 frame
= gtk_frame_new(_("Description"));
212 gtk_box_pack_start(GTK_BOX(tophbox
), frame
, TRUE
, TRUE
, 0);
213 gtk_container_set_border_width(GTK_CONTAINER(frame
), 6);
214 gtk_frame_set_label_align(GTK_FRAME(frame
), 0.05, 0.5);
215 gtk_widget_show(frame
);
217 vbox
= gtk_vbox_new(FALSE
, 0);
218 gtk_container_add(GTK_CONTAINER(frame
), vbox
);
219 gtk_widget_show(vbox
);
221 scrolledwindow
= gtk_scrolled_window_new(NULL
, NULL
);
222 gtk_box_pack_start(GTK_BOX(vbox
), scrolledwindow
, TRUE
, TRUE
, 0);
223 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolledwindow
),
224 GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
225 gtk_widget_show(scrolledwindow
);
227 plugtext
= gtk_text_new(NULL
, NULL
);
228 gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolledwindow
), plugtext
);
229 gtk_text_set_word_wrap(GTK_TEXT(plugtext
), TRUE
);
230 gtk_text_set_editable(GTK_TEXT(plugtext
), FALSE
);
231 gtk_widget_show(plugtext
);
233 hbox
= gtk_hbox_new(FALSE
, 5);
234 gtk_box_pack_start(GTK_BOX(vbox
), hbox
, FALSE
, FALSE
, 0);
235 gtk_container_set_border_width(GTK_CONTAINER(hbox
), 6);
236 gtk_widget_show(hbox
);
238 label
= gtk_label_new(_("Filepath:"));
239 gtk_box_pack_start(GTK_BOX(hbox
), label
, FALSE
, FALSE
, 0);
240 gtk_widget_show(label
);
242 plugentry
= gtk_entry_new();
243 gtk_box_pack_start(GTK_BOX(hbox
), plugentry
, TRUE
, TRUE
, 0);
244 gtk_entry_set_editable(GTK_ENTRY(plugentry
), FALSE
);
245 gtk_widget_show(plugentry
);
247 /* Build the bottom button bar */
248 bothbox
= gtk_hbox_new(TRUE
, 10);
249 gtk_box_pack_start(GTK_BOX(mainvbox
), bothbox
, FALSE
, FALSE
, 0);
250 gtk_container_set_border_width(GTK_CONTAINER(hbox
), 5);
251 gtk_widget_show(bothbox
);
254 tooltips
= gtk_tooltips_new();
256 add
= picture_button(plugwindow
, _("Load"), gnome_add_xpm
);
257 gtk_signal_connect(GTK_OBJECT(add
), "clicked", GTK_SIGNAL_FUNC(load_file
), NULL
);
258 gtk_box_pack_start(GTK_BOX(bothbox
), add
, TRUE
, TRUE
, 0);
259 gtk_tooltips_set_tip(tooltips
, add
, _("Load a plugin from a file"), "");
261 config
= picture_button(plugwindow
, _("Configure"), gnome_preferences_xpm
);
262 gtk_widget_set_sensitive(config
, FALSE
);
263 gtk_box_pack_start(GTK_BOX(bothbox
), config
, TRUE
, TRUE
, 0);
264 gtk_tooltips_set_tip(tooltips
, config
, _("Configure settings of the selected plugin"), "");
266 reload
= picture_button(plugwindow
, _("Reload"), refresh_xpm
);
267 gtk_widget_set_sensitive(reload
, FALSE
);
268 gtk_signal_connect(GTK_OBJECT(reload
), "clicked", GTK_SIGNAL_FUNC(plugin_reload_cb
), NULL
);
269 gtk_box_pack_start(GTK_BOX(bothbox
), reload
, TRUE
, TRUE
, 0);
270 gtk_tooltips_set_tip(tooltips
, reload
, _("Reload the selected plugin"), "");
272 unload
= picture_button(plugwindow
, _("Unload"), gnome_remove_xpm
);
273 gtk_signal_connect(GTK_OBJECT(unload
), "clicked", GTK_SIGNAL_FUNC(unload_plugin_cb
), pluglist
);
274 gtk_box_pack_start(GTK_BOX(bothbox
), unload
, TRUE
, TRUE
, 0);
275 gtk_tooltips_set_tip(tooltips
, unload
, _("Unload the selected plugin"), "");
277 close
= picture_button(plugwindow
, _("Close"), cancel_xpm
);
278 gtk_signal_connect(GTK_OBJECT(close
), "clicked", GTK_SIGNAL_FUNC(hide_plugins
), NULL
);
279 gtk_box_pack_start(GTK_BOX(bothbox
), close
, TRUE
, TRUE
, 0);
280 gtk_tooltips_set_tip(tooltips
, close
, _("Close this window"), "");
282 update_show_plugins();
283 gtk_widget_show(plugwindow
);
286 void update_show_plugins()
288 GList
*plugs
= plugins
;
289 struct gaim_plugin
*p
;
291 GtkWidget
*list_item
;
294 if (plugwindow
== NULL
)
297 gtk_list_clear_items(GTK_LIST(pluglist
), 0, -1);
299 p
= (struct gaim_plugin
*)plugs
->data
;
300 label
= gtk_label_new(plugin_makelistname(p
->handle
));
301 hbox
= gtk_hbox_new(FALSE
, 0); /* for left justification */
302 gtk_box_pack_start(GTK_BOX(hbox
), label
, FALSE
, FALSE
, 0);
304 list_item
= gtk_list_item_new();
305 gtk_container_add(GTK_CONTAINER(list_item
), hbox
);
306 gtk_signal_connect(GTK_OBJECT(list_item
), "select", GTK_SIGNAL_FUNC(list_clicked
), p
);
307 gtk_object_set_user_data(GTK_OBJECT(list_item
), p
);
309 gtk_widget_show(hbox
);
310 gtk_widget_show(label
);
311 gtk_container_add(GTK_CONTAINER(pluglist
), list_item
);
312 gtk_widget_show(list_item
);
314 plugs
= g_list_next(plugs
);
317 /* Clear the display if nothing's selected */
318 if (GTK_LIST(pluglist
)->selection
== NULL
) {
319 guint text_len
= gtk_text_get_length(GTK_TEXT(plugtext
));
320 gtk_text_set_point(GTK_TEXT(plugtext
), 0);
321 gtk_text_forward_delete(GTK_TEXT(plugtext
), text_len
);
322 gtk_entry_set_text(GTK_ENTRY(plugentry
), "");
324 gtk_widget_set_sensitive(config
, FALSE
);
325 gtk_widget_set_sensitive(reload
, FALSE
);
326 gtk_widget_set_sensitive(unload
, FALSE
);
330 static void unload_plugin_cb(GtkWidget
*w
, gpointer data
)
333 struct gaim_plugin
*p
;
335 i
= GTK_LIST(pluglist
)->selection
;
340 p
= gtk_object_get_user_data(GTK_OBJECT(i
->data
));
343 update_show_plugins();
346 static void plugin_reload_cb(GtkWidget
*w
, gpointer data
)
349 struct gaim_plugin
*p
;
351 i
= GTK_LIST(pluglist
)->selection
;
355 /* Just pass off plugin to the actual function */
356 p
= reload_plugin(gtk_object_get_user_data(GTK_OBJECT(i
->data
)));
358 update_show_plugins();
360 /* Try and reselect the plugin in list */
363 gtk_list_select_item(GTK_LIST(pluglist
), g_list_index(plugins
, p
));
366 static void list_clicked(GtkWidget
*w
, struct gaim_plugin
*p
)
370 void (*gaim_plugin_config
)();
372 if (confighandle
!= 0)
373 gtk_signal_disconnect(GTK_OBJECT(config
), confighandle
);
375 text_len
= gtk_text_get_length(GTK_TEXT(plugtext
));
376 gtk_text_set_point(GTK_TEXT(plugtext
), 0);
377 gtk_text_forward_delete(GTK_TEXT(plugtext
), text_len
);
379 temp
= g_strdup_printf("Name: %s\n\nDescription:\n%s",
380 (p
->name
!= NULL
) ? p
->name
: "",
381 (p
->description
!= NULL
) ? p
->description
: "");
382 gtk_text_insert(GTK_TEXT(plugtext
), NULL
, NULL
, NULL
, temp
, -1);
384 gtk_entry_set_text(GTK_ENTRY(plugentry
), g_module_name(p
->handle
));
386 /* Find out if this plug-in has a configuration function */
387 if (g_module_symbol(p
->handle
, "gaim_plugin_config", (gpointer
*)&gaim_plugin_config
)) {
388 confighandle
= gtk_signal_connect(GTK_OBJECT(config
), "clicked",
389 GTK_SIGNAL_FUNC(gaim_plugin_config
), NULL
);
390 gtk_widget_set_sensitive(config
, TRUE
);
393 gtk_widget_set_sensitive(config
, FALSE
);
396 gtk_widget_set_sensitive(reload
, TRUE
);
397 gtk_widget_set_sensitive(unload
, TRUE
);
400 static void hide_plugins(GtkWidget
*w
, gpointer data
)
403 gtk_widget_destroy(plugwindow
);
409 static const gchar
*plugin_makelistname(GModule
*module
)
411 static gchar filename
[PATHSIZE
];
412 gchar
*filepath
= g_module_name(module
);
415 if (filepath
== NULL
|| strlen(filepath
) == 0)
418 if ((cp
= strrchr(filepath
, '/')) == NULL
|| *++cp
== '\0')
421 strncpy(filename
, cp
, sizeof(filename
));
422 filename
[sizeof(filename
) - 1] = '\0';
424 /* Try to pretty name by removing any trailing ".so" */
425 if (strlen(filename
) > 3 &&
426 strncmp(filename
+ strlen(filename
) - 3, ".so", 3) == 0)
427 filename
[strlen(filename
) - 3] = '\0';