/* X-Chat * Copyright (C) 1998 Peter Zelezny. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #include #include #include #include "fe-gtk.h" #include "../common/zoitechat.h" #define PLUGIN_C typedef struct session zoitechat_context; #include "../common/zoitechat-plugin.h" #include "../common/plugin.h" #include "../common/util.h" #include "../common/outbound.h" #include "../common/fe.h" #include "../common/zoitechatc.h" #include "../common/cfgfiles.h" #include "gtkutil.h" #include "maingui.h" /* model for the plugin treeview */ enum { NAME_COLUMN, VERSION_COLUMN, FILE_COLUMN, DESC_COLUMN, FILEPATH_COLUMN, N_COLUMNS }; static GtkWidget *plugin_window = NULL; static const char * plugingui_safe_string (const char *value) { return value ? value : ""; } static session * plugingui_get_target_session (void) { if (is_session (current_sess)) return current_sess; fe_message (_("No active session available for addon command."), FE_MSG_ERROR); return NULL; } #if HAVE_GTK3 #define ICON_PLUGIN_LOAD "document-open" #define ICON_PLUGIN_UNLOAD "edit-delete" #define ICON_PLUGIN_RELOAD "view-refresh" #endif #if !HAVE_GTK3 #define ICON_PLUGIN_LOAD GTK_STOCK_REVERT_TO_SAVED #define ICON_PLUGIN_UNLOAD GTK_STOCK_DELETE #define ICON_PLUGIN_RELOAD GTK_STOCK_REFRESH #endif #if HAVE_GTK3 static GtkWidget * plugingui_icon_button (GtkWidget *box, const char *label, const char *icon_name, GCallback callback, gpointer userdata) { GtkWidget *button; GtkWidget *image; button = gtk_button_new_with_mnemonic (label); image = gtk_image_new_from_icon_name (icon_name, GTK_ICON_SIZE_MENU); gtk_button_set_image (GTK_BUTTON (button), image); gtk_button_set_use_underline (GTK_BUTTON (button), TRUE); gtk_container_add (GTK_CONTAINER (box), button); g_signal_connect (G_OBJECT (button), "clicked", callback, userdata); gtk_widget_show (button); return button; } #endif static GtkWidget * plugingui_treeview_new (GtkWidget *box) { GtkListStore *store; GtkWidget *view; GtkTreeViewColumn *col; int col_id; store = gtk_list_store_new (N_COLUMNS, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING); g_return_val_if_fail (store != NULL, NULL); view = gtkutil_treeview_new (box, GTK_TREE_MODEL (store), NULL, NAME_COLUMN, _("Name"), VERSION_COLUMN, _("Version"), FILE_COLUMN, _("File"), DESC_COLUMN, _("Description"), FILEPATH_COLUMN, NULL, -1); gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (view), TRUE); for (col_id=0; (col = gtk_tree_view_get_column (GTK_TREE_VIEW (view), col_id)); col_id++) gtk_tree_view_column_set_alignment (col, 0.5); return view; } static char * plugingui_getfilename (GtkTreeView *view) { GtkTreeModel *model; GtkTreeSelection *sel; GtkTreeIter iter; GValue file; char *str; memset (&file, 0, sizeof (file)); sel = gtk_tree_view_get_selection (view); if (gtk_tree_selection_get_selected (sel, &model, &iter)) { gtk_tree_model_get_value (model, &iter, FILEPATH_COLUMN, &file); str = g_value_dup_string (&file); g_value_unset (&file); return str; } return NULL; } static void plugingui_close (GtkWidget * wid, gpointer a) { plugin_window = NULL; } extern GSList *plugin_list; void fe_pluginlist_update (void) { zoitechat_plugin *pl; GSList *list; GtkTreeView *view; GtkListStore *store; GtkTreeIter iter; if (!plugin_window) return; view = g_object_get_data (G_OBJECT (plugin_window), "view"); if (!GTK_IS_TREE_VIEW (view)) return; store = GTK_LIST_STORE (gtk_tree_view_get_model (view)); if (!GTK_IS_LIST_STORE (store)) return; gtk_list_store_clear (store); list = plugin_list; while (list) { pl = list->data; if (pl && pl->version && pl->version[0] != 0) { gtk_list_store_append (store, &iter); gtk_list_store_set (store, &iter, NAME_COLUMN, plugingui_safe_string (pl->name), VERSION_COLUMN, plugingui_safe_string (pl->version), FILE_COLUMN, pl->filename ? file_part (pl->filename) : "", DESC_COLUMN, plugingui_safe_string (pl->desc), FILEPATH_COLUMN, plugingui_safe_string (pl->filename), -1); } list = list->next; } } static void plugingui_load_cb (session *sess, char *file) { session *target_sess; if (file) { char *buf; target_sess = is_session (sess) ? sess : current_sess; if (!is_session (target_sess)) { fe_message (_("No active session available for loading addons."), FE_MSG_ERROR); return; } if (strchr (file, ' ')) buf = g_strdup_printf ("LOAD \"%s\"", file); else buf = g_strdup_printf ("LOAD %s", file); handle_command (target_sess, buf, FALSE); g_free (buf); } } void plugingui_load (void) { char *sub_dir = g_build_filename (get_xdir(), "addons", NULL); gtkutil_file_req (NULL, _("Select a Plugin or Script to load"), plugingui_load_cb, NULL, sub_dir, "*."PLUGIN_SUFFIX";*.lua;*.pl;*.py;*.tcl;*.js", FRF_FILTERISINITIAL|FRF_EXTENSIONS); g_free (sub_dir); } static void plugingui_loadbutton_cb (GtkWidget * wid, gpointer unused) { plugingui_load (); } static void plugingui_unload (GtkWidget * wid, gpointer unused) { char *modname, *file; session *target_sess; GtkTreeView *view; GtkTreeIter iter; view = g_object_get_data (G_OBJECT (plugin_window), "view"); if (!gtkutil_treeview_get_selected (view, &iter, NAME_COLUMN, &modname, FILEPATH_COLUMN, &file, -1)) return; if (!modname || !*modname) { g_free (modname); g_free (file); return; } if (!file || !*file) { g_free (modname); g_free (file); return; } if (g_str_has_suffix (file, "."PLUGIN_SUFFIX)) { if (plugin_kill (modname, FALSE) == 2) fe_message (_("That plugin is refusing to unload.\n"), FE_MSG_ERROR); } else { char *buf; /* let python.so or perl.so handle it */ target_sess = plugingui_get_target_session (); if (!target_sess) { g_free (modname); g_free (file); return; } if (strchr (file, ' ')) buf = g_strdup_printf ("UNLOAD \"%s\"", file); else buf = g_strdup_printf ("UNLOAD %s", file); handle_command (target_sess, buf, FALSE); g_free (buf); } g_free (modname); g_free (file); } static void plugingui_reloadbutton_cb (GtkWidget *wid, GtkTreeView *view) { char *file = plugingui_getfilename(view); session *target_sess; if (file) { char *buf; target_sess = plugingui_get_target_session (); if (!target_sess) { g_free (file); return; } if (strchr (file, ' ')) buf = g_strdup_printf ("RELOAD \"%s\"", file); else buf = g_strdup_printf ("RELOAD %s", file); handle_command (target_sess, buf, FALSE); g_free (buf); g_free (file); } } void plugingui_open (void) { GtkWidget *view; GtkWidget *view_scroll; GtkWidget *vbox, *hbox; char buf[128]; if (plugin_window) { mg_bring_tofront (plugin_window); return; } g_snprintf(buf, sizeof(buf), _("Plugins and Scripts - %s"), _(DISPLAY_NAME)); plugin_window = mg_create_generic_tab ("Addons", buf, FALSE, TRUE, plugingui_close, NULL, 700, 300, &vbox, 0); gtkutil_destroy_on_esc (plugin_window); view = plugingui_treeview_new (vbox); view_scroll = gtk_widget_get_parent (view); if (view_scroll) { gtk_box_set_child_packing (GTK_BOX (vbox), view_scroll, TRUE, TRUE, 0, GTK_PACK_START); gtk_widget_set_hexpand (view_scroll, TRUE); gtk_widget_set_vexpand (view_scroll, TRUE); } g_object_set_data (G_OBJECT (plugin_window), "view", view); #if HAVE_GTK3 hbox = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL); gtk_button_box_set_layout (GTK_BUTTON_BOX (hbox), GTK_BUTTONBOX_SPREAD); #elif !HAVE_GTK3 hbox = gtk_hbutton_box_new (); gtk_button_box_set_layout (GTK_BUTTON_BOX (hbox), GTK_BUTTONBOX_SPREAD); #endif gtk_container_set_border_width (GTK_CONTAINER (hbox), 5); gtk_box_pack_end (GTK_BOX (vbox), hbox, 0, 0, 0); #if HAVE_GTK3 { plugingui_icon_button (hbox, _("_Load..."), ICON_PLUGIN_LOAD, G_CALLBACK (plugingui_loadbutton_cb), NULL); plugingui_icon_button (hbox, _("_Unload"), ICON_PLUGIN_UNLOAD, G_CALLBACK (plugingui_unload), NULL); plugingui_icon_button (hbox, _("_Reload"), ICON_PLUGIN_RELOAD, G_CALLBACK (plugingui_reloadbutton_cb), view); } #endif #if !HAVE_GTK3 gtkutil_button (hbox, ICON_PLUGIN_LOAD, NULL, plugingui_loadbutton_cb, NULL, _("_Load...")); gtkutil_button (hbox, ICON_PLUGIN_UNLOAD, NULL, plugingui_unload, NULL, _("_Unload")); gtkutil_button (hbox, ICON_PLUGIN_RELOAD, NULL, plugingui_reloadbutton_cb, view, _("_Reload")); #endif fe_pluginlist_update (); gtk_widget_show_all (plugin_window); }