* Guifications - The end all, be all, toaster popup plugin * Copyright (C) 2003-2005 Gary Kramlich * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # include "../gf_config.h" #include "gf_preferences.h" #include "gf_theme_editor.h" #include "gf_theme_info.h" GF_THEME_COL_DESCRIPTION, GF_NOTIF_COL_DESCRIPTION, /******************************************************************************* ******************************************************************************/ GaimPlugin *guifications; /******************************************************************************* ******************************************************************************/ option_menu_cb(GtkOptionMenu *option_menu, gchar *pref) { gaim_prefs_set_int(pref, gtk_option_menu_get_history(option_menu)); mouse_option_menu_cb(GtkOptionMenu *option_menu, gchar *pref) { name = gf_actions_get_nth_name(gtk_option_menu_get_history(option_menu)); gaim_prefs_set_string(pref, name); /*********************************************************************** **********************************************************************/ make_notebook_page(GtkNotebook *note, const gchar *text, gint position) { vbox = gtk_vbox_new(FALSE, 6); gtk_container_set_border_width(GTK_CONTAINER(vbox), 12); label = gtk_label_new_with_mnemonic(text); gtk_notebook_insert_page(note, vbox, label, position); make_label(const gchar *text, GtkSizeGroup *sg) { label = gtk_label_new_with_mnemonic(text); gtk_misc_set_alignment(GTK_MISC(label), 0, 0); gtk_size_group_add_widget(sg, label); make_bold_label(const gchar *text, GtkSizeGroup *sg) { escaped = g_markup_escape_text(text, strlen(text)); markup = g_strdup_printf("<b>%s:</b>", escaped); label = gtk_label_new(NULL); gtk_label_set_markup_with_mnemonic(GTK_LABEL(label), markup); gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.0); gtk_size_group_add_widget(sg, label); make_option_menu(const gchar *text, gchar *pref, GtkSizeGroup *sg, GfMenuItemBuilder builder) GtkWidget *hbox, *option_menu, *menu, *label; hbox = gtk_hbox_new(FALSE, 4); label = make_label(text, sg); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); option_menu = gtk_option_menu_new(); gtk_box_pack_start(GTK_BOX(hbox), option_menu, FALSE, FALSE, 0); menu = gf_menu_build(builder, NULL); gtk_option_menu_set_menu(GTK_OPTION_MENU(option_menu), menu); gtk_option_menu_set_history(GTK_OPTION_MENU(option_menu), gaim_prefs_get_int(pref)); g_signal_connect(G_OBJECT(option_menu), "changed", G_CALLBACK(option_menu_cb), pref); gtk_widget_show_all(hbox); make_mouse_option_menu(const gchar *text, gchar *pref, GtkSizeGroup *sg) { GtkWidget *hbox, *option_menu, *menu, *label; hbox = gtk_hbox_new(FALSE, 4); label = make_label(text, sg); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); option_menu = gtk_option_menu_new(); gtk_box_pack_start(GTK_BOX(hbox), option_menu, FALSE, FALSE, 0); menu = gf_menu_build(gf_menu_mouse, NULL); gtk_option_menu_set_menu(GTK_OPTION_MENU(option_menu), menu); action = gf_action_find_with_name(gaim_prefs_get_string(pref)); if(action && (position = gf_action_get_position(action)) > -1) { gtk_option_menu_set_history(GTK_OPTION_MENU(option_menu), g_signal_connect(G_OBJECT(option_menu), "changed", G_CALLBACK(mouse_option_menu_cb), pref); gtk_widget_show_all(hbox); /******************************************************************************* ******************************************************************************/ make_general_page(GtkWidget *notebook) { GtkWidget *vbox, *frame, *spin, *option, *label; vbox = make_notebook_page(GTK_NOTEBOOK(notebook), _("General"), -1); sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL); frame = pidgin_make_frame(vbox, _("Display Options")); option = make_option_menu(_("_Position:"), GF_PREF_APPEARANCE_POSITION, sg, gtk_box_pack_start(GTK_BOX(frame), option, FALSE, FALSE, 0); label = pidgin_prefs_dropdown(frame, _("_Stack:"), GAIM_PREF_BOOLEAN, GF_PREF_APPEARANCE_VERTICAL, _("Horizontally"), FALSE, gtk_misc_set_alignment(GTK_MISC(label), 0, 0); gtk_size_group_add_widget(sg, label); label = pidgin_prefs_dropdown(frame, _("Show _while away:"), GF_PREF_BEHAVIOR_SHOW_WHILE_AWAY, gtk_misc_set_alignment(GTK_MISC(label), 0, 0); gtk_size_group_add_widget(sg, label); label = pidgin_prefs_dropdown(frame, _("_Animate:"), GAIM_PREF_BOOLEAN, GF_PREF_APPEARANCE_ANIMATE, gtk_misc_set_alignment(GTK_MISC(label), 0, 0); gtk_size_group_add_widget(sg, label); spin = pidgin_prefs_labeled_spin_button(frame, _("_Display Time:"), GF_PREF_BEHAVIOR_DISPLAY_TIME, label = make_label(_("seconds"), NULL); gtk_box_pack_start(GTK_BOX(spin), label, FALSE, FALSE, 0); frame = pidgin_make_frame(vbox, _("Mouse")); option = make_mouse_option_menu(_("_Left:"), GF_PREF_MOUSE_LEFT, sg); gtk_box_pack_start(GTK_BOX(frame), option, FALSE, FALSE, 0); option = make_mouse_option_menu(_("_Middle:"), GF_PREF_MOUSE_MIDDLE, sg); gtk_box_pack_start(GTK_BOX(frame), option, FALSE, FALSE, 0); option = make_mouse_option_menu(_("_Right:"), GF_PREF_MOUSE_RIGHT, sg); gtk_box_pack_start(GTK_BOX(frame), option, FALSE, FALSE, 0); /******************************************************************************* * Notification page stuff ******************************************************************************/ notification_sort_show(GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gboolean a_show = FALSE, b_show = FALSE; gtk_tree_model_get(model, a, GF_NOTIF_COL_SHOW, &a_show, -1); gtk_tree_model_get(model, b, GF_NOTIF_COL_SHOW, &b_show, -1); else if(!a_show && b_show) notification_sort_name(GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gchar *a_name = NULL, *b_name = NULL; gchar *a_ckey = NULL, *b_ckey = NULL; gtk_tree_model_get(model, a, GF_NOTIF_COL_NAME, &a_name, -1); gtk_tree_model_get(model, b, GF_NOTIF_COL_NAME, &b_name, -1); a_ckey = g_utf8_collate_key(a_name, g_utf8_strlen(a_name, -1)); b_ckey = g_utf8_collate_key(b_name, g_utf8_strlen(b_name, -1)); ret = strcmp(a_ckey, b_ckey); notification_sort_desc(GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gchar *a_desc = NULL, *b_desc = NULL; gchar *a_ckey = NULL, *b_ckey = NULL; gtk_tree_model_get(model, a, GF_NOTIF_COL_DESCRIPTION, &a_desc, -1); gtk_tree_model_get(model, b, GF_NOTIF_COL_DESCRIPTION, &b_desc, -1); a_ckey = g_utf8_collate_key(a_desc, g_utf8_strlen(a_desc, -1)); b_ckey = g_utf8_collate_key(b_desc, g_utf8_strlen(b_desc, -1)); ret = strcmp(a_ckey, b_ckey); notification_show_cb(GtkCellRendererToggle *renderer, gchar *path, GtkListStore *store = (GtkListStore *)data; gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(store), &iter, path); gtk_tree_model_get(GTK_TREE_MODEL(store), &iter, GF_NOTIF_COL_SHOW, &show, GF_NOTIF_COL_TYPE, &type, event = gf_event_find_for_notification(type); gf_event_set_show(event, !show); gtk_list_store_set(store, &iter, GF_NOTIF_COL_SHOW, !show, make_notification_list(GtkBox *parent) { GtkTreeSortable *sortable; GtkCellRenderer *renderer; sw = gtk_scrolled_window_new(NULL, NULL); gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw), GTK_SHADOW_IN); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_box_pack_start(parent, sw, TRUE, TRUE, 0); store = gtk_list_store_new(4, G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_STRING, for(events = gf_events_get(); events; events = events->next) { event = GF_EVENT(events->data); type = gf_event_get_notification_type(event); if(type && type[0] == '!') gtk_list_store_append(store, &iter); gtk_list_store_set(store, &iter, GF_NOTIF_COL_SHOW, gf_event_show_notification(type), GF_NOTIF_COL_NAME, gf_event_get_name(event), GF_NOTIF_COL_DESCRIPTION, gf_event_get_description(event), sortable = GTK_TREE_SORTABLE(store); gtk_tree_sortable_set_sort_func(sortable, GF_NOTIF_COL_SHOW, notification_sort_show, NULL, NULL); gtk_tree_sortable_set_sort_func(sortable, GF_NOTIF_COL_NAME, notification_sort_name, NULL, NULL); gtk_tree_sortable_set_sort_func(sortable, GF_NOTIF_COL_DESCRIPTION, notification_sort_desc, NULL, NULL); gtk_tree_sortable_set_sort_column_id(sortable, GF_NOTIF_COL_NAME, list = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)); gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(list), TRUE); gtk_widget_set_size_request(list, -1, 150); gtk_container_add(GTK_CONTAINER(sw), list); renderer = gtk_cell_renderer_toggle_new(); g_signal_connect(G_OBJECT(renderer), "toggled", G_CALLBACK(notification_show_cb), store); col = gtk_tree_view_column_new_with_attributes(_("Show"), renderer, gtk_tree_view_column_set_sort_column_id(col, GF_NOTIF_COL_SHOW); gtk_tree_view_append_column(GTK_TREE_VIEW(list), col); renderer = gtk_cell_renderer_text_new(); col = gtk_tree_view_column_new_with_attributes(_("Event"), renderer, gtk_tree_view_column_set_sort_column_id(col, GF_NOTIF_COL_NAME); gtk_tree_view_append_column(GTK_TREE_VIEW(list), col); renderer = gtk_cell_renderer_text_new(); col = gtk_tree_view_column_new_with_attributes(_("Description"), renderer, gtk_tree_view_column_set_sort_column_id(col, GF_NOTIF_COL_DESCRIPTION); gtk_tree_view_append_column(GTK_TREE_VIEW(list), col); make_notifications_page(GtkWidget *notebook) { vbox = make_notebook_page(GTK_NOTEBOOK(notebook), _("Notifications"), -1); make_notification_list(GTK_BOX(vbox)); /******************************************************************************* ******************************************************************************/ GtkWidget *theme_refresh; GtkWidget *theme_get_more; GtkWidget *theme_version; GtkWidget *theme_description; GtkWidget *theme_website; GtkWidget *theme_supports; GtkWidget *theme_filename; static struct GfThemeListData theme_data; static struct ThemeInfoPane theme_info_pane; theme_sort_loaded(GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gboolean a_loaded = FALSE, b_loaded = FALSE; gtk_tree_model_get(model, a, GF_THEME_COL_LOADED, &a_loaded, -1); gtk_tree_model_get(model, b, GF_THEME_COL_LOADED, &b_loaded, -1); if(a_loaded && !b_loaded) else if(!a_loaded && b_loaded) theme_sort_name(GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gchar *a_name = NULL, *b_name = NULL; gchar *a_ckey = NULL, *b_ckey = NULL; gtk_tree_model_get(model, a, GF_THEME_COL_NAME, &a_name, -1); gtk_tree_model_get(model, b, GF_THEME_COL_NAME, &b_name, -1); else if(!a_name && b_name) a_ckey = g_utf8_collate_key(a_name, g_utf8_strlen(a_name, -1)); b_ckey = g_utf8_collate_key(b_name, g_utf8_strlen(b_name, -1)); ret = strcmp(a_ckey, b_ckey); theme_sort_summary(GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gchar *a_summ = NULL, *b_summ = NULL; gchar *a_ckey = NULL, *b_ckey = NULL; gtk_tree_model_get(model, a, GF_THEME_COL_SUMMARY, &a_summ, -1); gtk_tree_model_get(model, b, GF_THEME_COL_SUMMARY, &b_summ, -1); else if(!a_summ && b_summ) a_ckey = g_utf8_collate_key(a_summ, g_utf8_strlen(a_summ, -1)); b_ckey = g_utf8_collate_key(b_summ, g_utf8_strlen(b_summ, -1)); ret = strcmp(a_ckey, b_ckey); theme_install_theme(char *path, char *extn) { gchar *command, *escaped; /* I dont know what you are, get out of here */ else if ((tail = strrchr(path, '.')) == NULL) destdir = g_build_filename(gaim_user_dir(), "guifications", "themes", NULL); /* We'll check this just to make sure. This also lets us do something * different on other platforms, if need be */ if (!g_ascii_strcasecmp(tail, ".gz") || !g_ascii_strcasecmp(tail, ".tgz")) { escaped = g_shell_quote(path); command = g_strdup_printf("tar > /dev/null xzf %s -C %s", escaped, destdir); if(!gtkwgaim_gz_untar(path, destdir)) { gf_preferences_refresh_themes_list(); theme_got_url(GaimUtilFetchUrlData *url_data, void *data, const char *themedata, size_t len, const gchar *err_msg) f = gaim_mkstemp(&path, FALSE); fwrite(themedata, len, 1, f); theme_install_theme(path, data); theme_dnd_recv(GtkWidget *widget, GdkDragContext *dc, guint x, guint y, GtkSelectionData *sd, guint info, guint t, gpointer data) { gchar *name = (gchar *)sd->data; if ((sd->length >= 0) && (sd->format == 8)) { /* Well, it looks like the drag event was cool. * Let's do something with it */ if (!g_ascii_strncasecmp(name, "file://", 7)) { /* It looks like we're dealing with a local file. Let's * just untar it in the right place */ if(!(tmp = g_filename_from_uri(name, NULL, &converr))) { gaim_debug_error("guifications", "theme dnd %s\n", (converr ? converr->message : "g_filename_from_uri error")); theme_install_theme(tmp, NULL); } else if (!g_ascii_strncasecmp(name, "http://", 7)) { /* Oo, a web drag and drop. This is where things * will start to get interesting */ if ((tail = strrchr(name, '.')) == NULL) /* We'll check this just to make sure. This also lets us do something different on * other platforms, if need be */ /* Q: shouldn't tgz be tail? */ gaim_util_fetch_url(name, TRUE, NULL, FALSE, theme_got_url, ".tgz"); gtk_drag_finish(dc, TRUE, FALSE, t); gtk_drag_finish(dc, FALSE, FALSE, t); theme_load_cb(GtkCellRendererToggle *renderer, gchar *path, gpointer data) { gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(theme_data.store), gtk_tree_model_get(GTK_TREE_MODEL(theme_data.store), &iter, GF_THEME_COL_LOADED, &loaded, GF_THEME_COL_FILE, &filename, theme = gf_theme_find_theme_by_filename(filename); gtk_list_store_set(theme_data.store, &iter, GF_THEME_COL_LOADED, !loaded, theme_list_selection_cb(GtkTreeSelection *selection, gpointer data) { gchar *name = NULL, *version = NULL, *description = NULL; gchar *author = NULL, *website = NULL, *filename = NULL; if(gtk_tree_selection_get_selected(selection, &model, &iter)) { gtk_tree_model_get(model, &iter, GF_THEME_COL_NAME, &name, GF_THEME_COL_VERSION, &version, GF_THEME_COL_DESCRIPTION, &description, GF_THEME_COL_AUTHOR, &author, GF_THEME_COL_WEBSITE, &website, GF_THEME_COL_FILE, &filename, GF_THEME_COL_SUPPORTS, &supports, if(!gf_file_access(filename, W_OK)) { gtk_widget_set_sensitive(theme_data.theme_edit, TRUE); gtk_widget_set_sensitive(theme_data.theme_delete, TRUE); gtk_widget_set_sensitive(theme_data.theme_edit, FALSE); gtk_widget_set_sensitive(theme_data.theme_delete, FALSE); gtk_widget_set_sensitive(theme_data.theme_copy, TRUE); gtk_widget_set_sensitive(theme_data.theme_copy, FALSE); gtk_label_set_text(GTK_LABEL(theme_info_pane.theme_name), name); gtk_label_set_text(GTK_LABEL(theme_info_pane.theme_version), version); gtk_label_set_text(GTK_LABEL(theme_info_pane.theme_description), description); gtk_label_set_text(GTK_LABEL(theme_info_pane.theme_author), author); gtk_label_set_text(GTK_LABEL(theme_info_pane.theme_website), website); gtk_label_set_text(GTK_LABEL(theme_info_pane.theme_supports), supports); gtk_label_set_text(GTK_LABEL(theme_info_pane.theme_filename), filename); GtkTreeSortable *sortable; gboolean loaded = FALSE, destroy; gaim_debug_info("Guifications", "probes refreshed\n"); store = gtk_list_store_new(9, G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING); for(l = gf_themes_get_all(); l; l = l->next) { gtk_list_store_append(store, &iter); loaded = gf_theme_is_loaded(l->data); /* set the filename and if it's loaded */ gtk_list_store_set(store, &iter, GF_THEME_COL_FILE, l->data, GF_THEME_COL_LOADED, loaded, theme = gf_theme_find_theme_by_filename(l->data); theme = gf_theme_new_from_file(l->data); info = gf_theme_get_theme_info(theme); supports = gf_theme_get_supported_notifications(theme); gtk_list_store_set(store, &iter, GF_THEME_COL_NAME, gf_theme_info_get_name(info), GF_THEME_COL_VERSION, gf_theme_info_get_version(info), GF_THEME_COL_SUMMARY, gf_theme_info_get_summary(info), GF_THEME_COL_DESCRIPTION, gf_theme_info_get_description(info), GF_THEME_COL_AUTHOR, gf_theme_info_get_author(info), GF_THEME_COL_WEBSITE, gf_theme_info_get_website(info), GF_THEME_COL_SUPPORTS, supports, sortable = GTK_TREE_SORTABLE(store); gtk_tree_sortable_set_sort_func(sortable, GF_THEME_COL_LOADED, theme_sort_loaded, NULL, NULL); gtk_tree_sortable_set_sort_func(sortable, GF_THEME_COL_NAME, theme_sort_name, NULL, NULL); gtk_tree_sortable_set_sort_func(sortable, GF_THEME_COL_SUMMARY, theme_sort_summary, NULL, NULL); gtk_tree_sortable_set_sort_column_id(sortable, GF_THEME_COL_NAME, gtk_tree_view_set_model(GTK_TREE_VIEW(theme_data.tree), NULL); gtk_list_store_clear(theme_data.store); g_object_unref(G_OBJECT(theme_data.store)); theme_data.store = create_theme_store(); gtk_tree_view_set_model(GTK_TREE_VIEW(theme_data.tree), GTK_TREE_MODEL(theme_data.store)); gtk_tree_model_get_iter_first(GTK_TREE_MODEL(theme_data.store), &iter); sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(GTK_TREE_VIEW(theme_data.tree))); gtk_tree_selection_select_iter(sel, &iter); theme_list_refresh_cb(GtkWidget *w, gpointer data) { gf_preferences_refresh_themes_list(); theme_list_new_cb(GtkWidget *w, gpointer data) { gf_theme_editor_show(NULL); theme_list_edit_cb(GtkWidget *w, gpointer data) { sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(theme_data.tree)); gtk_tree_selection_get_selected(sel, &model, &iter); gtk_tree_model_get(model, &iter, GF_THEME_COL_FILE, &filename, -1); gf_theme_editor_show(filename); theme_list_delete_yes_cb(gpointer data, gint id) { if(gf_theme_is_loaded(filename)) gf_theme_unload(gf_theme_find_theme_by_filename(filename)); path = g_path_get_dirname(filename); gf_file_remove_dir(path); gf_preferences_refresh_themes_list(); theme_list_delete_no_cb(gpointer data, gint id) { gchar *filename = (char *)data; theme_list_delete_cb(GtkWidget *w, gpointer data) { sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(theme_data.tree)); if(gtk_tree_selection_get_selected(sel, &model, &iter)) gtk_tree_model_get(model, &iter, GF_THEME_COL_FILE, &filename, -1); gaim_request_yes_no(guifications, _("Delete theme?"), NULL, _("Are you sure you want to delete this theme?"), G_CALLBACK(theme_list_delete_yes_cb), G_CALLBACK(theme_list_delete_no_cb)); theme_list_copy_cb(GtkWidget *w, gpointer data) { gchar *filename, *newname, *fullname, *oldpath, *newpath, *dir; sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(theme_data.tree)); if(gtk_tree_selection_get_selected(sel, &model, &iter)) gtk_tree_model_get(model, &iter, GF_THEME_COL_FILE, &filename, -1); theme = gf_theme_new_from_file(filename); info = gf_theme_get_theme_info(theme); oldname = gf_theme_info_get_name(info); newname = g_strdup_printf("%s (copy)", oldname); newname = g_strdup("untitled (copy)"); gf_theme_info_set_name(info, newname); dir = gf_theme_info_strip_name(info); newpath = g_build_filename(gaim_user_dir(), "guifications", "themes", gaim_build_dir(newpath, S_IRUSR | S_IWUSR | S_IXUSR); fullname = g_build_filename(newpath, "theme.xml", NULL); /* we copy everything first, and then rewrite theme.xml. Yeah it's not ideal but it oldpath = g_path_get_dirname(filename); gf_file_copy_directory(oldpath, newpath); gf_theme_save_to_file(theme, fullname); theme_list_get_more_cb(GtkWidget *w, gpointer data) { gaim_notify_uri(NULL, "http://sourceforge.net/tracker/?atid=676821&group_id=92888&func=browse"); theme_list_clicked_cb(GtkWidget *w, GdkEventButton *e, gpointer data) { pidgin_new_item_from_stock(menu, _("New"), GTK_STOCK_NEW, G_CALLBACK(theme_list_new_cb), NULL, sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(theme_data.tree)); if(gtk_tree_selection_get_selected(sel, &model, &iter)) { gtk_tree_model_get(model, &iter, GF_THEME_COL_FILE, &filename, -1); if(!gf_file_access(filename, W_OK)) { pidgin_new_item_from_stock(menu, _("Edit"), GTK_STOCK_PREFERENCES, G_CALLBACK(theme_list_edit_cb), pidgin_new_item_from_stock(menu, _("Delete"), GTK_STOCK_DELETE, G_CALLBACK(theme_list_delete_cb), pidgin_new_item_from_stock(menu, _("Refresh"), GTK_STOCK_REFRESH, G_CALLBACK(theme_list_refresh_cb), NULL, gtk_widget_show_all(menu); gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, 3, gtk_get_current_event_time()); make_theme_list(GtkBox *parent) { GtkCellRenderer *renderer; GtkTargetEntry te[3] = {{"text/plain", 0, 0},{"text/uri-list", 0, 1},{"STRING", 0, 2}}; /* scrolled window and tree */ sw = gtk_scrolled_window_new(NULL, NULL); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw), GTK_SHADOW_IN); gtk_box_pack_start(parent, sw, TRUE, TRUE, 0); theme_data.store = create_theme_store(); theme_data.tree = gtk_tree_view_new_with_model(GTK_TREE_MODEL(theme_data.store)); gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(theme_data.tree), TRUE); gtk_widget_set_size_request(theme_data.tree, -1, 150); gtk_container_add(GTK_CONTAINER(sw), theme_data.tree); g_signal_connect(G_OBJECT(theme_data.tree), "button-press-event", G_CALLBACK(theme_list_clicked_cb), NULL); gtk_drag_dest_set(theme_data.tree, GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_HIGHLIGHT | GTK_DEST_DEFAULT_DROP, te, sizeof(te) / sizeof(GtkTargetEntry) , GDK_ACTION_COPY | GDK_ACTION_MOVE); g_signal_connect(G_OBJECT(theme_data.tree), "drag_data_received", G_CALLBACK(theme_dnd_recv), theme_data.store); renderer = gtk_cell_renderer_toggle_new(); g_signal_connect(G_OBJECT(renderer), "toggled", G_CALLBACK(theme_load_cb), NULL); col = gtk_tree_view_column_new_with_attributes(_("Loaded"), renderer, "active", GF_THEME_COL_LOADED, gtk_tree_view_column_set_sort_column_id(col, GF_THEME_COL_LOADED); gtk_tree_view_append_column(GTK_TREE_VIEW(theme_data.tree), col); renderer = gtk_cell_renderer_text_new(); col = gtk_tree_view_column_new_with_attributes(_("Name"), renderer, "text", GF_THEME_COL_NAME, gtk_tree_view_column_set_sort_column_id(col, GF_THEME_COL_NAME); gtk_tree_view_append_column(GTK_TREE_VIEW(theme_data.tree), col); renderer = gtk_cell_renderer_text_new(); col = gtk_tree_view_column_new_with_attributes(_("Summary"), renderer, "text", GF_THEME_COL_SUMMARY, gtk_tree_view_column_set_sort_column_id(col, GF_THEME_COL_SUMMARY); gtk_tree_view_append_column(GTK_TREE_VIEW(theme_data.tree), col); sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(theme_data.tree)); g_signal_connect(G_OBJECT(sel), "changed", G_CALLBACK(theme_list_selection_cb), NULL); /* the new, edit, delete, refresh buttons and get more buttons */ hbox = gtk_hbox_new(FALSE, 4); gtk_box_pack_start(GTK_BOX(parent), hbox, FALSE, FALSE, 0); theme_data.theme_new = gtk_button_new_from_stock(GTK_STOCK_NEW); gtk_button_set_relief(GTK_BUTTON(theme_data.theme_new), GTK_RELIEF_NONE); g_signal_connect(G_OBJECT(theme_data.theme_new), "clicked", G_CALLBACK(theme_list_new_cb), NULL); gtk_box_pack_start(GTK_BOX(hbox), theme_data.theme_new, FALSE, FALSE, 0); pidgin_pixbuf_button_from_stock(_("_Edit"), PIDGIN_BUTTON_HORIZONTAL); gtk_button_set_relief(GTK_BUTTON(theme_data.theme_edit), GTK_RELIEF_NONE); gtk_widget_set_sensitive(theme_data.theme_edit, FALSE); g_signal_connect(G_OBJECT(theme_data.theme_edit), "clicked", G_CALLBACK(theme_list_edit_cb), NULL); gtk_box_pack_start(GTK_BOX(hbox), theme_data.theme_edit, FALSE, FALSE, 0); theme_data.theme_delete = gtk_button_new_from_stock(GTK_STOCK_DELETE); gtk_button_set_relief(GTK_BUTTON(theme_data.theme_delete), GTK_RELIEF_NONE); gtk_widget_set_sensitive(theme_data.theme_delete, FALSE); g_signal_connect(G_OBJECT(theme_data.theme_delete), "clicked", G_CALLBACK(theme_list_delete_cb), NULL); gtk_box_pack_start(GTK_BOX(hbox), theme_data.theme_delete, FALSE, FALSE, 0); theme_data.theme_copy = gtk_button_new_from_stock(GTK_STOCK_COPY); gtk_button_set_relief(GTK_BUTTON(theme_data.theme_copy), GTK_RELIEF_NONE); gtk_widget_set_sensitive(theme_data.theme_copy, FALSE); g_signal_connect(G_OBJECT(theme_data.theme_copy), "clicked", G_CALLBACK(theme_list_copy_cb), NULL); gtk_box_pack_start(GTK_BOX(hbox), theme_data.theme_copy, FALSE, FALSE, 0); theme_data.theme_refresh = gtk_button_new_from_stock(GTK_STOCK_REFRESH); gtk_button_set_relief(GTK_BUTTON(theme_data.theme_refresh), GTK_RELIEF_NONE); g_signal_connect(G_OBJECT(theme_data.theme_refresh), "clicked", G_CALLBACK(theme_list_refresh_cb), NULL); gtk_box_pack_start(GTK_BOX(hbox), theme_data.theme_refresh, FALSE, FALSE, 0); theme_data.theme_get_more = pidgin_pixbuf_button_from_stock(_("_Get More"), PIDGIN_BUTTON_HORIZONTAL); gtk_button_set_relief(GTK_BUTTON(theme_data.theme_get_more), GTK_RELIEF_NONE); g_signal_connect(G_OBJECT(theme_data.theme_get_more), "clicked", G_CALLBACK(theme_list_get_more_cb), NULL); gtk_box_pack_start(GTK_BOX(hbox), theme_data.theme_get_more, FALSE, FALSE, 0); make_theme_page(GtkWidget *notebook) { GtkWidget *sw, *vp, *mbox, *vbox, *hbox, *label; mbox = make_notebook_page(GTK_NOTEBOOK(notebook), _("Themes"), -1); make_theme_list(GTK_BOX(mbox)); sw = gtk_scrolled_window_new(NULL, NULL); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw), GTK_SHADOW_IN); gtk_box_pack_start(GTK_BOX(mbox), sw, TRUE, TRUE, 0); vp = gtk_viewport_new(NULL, NULL); gtk_viewport_set_shadow_type(GTK_VIEWPORT(vp), GTK_SHADOW_NONE); gtk_container_set_border_width(GTK_CONTAINER(vp), 4); gtk_container_add(GTK_CONTAINER(sw), vp); vbox = gtk_vbox_new(FALSE, 0); gtk_container_add(GTK_CONTAINER(vp), vbox); sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL); hbox = gtk_hbox_new(FALSE, 6); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); label = make_bold_label(_("Name"), sg); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); theme_info_pane.theme_name = make_label(NULL, NULL); gtk_label_set_line_wrap(GTK_LABEL(theme_info_pane.theme_name), TRUE); gtk_box_pack_start(GTK_BOX(hbox), theme_info_pane.theme_name, hbox = gtk_hbox_new(FALSE, 6); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); label = make_bold_label(_("Version"), sg); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); theme_info_pane.theme_version = make_label(NULL, NULL); gtk_label_set_line_wrap(GTK_LABEL(theme_info_pane.theme_version), TRUE); gtk_box_pack_start(GTK_BOX(hbox), theme_info_pane.theme_version, hbox = gtk_hbox_new(FALSE, 6); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); label = make_bold_label(_("Description"), sg); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); theme_info_pane.theme_description = make_label(NULL, NULL); gtk_label_set_line_wrap(GTK_LABEL(theme_info_pane.theme_description), TRUE); gtk_box_pack_start(GTK_BOX(hbox), theme_info_pane.theme_description, hbox = gtk_hbox_new(FALSE, 6); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); label = make_bold_label(_("Author"), sg); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); theme_info_pane.theme_author = make_label(NULL, NULL); gtk_label_set_line_wrap(GTK_LABEL(theme_info_pane.theme_author), TRUE); gtk_box_pack_start(GTK_BOX(hbox), theme_info_pane.theme_author, hbox = gtk_hbox_new(FALSE, 6); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); label = make_bold_label(_("Website"), sg); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); theme_info_pane.theme_website = make_label(NULL, NULL); gtk_label_set_line_wrap(GTK_LABEL(theme_info_pane.theme_website), TRUE); gtk_box_pack_start(GTK_BOX(hbox), theme_info_pane.theme_website, hbox = gtk_hbox_new(FALSE, 6); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); label = make_bold_label(_("Supports"), sg); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); theme_info_pane.theme_supports = make_label(NULL, NULL); gtk_label_set_line_wrap(GTK_LABEL(theme_info_pane.theme_supports), TRUE); gtk_box_pack_start(GTK_BOX(hbox), theme_info_pane.theme_supports, hbox = gtk_hbox_new(FALSE, 6); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); label = make_bold_label(_("Filename"), sg); gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); theme_info_pane.theme_filename = make_label(NULL, NULL); gtk_label_set_line_wrap(GTK_LABEL(theme_info_pane.theme_filename), TRUE); gtk_box_pack_start(GTK_BOX(hbox), theme_info_pane.theme_filename, gtk_widget_show_all(mbox); /******************************************************************************* ******************************************************************************/ make_advanced_page(GtkWidget *notebook) { #if GTK_CHECK_VERSION(2,2,0) gint screen_count, monitor_count; sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL); vbox = make_notebook_page(GTK_NOTEBOOK(notebook), _("Advanced"), -1); frame = pidgin_make_frame(vbox, _("Display Options")); pidgin_prefs_labeled_spin_button(frame, _("Max _Visible Guifications:"), GF_PREF_BEHAVIOR_THROTTLE, #if GTK_CHECK_VERSION(2,2,0) screen_count = gf_display_get_screen_count(); monitor_count = gf_display_get_monitor_count(); if(screen_count > 0 || monitor_count > 0) { frame = pidgin_make_frame(vbox, _("Placement")); pidgin_prefs_labeled_spin_button(frame, _("Show notifications on _screen:"), pidgin_prefs_labeled_spin_button(frame, _("Show notifications on _monitor:"), GF_PREF_ADVANCED_MONITOR, #endif /* GTK_CHECK_VERSION(2,2,0) */ gtk_widget_show_all(vbox); /******************************************************************************* ******************************************************************************/ gf_preferences_notebook_destroy_cb(GtkObject *obj, gpointer data) { /******************************************************************************* ******************************************************************************/ gf_preferences_get_frame(GaimPlugin *plugin) { notebook = gtk_notebook_new(); g_signal_connect(GTK_OBJECT(notebook), "destroy", G_CALLBACK(gf_preferences_notebook_destroy_cb), NULL); gtk_widget_show(notebook); make_general_page(notebook); make_notifications_page(notebook); make_theme_page(notebook); make_advanced_page(notebook); gf_preferences_refresh_themes_list() { gaim_prefs_add_none(GF_PREF_ROOT); gaim_prefs_add_none(GF_PREF_PLUGIN_ROOT); gaim_prefs_add_none(GF_PREF_BEHAVIOR_ROOT); gaim_prefs_add_int(GF_PREF_BEHAVIOR_DISPLAY_TIME, 6); gaim_prefs_add_int(GF_PREF_BEHAVIOR_THROTTLE, 6); gaim_prefs_add_bool(GF_PREF_BEHAVIOR_SHOW_WHILE_AWAY, TRUE); gaim_prefs_add_none(GF_PREF_APPEARANCE_ROOT); gaim_prefs_add_int(GF_PREF_APPEARANCE_POSITION, GF_DISPLAY_POSITION_SE); gaim_prefs_add_bool(GF_PREF_APPEARANCE_VERTICAL, TRUE); gaim_prefs_add_bool(GF_PREF_APPEARANCE_ANIMATE, TRUE); gaim_prefs_add_none(GF_PREF_MOUSE_ROOT); gaim_prefs_add_string(GF_PREF_MOUSE_LEFT, "open"); gaim_prefs_add_string(GF_PREF_MOUSE_MIDDLE, "close"); gaim_prefs_add_string(GF_PREF_MOUSE_RIGHT, "context"); def_theme = g_build_filename(DATADIR, "pixmaps", "gaim", "guifications", "themes", "default", "theme.xml", NULL); l = g_list_append(l, def_theme); gaim_prefs_add_string_list(GF_PREF_LOADED_THEMES, l); gaim_prefs_add_none(GF_PREF_ADVANCED_ROOT); gaim_prefs_add_bool(GF_PREF_ADVANCED_RELEASE_NOTIFICATION, TRUE); gaim_prefs_add_int(GF_PREF_ADVANCED_RELEASE_LAST_CHECK, 0); #if GTK_CHECK_VERSION(2,2,0) gaim_prefs_add_int(GF_PREF_ADVANCED_SCREEN, 0); gaim_prefs_add_int(GF_PREF_ADVANCED_MONITOR, 0); if(gaim_prefs_get_int(GF_PREF_ADVANCED_SCREEN) > gf_display_get_screen_count()) gaim_prefs_set_int(GF_PREF_ADVANCED_SCREEN, gf_display_get_default_screen()); if(gaim_prefs_get_int(GF_PREF_ADVANCED_MONITOR) > gf_display_get_monitor_count()) gaim_prefs_set_int(GF_PREF_ADVANCED_MONITOR, gf_display_get_default_monitor()); #endif /* GTK_CHECK_VERSION(2,2,0) */ /* clean up old prefs if they exist */ gaim_prefs_remove("/plugins/gtk/amc_grim/guifications2/behavior/show_during_screen_saver"); gaim_prefs_remove("/plugins/gtk/amc_grim/guifications2/appearance/h_offset"); gaim_prefs_remove("/plugins/gtk/amc_grim/guifications2/appearance/v_offset"); gaim_prefs_remove("/plugins/gtk/amc_grim/guifications2/appearance/zoom"); gaim_prefs_remove("/plugins/gtk/amc_grim/guifications2/appearance/show_contacts"); gaim_prefs_remove("/plugins/gtk/amc_grim/guifications2/appearance/alias"); gaim_prefs_remove("/plugins/gtk/amc_grim/guifications2/advanced/sign_on_delay"); gaim_prefs_remove("/plugins/gtk/amc_grim/guifications2/advanced/hide_joinleave"); gaim_prefs_remove("/plugins/gtk/amc_grim/guifications2/advanced/hide_conv_focused");