* 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_item_icon.h" #include "gf_item_image.h" #include "gf_item_offset.h" #include "gf_item_text.h" #include "gf_notification.h" #include "gf_preferences.h" #include "gf_theme_editor.h" #include "gf_theme_info.h" #include "gf_theme_ops.h" /* Okay, heres the run down of how all of this works. * The theme is loaded and then converted into a GtkTreeStore. The store holds, * the title of what to display in the tree view, as well as what page to * display when it's selected, as well as the object itself. * The getters and setters are added as data to the widget at creation time. * This way when we hit the callback, we grab the item from the store, and pop * it into the getter or setter function, update accordingly, and go about our struct GfThemeEditorInfo { struct GfThemeEditorOps { struct GfThemeEditorNotification { struct GfThemeEditorItem { struct GfThemeEditorIcon { struct GfThemeEditorItem item; struct GfThemeEditorImage { struct GfThemeEditorItem item; struct GfThemeEditorText { struct GfThemeEditorItem item; GtkWidget *tool_notification; struct GfThemeEditorInfo info; struct GfThemeEditorOps ops; struct GfThemeEditorNotification notification; struct GfThemeEditorIcon icon; struct GfThemeEditorImage image; struct GfThemeEditorText text; struct GfteNewNotification { typedef void (*GfteSetFunc)(gpointer obj, gconstpointer val); typedef gconstpointer (*GfteGetFunc)(gpointer obj); /******************************************************************************* ******************************************************************************/ static void gfte_selection_changed_cb(GtkTreeSelection *sel, gpointer data); /******************************************************************************* ******************************************************************************/ PurplePlugin *plugin_handle = NULL; gpointer image_dialog = NULL; GtkWidget *opt_dialog = NULL; struct GfThemeEditor editor; struct GfteModified modified; struct GfteDelete del_obj; struct GfteNewNotification new_notification; struct GfteNewItem new_item; /******************************************************************************* ******************************************************************************/ gfte_toolbar_buttons_update(gboolean item, gboolean copy, gboolean delete, gboolean up, gboolean down) gtk_widget_set_sensitive(editor.tool_item, item); gtk_widget_set_sensitive(editor.tool_copy, copy); gtk_widget_set_sensitive(editor.tool_delete, delete); gtk_widget_set_sensitive(editor.tool_up, up); gtk_widget_set_sensitive(editor.tool_down, down); /******************************************************************************* * Main stuff thats used all over the place ******************************************************************************/ name = g_path_get_basename(editor.path); if(name && name[0] == '.') gf_file_remove_dir(editor.path); gchar *path, *oldpath, *dir; loaded = gf_theme_is_loaded(editor.filename); GfTheme *theme = gf_theme_find_theme_by_filename(editor.filename); gf_theme_save_to_file(editor.theme, editor.filename); dir = gf_theme_strip_name(editor.theme); oldpath = g_path_get_dirname(editor.path); /* ok, because windows is retarded, and everyone can edit everything, we get to take * the editor's path, remove the last part of it, and then attach the new dir name to path = g_build_filename(oldpath, dir, NULL); g_rename(editor.path, path); /* update the editor's path */ /* update the editor's file */ editor.filename = g_build_filename(editor.path, "theme.xml", NULL); /* reprobe the theme and tell the prefs to refresh it.. */ gf_theme_probe(editor.filename); gf_theme_load(editor.filename); gf_preferences_refresh_themes_list(); gfte_store_add(GtkTreeStore *store, GtkTreeIter *child, GtkTreeIter *parent, const gchar *title, gint page, gpointer data) gtk_tree_store_append(store, child, parent); gtk_tree_store_set(store, child, GfNotification *notification; GtkTreeIter parent, child, iter; store = gtk_tree_store_new(GFTE_STORE_TOTAL, G_TYPE_STRING, G_TYPE_INT, gfte_store_add(store, &parent, NULL, _("Theme"), GFTE_PAGE_THEME, editor.theme); info = gf_theme_get_theme_info(editor.theme); gfte_store_add(store, &child, &parent, _("Info"), GFTE_PAGE_INFO, info); ops = gf_theme_get_theme_options(editor.theme); gfte_store_add(store, &child, &parent, _("Options"), GFTE_PAGE_OPS, ops); for(n = gf_theme_get_notifications(editor.theme); n; n = n->next) { const gchar *alias = NULL, *name = NULL; notification = GF_NOTIFICATION(n->data); if((alias = gf_notification_get_alias(notification))) type = gf_notification_get_type(notification); event = gf_event_find_for_notification(type); name = gf_event_get_name(event); gfte_store_add(store, &child, &parent, name, GFTE_PAGE_NOTIFICATION, notification); for(i = gf_notification_get_items(notification); i; i = i->next) { type = gf_item_get_type(item); case GF_ITEM_TYPE_UNKNOWN: gfte_store_add(store, &iter, &child, gf_item_type_to_string(type, TRUE), /* This was yanked from gtk 2.4.x, it's a wrapper to support this function on gtk 2.0 */ gfte_tree_view_expand_to_path(GtkTreeView *tree, GtkTreePath *path) { #if GTK_CHECK_VERSION(2,2,0) gtk_tree_view_expand_to_path(tree, path); g_return_if_fail(GTK_IS_TREE_VIEW(tree)); g_return_if_fail(path != NULL); depth = gtk_tree_path_get_depth(path); indices = gtk_tree_path_get_indices(path); tmp = gtk_tree_path_new(); g_return_if_fail(tmp != NULL); for(i = 0; i < depth; i++) { gtk_tree_path_append_index(tmp, indices[i]); gtk_tree_view_expand_row(tree, tmp, FALSE); gfte_store_select_iter(GtkTreeIter *iter) { model = gtk_tree_view_get_model(GTK_TREE_VIEW(editor.tree)); path = gtk_tree_model_get_path(model, iter); gfte_tree_view_expand_to_path(GTK_TREE_VIEW(editor.tree), path); gtk_tree_path_free(path); sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(editor.tree)); gtk_tree_selection_select_iter(sel, iter); dir = g_strdup_printf(".%x", g_random_int()); path = g_build_filename(purple_user_dir(), "guifications", "themes", dir, NULL); g_mkdir(path, S_IRUSR | S_IWUSR | S_IXUSR); gfte_setup(const gchar *filename) { GfTheme *old = editor.theme; GfNotification *notification; editor.theme = gf_theme_new_from_file(filename); for(l = gf_theme_get_notifications(editor.theme); l; l = l->next) { notification = GF_NOTIFICATION(l->data); GfNotification *master = NULL; editor.theme = gf_theme_new(); gf_theme_set_theme_info(editor.theme, gf_theme_info_new()); gf_theme_set_theme_options(editor.theme, gf_theme_options_new()); master = gf_notification_new(editor.theme); gf_notification_set_type(master, GF_NOTIFICATION_MASTER); gf_theme_add_notification(editor.theme, master); editor.filename = g_strdup(filename); path = gfte_make_temp_dir(); editor.filename = g_build_filename(path, "theme.xml", NULL); editor.path = g_path_get_dirname(editor.filename); gtk_tree_view_set_model(GTK_TREE_VIEW(editor.tree), NULL); g_object_unref(G_OBJECT(editor.store)); editor.store = gfte_store_update(); gtk_tree_view_set_model(GTK_TREE_VIEW(editor.tree), GTK_TREE_MODEL(editor.store)); gtk_tree_view_expand_all(GTK_TREE_VIEW(editor.tree)); gtk_tree_model_get_iter_first(GTK_TREE_MODEL(editor.store), &iter); gfte_store_select_iter(&iter); gtk_widget_destroy(del_obj.window); if(new_notification.window) { gtk_widget_destroy(new_notification.window); new_notification.window = NULL; gtk_widget_destroy(new_item.window); gtk_widget_destroy(modified.window); g_free(modified.filename); modified.filename = NULL; purple_request_close(PURPLE_REQUEST_FILE, image_dialog); gtk_widget_destroy(opt_dialog); gf_theme_unload(editor.theme); dir = g_path_get_basename(editor.path); if(dir && dir[0] == '.') { gf_file_remove_dir(editor.path); g_object_unref(G_OBJECT(editor.store)); g_object_unref(G_OBJECT(editor.tooltips)); /******************************************************************************* ******************************************************************************/ gfte_store_get_row(GtkTreeIter *iter, gint *page, gchar **title) { sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(editor.tree)); if(!gtk_tree_selection_get_selected(sel, &model, iter)) gtk_tree_model_get(model, iter, GFTE_STORE_OBJECT, &object, /******************************************************************************* ******************************************************************************/ gfte_modified_deleted_cb(GtkWidget *w, GdkEvent *e, gpointer data) { g_free(modified.filename); modified.filename = NULL; gfte_modified_cancel_cb(GtkButton *button, gpointer data) { gtk_widget_destroy(modified.window); g_free(modified.filename); modified.filename = NULL; gfte_modified_no_cb(GtkButton *button, gpointer data) { gtk_widget_destroy(modified.window); case GFTE_MODIFIED_CLOSE: gtk_widget_destroy(editor.window); gfte_setup(modified.filename); g_free(modified.filename); modified.filename = NULL; case GFTE_MODIFIED_TOTAL: gfte_modified_yes_cb(GtkButton *button, gpointer data) { gtk_widget_destroy(modified.window); case GFTE_MODIFIED_CLOSE: gtk_widget_destroy(editor.window); gfte_setup(modified.filename); g_free(modified.filename); modified.filename = NULL; case GFTE_MODIFIED_TOTAL: gfte_modified_show(gint type, const gchar *filename) { GtkWidget *vbox, *hbox, *widget; gtk_widget_show(modified.window); if(type == GFTE_MODIFIED_CLOSE) label = g_strdup(_("Would you like to save before closing?")); else if(type == GFTE_MODIFIED_NEW) label = g_strdup(_("Would you like to save before creating a new theme?")); else if(type == GFTE_MODIFIED_OPEN) label = g_strdup_printf(_("Would you like to save before opening %s?"), modified.filename = g_strdup(filename); modified.window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(modified.window), _("Confirm")); gtk_window_set_resizable(GTK_WINDOW(modified.window), FALSE); gtk_container_set_border_width(GTK_CONTAINER(modified.window), 12); g_signal_connect(G_OBJECT(modified.window), "delete-event", G_CALLBACK(gfte_modified_deleted_cb), NULL); vbox = gtk_vbox_new(FALSE, 4); gtk_container_add(GTK_CONTAINER(modified.window), vbox); widget = gtk_label_new(label); gtk_label_set_line_wrap(GTK_LABEL(widget), TRUE); gtk_box_pack_start(GTK_BOX(vbox), widget, FALSE, FALSE, 0); widget = gtk_hseparator_new(); gtk_box_pack_start(GTK_BOX(vbox), widget, FALSE, FALSE, 0); hbox = gtk_hbox_new(FALSE, 4); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); widget = gtk_button_new_from_stock(GTK_STOCK_YES); g_signal_connect(G_OBJECT(widget), "clicked", G_CALLBACK(gfte_modified_yes_cb), NULL); gtk_box_pack_end(GTK_BOX(hbox), widget, FALSE, FALSE, 0); widget = gtk_button_new_from_stock(GTK_STOCK_NO); g_signal_connect(G_OBJECT(widget), "clicked", G_CALLBACK(gfte_modified_no_cb), NULL); gtk_box_pack_end(GTK_BOX(hbox), widget, FALSE, FALSE, 0); widget = gtk_button_new_from_stock(GTK_STOCK_CANCEL); g_signal_connect(G_OBJECT(widget), "clicked", G_CALLBACK(gfte_modified_cancel_cb), NULL); gtk_box_pack_end(GTK_BOX(hbox), widget, FALSE, FALSE, 0); gtk_widget_show_all(modified.window); /******************************************************************************* ******************************************************************************/ gfte_delete_deleted_cb(GtkWidget *w, GdkEvent *e, gpointer data) { gfte_delete_no_cb(GtkButton *button, gpointer data) { gtk_widget_destroy(del_obj.window); gfte_delete_yes_cb(GtkButton *button, gpointer data) { obj = gfte_store_get_row(&iter, &page, &title); gtk_widget_destroy(del_obj.window); if(page == GFTE_PAGE_NOTIFICATION) { GfTheme *theme = gf_notification_get_theme(GF_NOTIFICATION(obj)); gf_theme_remove_notification(theme, GF_NOTIFICATION(obj)); gf_notification_destroy(GF_NOTIFICATION(obj)); gtk_tree_store_remove(editor.store, &iter); } else if(page == GFTE_PAGE_ICON || page == GFTE_PAGE_IMAGE || GfNotification *notification = gf_item_get_notification(GF_ITEM(obj)); gf_notification_remove_item(notification, GF_ITEM(obj)); gf_item_destroy(GF_ITEM(obj)); gtk_tree_store_remove(editor.store, &iter); gtk_widget_destroy(del_obj.window); gfte_toolbar_buttons_update(FALSE, FALSE, FALSE, FALSE, FALSE); gfte_delete_show(GtkButton *button, gpointer data) { GtkWidget *vbox, *hbox, *widget; gchar *item, *title, *label; gtk_widget_show(del_obj.window); gfte_store_get_row(&iter, &page, &item); if(page == GFTE_PAGE_NOTIFICATION) { label = g_strdup_printf(_("Are you sure you want to delete this %s notification?"), title = g_strdup(_("Confirm delete notification")); } else if(page == GFTE_PAGE_ICON || page == GFTE_PAGE_IMAGE || label = g_strdup_printf(_("Are you sure you want to delete this %s item?"), title = g_strdup(_("Confirm delete item")); gtk_widget_destroy(del_obj.window); del_obj.window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(del_obj.window), title); gtk_window_set_resizable(GTK_WINDOW(del_obj.window), FALSE); gtk_container_set_border_width(GTK_CONTAINER(del_obj.window), 12); g_signal_connect(G_OBJECT(del_obj.window), "delete-event", G_CALLBACK(gfte_delete_deleted_cb), NULL); vbox = gtk_vbox_new(FALSE, 4); gtk_container_add(GTK_CONTAINER(del_obj.window), vbox); widget = gtk_label_new(label); gtk_box_pack_start(GTK_BOX(vbox), widget, FALSE, FALSE, 0); widget = gtk_hseparator_new(); gtk_box_pack_start(GTK_BOX(vbox), widget, FALSE, FALSE, 0); hbox = gtk_hbox_new(FALSE, 4); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); widget = gtk_button_new_from_stock(GTK_STOCK_YES); g_signal_connect(G_OBJECT(widget), "clicked", G_CALLBACK(gfte_delete_yes_cb), NULL); gtk_box_pack_end(GTK_BOX(hbox), widget, FALSE, FALSE, 0); widget = gtk_button_new_from_stock(GTK_STOCK_NO); g_signal_connect(G_OBJECT(widget), "clicked", G_CALLBACK(gfte_delete_no_cb), NULL); gtk_box_pack_end(GTK_BOX(hbox), widget, FALSE, FALSE, 0); gtk_widget_show_all(del_obj.window); /******************************************************************************* ******************************************************************************/ gfte_new_notification_deleted_cb(GtkWidget *w, GdkEvent *e, gpointer data) { new_notification.window = NULL; gfte_new_notification_cancel_cb(GtkButton *button, gpointer data) { gtk_widget_destroy(new_notification.window); new_notification.window = NULL; gfte_new_notification_ok_cb(GtkButton *button, gpointer data) { GfNotification *notification, *master; GtkTreeIter parent, child; gtk_tree_model_get_iter_first(GTK_TREE_MODEL(editor.store), &parent); gtk_tree_model_get(GTK_TREE_MODEL(editor.store), &parent, GFTE_STORE_OBJECT, &object, purple_debug_misc("guifications", "ouch, I don't know where to put this, aborting\n"); if(new_notification.window) gtk_widget_destroy(new_notification.window); new_notification.window = NULL; /* find the notification type, this really needs to get cleaned up but works for now hist = gtk_option_menu_get_history(GTK_OPTION_MENU(new_notification.type)); n_type = gf_events_get_nth_notification(hist); if(!g_utf8_collate(n_type, GF_NOTIFICATION_MASTER)) master = gf_theme_get_master(editor.theme); notification = gf_notification_new(GF_THEME(object)); notification = gf_notification_copy(master); /* create the notification */ gf_notification_set_type(notification, n_type); /* add it to the theme */ gf_theme_add_notification(GF_THEME(object), notification); /* add it to the store */ gfte_store_add(editor.store, &child, &parent, gf_events_get_nth_name(hist), gfte_store_select_iter(&child); for(l = gf_notification_get_items(notification); l; l = l->next) { gint type = gf_item_get_type(GF_ITEM(l->data)); gfte_store_add(editor.store, &item, &child, gf_item_type_to_string(type, TRUE), path = gtk_tree_model_get_path(GTK_TREE_MODEL(editor.store), &child); gtk_tree_view_expand_row(GTK_TREE_VIEW(editor.tree), path, TRUE); gtk_tree_path_free(path); if(new_notification.window) gtk_widget_destroy(new_notification.window); new_notification.window = NULL; gfte_new_notification_show(GtkButton *button, gpointer data) { GtkWidget *vbox, *hbox, *widget, *menu; if(new_notification.window) { gtk_widget_show(new_notification.window); new_notification.window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(new_notification.window), _("New Notification")); gtk_window_set_resizable(GTK_WINDOW(new_notification.window), FALSE); gtk_container_set_border_width(GTK_CONTAINER(new_notification.window), 12); g_signal_connect(G_OBJECT(new_notification.window), "delete-event", G_CALLBACK(gfte_new_notification_deleted_cb), NULL); vbox = gtk_vbox_new(FALSE, 4); gtk_container_add(GTK_CONTAINER(new_notification.window), vbox); hbox = gtk_hbox_new(FALSE, 4); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); widget = gtk_label_new(_("New notification type:")); gtk_box_pack_start(GTK_BOX(hbox), widget, FALSE, FALSE, 0); menu = gf_menu_build(gf_menu_event, editor.theme); new_notification.type = gtk_option_menu_new(); gtk_option_menu_set_menu(GTK_OPTION_MENU(new_notification.type), menu); gtk_box_pack_start(GTK_BOX(hbox), new_notification.type, TRUE, TRUE, 0); widget = gtk_hseparator_new(); gtk_box_pack_start(GTK_BOX(vbox), widget, FALSE, FALSE, 0); hbox = gtk_hbox_new(FALSE, 4); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); widget = gtk_button_new_from_stock(GTK_STOCK_OK); g_signal_connect(G_OBJECT(widget), "clicked", G_CALLBACK(gfte_new_notification_ok_cb), NULL); gtk_box_pack_end(GTK_BOX(hbox), widget, FALSE, FALSE, 0); widget = gtk_button_new_from_stock(GTK_STOCK_CANCEL); g_signal_connect(G_OBJECT(widget), "clicked", G_CALLBACK(gfte_new_notification_cancel_cb), NULL); gtk_box_pack_end(GTK_BOX(hbox), widget, FALSE, FALSE, 0); gtk_widget_show_all(new_notification.window); /******************************************************************************* ******************************************************************************/ gfte_new_item_deleted_cb(GtkWidget *w, GdkEvent *e, gpointer data) { gfte_new_item_cancel_cb(GtkButton *button, gpointer data) { gtk_widget_destroy(new_item.window); gfte_new_item_ok_cb(GtkButton *button, gpointer data) { GtkTreeIter parent, child; object = gfte_store_get_row(&parent, &page, &title); /* we have to grab this early in case the selected node is an item, and we select the * notification. If we don't grab this, the selection changes kills all the dialogs * making this and invalid widget. type = gtk_option_menu_get_history(GTK_OPTION_MENU(new_item.type)); if(page == GFTE_PAGE_ICON || page == GFTE_PAGE_IMAGE || gtk_tree_model_iter_parent(GTK_TREE_MODEL(editor.store), &child, &parent); sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(editor.tree)); gtk_tree_selection_select_iter(sel, &child); object = gfte_store_get_row(&parent, &page, &title); purple_debug_misc("guifications", "ouch, I don't know where to put this, aborting\n"); gtk_widget_destroy(new_item.window); item = gf_item_new(GF_NOTIFICATION(object)); gf_item_set_type(item, type); if(type == GF_ITEM_TYPE_ICON) { GfItemIcon *icon = gf_item_icon_new(item); gf_item_set_item_icon(item, icon); } else if(type == GF_ITEM_TYPE_IMAGE) { GfItemImage *image = gf_item_image_new(item); gf_item_set_item_image(item, image); } else if(type == GF_ITEM_TYPE_TEXT) { GfItemText *text = gf_item_text_new(item); gf_item_set_item_text(item, text); /* create the offsets for the item */ offset = gf_item_offset_new(item); gf_item_set_horz_offset(item, offset); offset = gf_item_offset_new(item); gf_item_set_vert_offset(item, offset); /* add the item to the notification */ gf_notification_add_item(GF_NOTIFICATION(object), item); /* throw it in the tree */ gfte_store_add(editor.store, &child, &parent, gf_item_type_to_string(type, TRUE), /* gross dirty hack.. clean me up later */ gfte_store_select_iter(&child); gtk_widget_destroy(new_item.window); gfte_new_item_show(GtkButton *button, gpointer data) { GtkWidget *vbox, *hbox, *widget, *menu; gtk_widget_show(new_item.window); new_item.window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(new_item.window), _("New Item")); gtk_window_set_resizable(GTK_WINDOW(new_item.window), FALSE); gtk_widget_set_size_request(new_item.window, 250, -1); gtk_container_set_border_width(GTK_CONTAINER(new_item.window), 12); g_signal_connect(G_OBJECT(new_item.window), "delete-event", G_CALLBACK(gfte_new_item_deleted_cb), NULL); vbox = gtk_vbox_new(FALSE, 4); gtk_container_add(GTK_CONTAINER(new_item.window), vbox); hbox = gtk_hbox_new(FALSE, 4); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); widget = gtk_label_new(_("New item type:")); gtk_box_pack_start(GTK_BOX(hbox), widget, FALSE, FALSE, 0); menu = gf_menu_build(gf_menu_item_type, NULL); new_item.type = gtk_option_menu_new(); gtk_option_menu_set_menu(GTK_OPTION_MENU(new_item.type), menu); gtk_box_pack_start(GTK_BOX(hbox), new_item.type, TRUE, TRUE, 0); widget = gtk_hseparator_new(); gtk_box_pack_start(GTK_BOX(vbox), widget, FALSE, FALSE, 0); hbox = gtk_hbox_new(FALSE, 4); gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); widget = gtk_button_new_from_stock(GTK_STOCK_OK); g_signal_connect(G_OBJECT(widget), "clicked", G_CALLBACK(gfte_new_item_ok_cb), NULL); gtk_box_pack_end(GTK_BOX(hbox), widget, FALSE, FALSE, 0); widget = gtk_button_new_from_stock(GTK_STOCK_CANCEL); g_signal_connect(G_OBJECT(widget), "clicked", G_CALLBACK(gfte_new_item_cancel_cb), NULL); gtk_box_pack_end(GTK_BOX(hbox), widget, FALSE, FALSE, 0); gtk_widget_show_all(new_item.window); /******************************************************************************* ******************************************************************************/ gfte_duplicate_object(GtkButton *button, gpointer data) { GtkTreeIter parent, child, sibling; object = gfte_store_get_row(&sibling, &page, &title); gtk_tree_model_iter_parent(GTK_TREE_MODEL(editor.store), &parent, &sibling); if(page == GFTE_PAGE_NOTIFICATION) { GfNotification *notification; notification = gf_notification_copy(GF_NOTIFICATION(object)); gfte_store_add(editor.store, &child, &parent, title, page, for(l = gf_notification_get_items(notification); l; l = l->next) { gint type = gf_item_get_type(GF_ITEM(l->data)); gfte_store_add(editor.store, &item, &child, gf_item_type_to_string(type, TRUE), gf_theme_add_notification(editor.theme, notification); path = gtk_tree_model_get_path(GTK_TREE_MODEL(editor.store), &child); gtk_tree_view_expand_row(GTK_TREE_VIEW(editor.tree), path, TRUE); gtk_tree_path_free(path); } else if(page == GFTE_PAGE_ICON || page == GFTE_PAGE_IMAGE || item = gf_item_copy(GF_ITEM(object)); gtk_tree_store_append(editor.store, &child, &parent); gtk_tree_store_set(editor.store, &child, gf_notification_add_item(gf_item_get_notification(GF_ITEM(object)), gfte_store_select_iter(&child); /******************************************************************************* ******************************************************************************/ gfte_is_older_notification(GfNotification *notification) { theme = gf_notification_get_theme(notification); l = gf_theme_get_notifications(theme); if(l->data == notification) gfte_is_younger_notification(GfNotification *notification) { theme = gf_notification_get_theme(notification); /* get the last notification */ for(l = gf_theme_get_notifications(theme); l->next; l = l->next); if(l->data == notification) gfte_is_older_item(GfItem *item) { GfNotification *notification; notification = gf_item_get_notification(item); l = gf_notification_get_items(notification); gfte_is_younger_item(GfItem *item) { GfNotification *notification; notification = gf_item_get_notification(item); for(l = gf_notification_get_items(notification); l->next; l = l->next); gfte_store_swap(GtkTreeIter *a, GtkTreeIter *b) { gchar *a_title, *b_title; #if !GTK_CHECK_VERSION(2,2,0) #endif /* !GTK_CHECK_VERSION(2,2,0) */ gtk_tree_model_get(GTK_TREE_MODEL(editor.store), a, GFTE_STORE_OBJECT, &a_obj, GFTE_STORE_PAGE, &a_page, GFTE_STORE_TITLE, &a_title, gtk_tree_model_get(GTK_TREE_MODEL(editor.store), b, GFTE_STORE_OBJECT, &b_obj, GFTE_STORE_PAGE, &b_page, GFTE_STORE_TITLE, &b_title, if(a_page == GFTE_PAGE_NOTIFICATION) gf_notifications_swap(GF_NOTIFICATION(a_obj), GF_NOTIFICATION(b_obj)); gf_items_swap(GF_ITEM(a_obj), GF_ITEM(b_obj)); #if GTK_CHECK_VERSION(2,2,0) gtk_tree_store_swap(editor.store, a, b); gtk_tree_store_set(editor.store, a, GFTE_STORE_OBJECT, a_obj, GFTE_STORE_TITLE, a_title, gtk_tree_store_set(editor.store, b, GFTE_STORE_OBJECT, b_obj, GFTE_STORE_TITLE, b_title, #endif /* GTK_CHECK_VERSION(2,2,0) */ sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(editor.tree)); gfte_selection_changed_cb(sel, NULL); gfte_move_up(GtkButton *button, gpointer data) { GtkTreeIter child, sibling; object = gfte_store_get_row(&child, &page, &title); path = gtk_tree_model_get_path(GTK_TREE_MODEL(editor.store), &child); if(!gtk_tree_path_prev(path)) { gtk_tree_path_free(path); if(!gtk_tree_model_get_iter(GTK_TREE_MODEL(editor.store), &sibling, path)) { gtk_tree_path_free(path); gfte_store_swap(&child, &sibling); gtk_tree_path_free(path); gfte_move_down(GtkButton *button, gpointer data) { GtkTreeIter child, sibling; object = gfte_store_get_row(&child, &page, &title); path = gtk_tree_model_get_path(GTK_TREE_MODEL(editor.store), &child); /* we just assume this works since it returns void I guess.. */ gtk_tree_path_next(path); if(!gtk_tree_model_get_iter(GTK_TREE_MODEL(editor.store), &sibling, path)) { gtk_tree_path_free(path); gfte_store_swap(&child, &sibling); gtk_tree_path_free(path); /******************************************************************************* ******************************************************************************/ gfte_store_get_object_and_iter(GtkTreeIter *iter) { g_return_val_if_fail(iter, NULL); sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(editor.tree)); gtk_tree_selection_get_selected(sel, &model, iter); gtk_tree_model_get(model, iter, GFTE_STORE_OBJECT, &object, gfte_store_get_object() { return gfte_store_get_object_and_iter(&iter); /******************************************************************************* ******************************************************************************/ gfte_set_value(GtkWidget *widget, gint page, gpointer object, gconstpointer value) { GfteSetFunc setter = g_object_get_data(G_OBJECT(widget), "setter"); gint flags = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), "flags")); setter(GF_THEME_INFO(object), value); setter(GF_THEME_OPTIONS(object), value); case GFTE_PAGE_NOTIFICATION: setter(GF_NOTIFICATION(object), value); setter(GF_ITEM(object), value); case GFTE_FLAGS_SUB_OBJECT: setter(gf_item_get_item_icon(GF_ITEM(object)), value); case GFTE_FLAGS_H_OFFSET: setter(gf_item_get_horz_offset(GF_ITEM(object)), value); case GFTE_FLAGS_V_OFFSET: setter(gf_item_get_vert_offset(GF_ITEM(object)), value); setter(GF_ITEM(object), value); case GFTE_FLAGS_SUB_OBJECT: setter(gf_item_get_item_image(GF_ITEM(object)), value); case GFTE_FLAGS_H_OFFSET: setter(gf_item_get_horz_offset(GF_ITEM(object)), value); case GFTE_FLAGS_V_OFFSET: setter(gf_item_get_vert_offset(GF_ITEM(object)), value); setter(GF_ITEM(object), value); case GFTE_FLAGS_SUB_OBJECT: setter(gf_item_get_item_text(GF_ITEM(object)), value); case GFTE_FLAGS_H_OFFSET: setter(gf_item_get_horz_offset(GF_ITEM(object)), value); case GFTE_FLAGS_V_OFFSET: setter(gf_item_get_vert_offset(GF_ITEM(object)), value); gfte_entry_changed_cb(GtkWidget *widget, gpointer data) { object = gfte_store_get_object_and_iter(&iter); value = gtk_entry_get_text(GTK_ENTRY(widget)); page = gtk_notebook_get_current_page(GTK_NOTEBOOK(editor.note)); gfte_set_value(widget, page, object, (gpointer)value); if(page == GFTE_PAGE_NOTIFICATION && widget == editor.notification.alias) { GfNotification *notification; const gchar *alias = NULL, *type = NULL; if(!gf_utils_strcmp(value, "")) { notification = GF_NOTIFICATION(object); type = gf_notification_get_type(notification); event = gf_event_find_for_notification(type); alias = gf_event_get_name(event); gtk_tree_store_set(editor.store, &iter, gfte_check_toggled_cb(GtkWidget *widget, gpointer data) { gpointer object = gfte_store_get_object(); gint page = gtk_notebook_get_current_page(GTK_NOTEBOOK(editor.note)); value = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); pvalue = GINT_TO_POINTER(value); gfte_set_value(widget, page, object, pvalue); /* adjust the sensitivity according to the use gtk setting */ if(widget == editor.notification.use_gtk) { gtk_widget_set_sensitive(editor.notification.button, !value); gtk_widget_set_sensitive(editor.notification.width, value); gtk_widget_set_sensitive(editor.notification.height, value); gfte_spin_changed_cb(GtkWidget *widget, GtkScrollType arg1, gpointer user_data) gpointer object = gfte_store_get_object(); gpointer value = GINT_TO_POINTER(gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(widget))); gint page = gtk_notebook_get_current_page(GTK_NOTEBOOK(editor.note)); gfte_set_value(widget, page, object, value); gfte_option_menu_changed_cb(GtkWidget *widget, gpointer user_data) { gpointer object = gfte_store_get_object(); gpointer value = GINT_TO_POINTER(gtk_option_menu_get_history(GTK_OPTION_MENU(widget))); gint page = gtk_notebook_get_current_page(GTK_NOTEBOOK(editor.note)); gfte_set_value(widget, page, object, value); /******************************************************************************* ******************************************************************************/ gfte_get_value(GtkWidget *widget, gint page, gpointer object) { GfteGetFunc getter = g_object_get_data(G_OBJECT(widget), "getter"); /* The flags decide what item we use in our call to the getter function. This could * be GfTheme, GfThemeInfo, GfThemeOptions, GfNotification, GfItem, GfItemIcon, * GfItemImage, GfItemOffset, or GfItemText. Everything besides the item gets called * as is. Thats why we check it only for the item pages. Since the object we need * to use for the getter could be GfItem, GfItemIcon, GfItemImage, GfItemOffset, or * GfItemText. Once we know what it is, we can call it correctly. gint flags = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), "flags")); return (gpointer)getter(GF_THEME(object)); return (gpointer)getter(GF_THEME_INFO(object)); return (gpointer)getter(GF_THEME_OPTIONS(object)); case GFTE_PAGE_NOTIFICATION: return (gpointer)getter(GF_NOTIFICATION(object)); return (gpointer)getter(GF_ITEM(object)); case GFTE_FLAGS_SUB_OBJECT: return (gpointer)getter(gf_item_get_item_icon(GF_ITEM(object))); case GFTE_FLAGS_H_OFFSET: return (gpointer)getter(gf_item_get_horz_offset(GF_ITEM(object))); case GFTE_FLAGS_V_OFFSET: return (gpointer)getter(gf_item_get_vert_offset(GF_ITEM(object))); return (gpointer)getter(GF_ITEM(object)); case GFTE_FLAGS_SUB_OBJECT: return (gpointer)getter(gf_item_get_item_image(GF_ITEM(object))); case GFTE_FLAGS_H_OFFSET: return (gpointer)getter(gf_item_get_horz_offset(GF_ITEM(object))); case GFTE_FLAGS_V_OFFSET: return (gpointer)getter(gf_item_get_vert_offset(GF_ITEM(object))); return (gpointer)getter(GF_ITEM(object)); case GFTE_FLAGS_SUB_OBJECT: return (gpointer)getter(gf_item_get_item_text(GF_ITEM(object))); case GFTE_FLAGS_H_OFFSET: return (gpointer)getter(gf_item_get_horz_offset(GF_ITEM(object))); case GFTE_FLAGS_V_OFFSET: return (gpointer)getter(gf_item_get_vert_offset(GF_ITEM(object))); /******************************************************************************* ******************************************************************************/ gfte_update_entry(GtkWidget *entry, gint page, gpointer object) { gchar *value = (gchar *)gfte_get_value(entry, page, object); g_signal_handlers_block_by_func(G_OBJECT(entry), gfte_entry_changed_cb, NULL); gtk_entry_set_text(GTK_ENTRY(entry), value); gtk_entry_set_text(GTK_ENTRY(entry), ""); g_signal_handlers_unblock_by_func(G_OBJECT(entry), gfte_entry_changed_cb, NULL); gfte_update_option_menu(GtkWidget *opt_menu, gint page, gpointer object) { gint value = GPOINTER_TO_INT(gfte_get_value(opt_menu, page, object)); g_signal_handlers_block_by_func(G_OBJECT(opt_menu), gfte_option_menu_changed_cb, NULL); gtk_option_menu_set_history(GTK_OPTION_MENU(opt_menu), value); g_signal_handlers_unblock_by_func(G_OBJECT(opt_menu), gfte_option_menu_changed_cb, NULL); gfte_update_spin_button(GtkWidget *spin, gint page, gpointer object) { gint value = GPOINTER_TO_INT(gfte_get_value(spin, page, object)); g_signal_handlers_block_by_func(G_OBJECT(spin), gfte_spin_changed_cb, NULL); gtk_spin_button_set_value(GTK_SPIN_BUTTON(spin), value); g_signal_handlers_unblock_by_func(G_OBJECT(spin), gfte_spin_changed_cb, NULL); gfte_update_check(GtkWidget *check, gint page, gpointer object) { gboolean value = GPOINTER_TO_INT(gfte_get_value(check, page, object)); g_signal_handlers_block_by_func(G_OBJECT(check), gfte_check_toggled_cb, NULL); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check), value); g_signal_handlers_unblock_by_func(G_OBJECT(check), gfte_check_toggled_cb, NULL); /* adjust the sensitivity according to the use gtk setting */ if(check == editor.notification.use_gtk) { gtk_widget_set_sensitive(editor.notification.button, !value); gtk_widget_set_sensitive(editor.notification.width, value); gtk_widget_set_sensitive(editor.notification.height, value); /******************************************************************************* * Button stuff (requires getters and setters thats why it's here...) ******************************************************************************/ gfte_dialog_file_ok_cb(gpointer data, const gchar *filename) { gchar *relative = NULL, *target = NULL; button = GTK_WIDGET(data); object = gfte_store_get_object(); page = gtk_notebook_get_current_page(GTK_NOTEBOOK(editor.note)); relative = g_path_get_basename(filename); target = g_build_filename(editor.path, relative, NULL); if(!gf_file_copy_file(filename, target)) { gfte_set_value(button, page, object, relative); if(page == GFTE_PAGE_NOTIFICATION) gfte_update_entry(editor.notification.filename, page, object); else if(page == GFTE_PAGE_IMAGE) gfte_update_entry(editor.image.filename, page, object); gfte_dialog_file_cancel_cb(gpointer data, const gchar *filename) { gfte_dialog_font_ok_cb(GtkButton *b, gpointer data) { button = GTK_WIDGET(data); object = gfte_store_get_object(); page = gtk_notebook_get_current_page(GTK_NOTEBOOK(editor.note)); font = gtk_font_selection_dialog_get_font_name( GTK_FONT_SELECTION_DIALOG(opt_dialog)); gfte_set_value(button, page, object, font); gtk_widget_destroy(opt_dialog); gfte_dialog_font_cancel_cb(GtkButton *b, gpointer data) { gtk_widget_destroy(opt_dialog); gfte_dialog_color_ok_cb(GtkButton *b, gpointer data) { button = GTK_WIDGET(data); object = gfte_store_get_object(); page = gtk_notebook_get_current_page(GTK_NOTEBOOK(editor.note)); gtk_color_selection_get_current_color(GTK_COLOR_SELECTION( GTK_COLOR_SELECTION_DIALOG(opt_dialog)->colorsel), g_snprintf(ccolor, sizeof(ccolor), "#%04x%04x%04x", gcolor.red, gcolor.green, gcolor.blue); gfte_set_value(button, page, object, ccolor); gtk_widget_destroy(opt_dialog); gfte_dialog_color_cancel_cb(GtkButton *b, gpointer data) { gtk_widget_destroy(opt_dialog); gfte_button_clicked_cb(GtkWidget *button, gpointer data) { type = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(button), "type")); object = gfte_store_get_object(); page = gtk_notebook_get_current_page(GTK_NOTEBOOK(editor.note)); value = gfte_get_value(button, page, object); if(type == GFTE_BUTTON_FILE) { image_dialog = purple_request_file(plugin_handle, _("Open"), "", FALSE, G_CALLBACK(gfte_dialog_file_ok_cb), G_CALLBACK(gfte_dialog_file_cancel_cb), NULL, NULL, NULL, (gpointer)button); } else if(type == GFTE_BUTTON_FONT) { opt_dialog = gtk_font_selection_dialog_new(_("Select font")); gtk_font_selection_dialog_set_font_name( GTK_FONT_SELECTION_DIALOG(opt_dialog), (value) ? (gchar *)value : "Arial 12"); gtk_font_selection_dialog_set_preview_text( GTK_FONT_SELECTION_DIALOG(opt_dialog), g_signal_connect(G_OBJECT(GTK_FONT_SELECTION_DIALOG(opt_dialog)->ok_button), "clicked", G_CALLBACK(gfte_dialog_font_ok_cb), g_signal_connect(G_OBJECT(GTK_FONT_SELECTION_DIALOG(opt_dialog)->cancel_button), "clicked", G_CALLBACK(gfte_dialog_font_cancel_cb), gtk_widget_show_all(opt_dialog); } else if(type == GFTE_BUTTON_COLOR) { pango_color_parse(&pcolor, (gchar *)value); gcolor.green = pcolor.green; gcolor.blue = pcolor.blue; gcolor.red = gcolor.green = gcolor.blue = 0; opt_dialog = gtk_color_selection_dialog_new(_("Select color")); gtk_color_selection_set_current_color(GTK_COLOR_SELECTION( GTK_COLOR_SELECTION_DIALOG(opt_dialog)->colorsel), g_signal_connect(G_OBJECT(GTK_COLOR_SELECTION_DIALOG(opt_dialog)->ok_button), "clicked", G_CALLBACK(gfte_dialog_color_ok_cb), g_signal_connect(G_OBJECT(GTK_COLOR_SELECTION_DIALOG(opt_dialog)->cancel_button), "clicked", G_CALLBACK(gfte_dialog_color_cancel_cb), gtk_widget_show_all(opt_dialog); /******************************************************************************* ******************************************************************************/ gfte_update_item(struct GfThemeEditorItem *te_item, gint page, GfItem *item) { gfte_update_option_menu(te_item->position, page, item); gfte_update_spin_button(te_item->h_offset, page, item); gfte_update_check(te_item->h_offset_p, page, item); gfte_update_spin_button(te_item->v_offset, page, item); gfte_update_check(te_item->v_offset_p, page, item); gfte_update_info_page() { GfThemeInfo *info = (GfThemeInfo *)gfte_store_get_object(); gfte_update_entry(editor.info.name, GFTE_PAGE_INFO, info); gfte_update_entry(editor.info.version, GFTE_PAGE_INFO, info); gfte_update_entry(editor.info.summary, GFTE_PAGE_INFO, info); gfte_update_entry(editor.info.description, GFTE_PAGE_INFO, info); gfte_update_entry(editor.info.author, GFTE_PAGE_INFO, info); gfte_update_entry(editor.info.website, GFTE_PAGE_INFO, info); GfThemeOptions *ops = (GfThemeOptions *)gfte_store_get_object(); gfte_update_entry(editor.ops.date_format, GFTE_PAGE_OPS, ops); gfte_update_entry(editor.ops.time_format, GFTE_PAGE_OPS, ops); gfte_update_entry(editor.ops.warning, GFTE_PAGE_OPS, ops); gfte_update_entry(editor.ops.ellipsis, GFTE_PAGE_OPS, ops); gfte_update_notification_page() { GfNotification *notification; obj = gfte_store_get_object(); notification = GF_NOTIFICATION(obj); gfte_update_entry(editor.notification.alias, GFTE_PAGE_NOTIFICATION, gfte_update_check(editor.notification.use_gtk, GFTE_PAGE_NOTIFICATION, gfte_update_entry(editor.notification.filename, GFTE_PAGE_NOTIFICATION, gfte_update_spin_button(editor.notification.width, GFTE_PAGE_NOTIFICATION, gfte_update_spin_button(editor.notification.height, GFTE_PAGE_NOTIFICATION, gfte_update_icon_page() { GfItem *item = GF_ITEM(gfte_store_get_object()); gfte_update_item(&editor.icon.item, GFTE_PAGE_ICON, item); gfte_update_option_menu(editor.icon.type, GFTE_PAGE_ICON, item); gfte_update_option_menu(editor.icon.size, GFTE_PAGE_ICON, item); gfte_update_image_page() { GfItem *item = GF_ITEM(gfte_store_get_object()); gfte_update_item(&editor.image.item, GFTE_PAGE_IMAGE, item); gfte_update_entry(editor.image.filename, GFTE_PAGE_IMAGE, item); gfte_update_text_page() { GfItem *item = GF_ITEM(gfte_store_get_object()); gfte_update_item(&editor.text.item, GFTE_PAGE_TEXT, item); gfte_update_entry(editor.text.format, GFTE_PAGE_TEXT, item); gfte_update_spin_button(editor.text.width, GFTE_PAGE_TEXT, item); gfte_update_option_menu(editor.text.clipping, GFTE_PAGE_TEXT, item); /******************************************************************************* ******************************************************************************/ gfte_selection_changed_cb(GtkTreeSelection *sel, gpointer data) { if(!gtk_tree_selection_get_selected(sel, &model, &iter)) { gtk_notebook_set_current_page(GTK_NOTEBOOK(editor.note), gtk_tree_model_get(model, &iter, GFTE_STORE_OBJECT, &object, gtk_notebook_set_current_page(GTK_NOTEBOOK(editor.note), page); gfte_toolbar_buttons_update(FALSE, FALSE, FALSE, FALSE, FALSE); gfte_toolbar_buttons_update(FALSE, FALSE, FALSE, FALSE, FALSE); gfte_toolbar_buttons_update(FALSE, FALSE, FALSE, FALSE, FALSE); case GFTE_PAGE_NOTIFICATION: { GfNotification *notification = GF_NOTIFICATION(object); master = (g_ascii_strcasecmp(GF_NOTIFICATION_MASTER, gf_notification_get_type(notification))); gfte_toolbar_buttons_update(TRUE, master, master, gfte_is_older_notification(object), gfte_is_younger_notification(object)); gfte_update_notification_page(); gfte_toolbar_buttons_update(TRUE, TRUE, TRUE, gfte_is_older_item(object), gfte_is_younger_item(object)); gfte_toolbar_buttons_update(TRUE, TRUE, TRUE, gfte_is_older_item(object), gfte_is_younger_item(object)); gfte_update_image_page(); gfte_toolbar_buttons_update(TRUE, TRUE, TRUE, gfte_is_older_item(object), gfte_is_younger_item(object)); gfte_new_theme_cb(GtkButton *button, gpointer data) { gfte_modified_show(GFTE_MODIFIED_NEW, NULL); gfte_save_theme_cb(GtkButton *button, gpointer data) { gfte_help(GtkButton *button, gpointer data) { purple_notify_uri(NULL, GF_WEBSITE "/themes/theme_howto/"); /******************************************************************************* ******************************************************************************/ GtkCellRenderer *renderer; 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(editor.hbox), sw, FALSE, FALSE, 0); editor.tree = gtk_tree_view_new_with_model(GTK_TREE_MODEL(editor.store)); sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(editor.tree)); g_signal_connect_after(G_OBJECT(sel), "changed", G_CALLBACK(gfte_selection_changed_cb), NULL); gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(editor.tree), FALSE); gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(editor.tree), FALSE); gtk_tree_view_expand_all(GTK_TREE_VIEW(editor.tree)); gtk_container_add(GTK_CONTAINER(sw), editor.tree); renderer = gtk_cell_renderer_text_new(); col = gtk_tree_view_column_new_with_attributes(NULL, renderer, "text", GFTE_STORE_TITLE, gtk_tree_view_append_column(GTK_TREE_VIEW(editor.tree), col); gfte_make_label(const gchar *text, GtkSizeGroup *sg) { label = gtk_label_new_with_mnemonic(text); gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); gtk_size_group_add_widget(sg, label); gfte_add_label(GtkWidget *widget, const gchar *label, GtkSizeGroup *sg) { hbox = gtk_hbox_new(FALSE, 4); gtk_box_pack_start(GTK_BOX(hbox), gfte_make_label(label, sg), gtk_box_pack_start(GTK_BOX(hbox), widget, FALSE, FALSE, 0); gfte_add_entry(GtkWidget *parent, GtkSizeGroup *sg, gint flags, const gchar *label, gpointer getter, gpointer setter) g_object_set_data(G_OBJECT(entry), "getter", getter); g_object_set_data(G_OBJECT(entry), "setter", setter); g_object_set_data(G_OBJECT(entry), "flags", GINT_TO_POINTER(flags)); g_signal_connect(G_OBJECT(entry), "changed", G_CALLBACK(gfte_entry_changed_cb), NULL); hbox = gfte_add_label(entry, label, sg); gtk_box_pack_start(GTK_BOX(parent), hbox, FALSE, FALSE, 0); gfte_add_check(GtkWidget *parent, gint flags, const gchar *label, gpointer getter, gpointer setter) check = gtk_check_button_new_with_mnemonic(label); g_object_set_data(G_OBJECT(check), "getter", getter); g_object_set_data(G_OBJECT(check), "setter", setter); g_object_set_data(G_OBJECT(check), "flags", GINT_TO_POINTER(flags)); g_signal_connect(G_OBJECT(check), "toggled", G_CALLBACK(gfte_check_toggled_cb), NULL); gtk_box_pack_start(GTK_BOX(parent), check, FALSE, FALSE, 0); gfte_add_spin_button(GtkWidget *parent, GtkSizeGroup *sg, gint flags, const gchar *label, gint min, gint max, gpointer getter, gpointer setter) spin = gtk_spin_button_new_with_range(min, max, 1); gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(spin), TRUE); g_object_set_data(G_OBJECT(spin), "getter", getter); g_object_set_data(G_OBJECT(spin), "setter", setter); g_object_set_data(G_OBJECT(spin), "flags", GINT_TO_POINTER(flags)); g_signal_connect(G_OBJECT(spin), "value-changed", G_CALLBACK(gfte_spin_changed_cb), NULL); hbox = gfte_add_label(spin, label, sg); gtk_box_pack_start(GTK_BOX(parent), hbox, FALSE, FALSE, 0); gfte_add_option_menu(GtkWidget *parent, GtkSizeGroup *sg, gint flags, const gchar *label, GfMenuItemBuilder builder, gpointer getter, gpointer setter) GtkWidget *option_menu, *hbox; option_menu = gtk_option_menu_new(); gtk_option_menu_set_menu(GTK_OPTION_MENU(option_menu), gf_menu_build(builder, NULL)); g_object_set_data(G_OBJECT(option_menu), "getter", getter); g_object_set_data(G_OBJECT(option_menu), "setter", setter); g_object_set_data(G_OBJECT(option_menu), "flags", GINT_TO_POINTER(flags)); g_signal_connect(G_OBJECT(option_menu), "changed", G_CALLBACK(gfte_option_menu_changed_cb), NULL); hbox = gfte_add_label(option_menu, label, sg); gtk_box_pack_start(GTK_BOX(parent), hbox, FALSE, FALSE, 0); gfte_add_button(GtkWidget *parent, gint flags, gint type, const gchar *stock_id, gpointer getter, gpointer setter) button = gtk_button_new_from_stock(stock_id); g_object_set_data(G_OBJECT(button), "getter", getter); g_object_set_data(G_OBJECT(button), "setter", setter); g_object_set_data(G_OBJECT(button), "flags", GINT_TO_POINTER(flags)); g_object_set_data(G_OBJECT(button), "type", GINT_TO_POINTER(type)); g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(gfte_button_clicked_cb), NULL); gtk_box_pack_start(GTK_BOX(parent), button, FALSE, FALSE, 0); /******************************************************************************* ******************************************************************************/ page = gtk_vbox_new(FALSE, 0); sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL); page = gtk_vbox_new(FALSE, 4); gtk_container_set_border_width(GTK_CONTAINER(page), 12); gfte_add_entry(page, sg, GFTE_FLAGS_OBJECT, _("Name:"), gfte_add_entry(page, sg, GFTE_FLAGS_OBJECT, _("Version:"), gf_theme_info_get_version, gf_theme_info_set_version); gfte_add_entry(page, sg, GFTE_FLAGS_OBJECT, _("Summary:"), gf_theme_info_get_summary, gf_theme_info_set_summary); editor.info.description = gfte_add_entry(page, sg, GFTE_FLAGS_OBJECT, _("Description:"), gf_theme_info_get_description, gf_theme_info_set_description); gfte_add_entry(page, sg, GFTE_FLAGS_OBJECT, _("Author:"), gf_theme_info_get_author, gf_theme_info_set_author); gfte_add_entry(page, sg, GFTE_FLAGS_OBJECT, _("Website:"), gf_theme_info_get_website, gf_theme_info_set_website); sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL); page = gtk_vbox_new(FALSE, 4); gtk_container_set_border_width(GTK_CONTAINER(page), 12); gfte_add_entry(page, sg, GFTE_FLAGS_OBJECT, _("Date Format:"), gf_theme_options_get_date_format, gf_theme_options_set_date_format); gfte_add_entry(page, sg, GFTE_FLAGS_OBJECT, _("Time Format:"), gf_theme_options_get_time_format, gf_theme_options_set_time_format); gfte_add_entry(page, sg, GFTE_FLAGS_OBJECT, _("Warning:"), gf_theme_options_get_warning, gf_theme_options_set_warning); gfte_add_entry(page, sg, GFTE_FLAGS_OBJECT, _("Ellipsis:"), gf_theme_options_get_ellipsis, gf_theme_options_set_ellipsis); gfte_make_notification_page() { sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL); page = gtk_vbox_new(FALSE, 4); gtk_container_set_border_width(GTK_CONTAINER(page), 12); editor.notification.alias = gfte_add_entry(page, sg, GFTE_FLAGS_OBJECT, _("Alias:"), gf_notification_get_alias, gf_notification_set_alias); editor.notification.use_gtk = gfte_add_check(page, GFTE_FLAGS_OBJECT, _("Use Gtk theme background"), gf_notification_get_use_gtk, gf_notification_set_use_gtk); editor.notification.filename = gfte_add_entry(page, sg, GFTE_FLAGS_OBJECT, _("Background:"), gf_notification_get_background, gf_notification_set_background); gtk_widget_set_sensitive(editor.notification.filename, FALSE); editor.notification.button = gfte_add_button(editor.notification.filename->parent, GFTE_FLAGS_OBJECT, GFTE_BUTTON_FILE, gf_notification_get_background, gf_notification_set_background); editor.notification.width = gfte_add_spin_button(page, sg, GFTE_FLAGS_OBJECT, _("Width:"), GF_NOTIFICATION_MIN, GF_NOTIFICATION_MAX, gf_notification_get_width, gf_notification_set_width); editor.notification.height = gfte_add_spin_button(page, sg, GFTE_FLAGS_OBJECT, _("Height:"), GF_NOTIFICATION_MIN, GF_NOTIFICATION_MAX, gf_notification_get_height, gf_notification_set_height); gfte_make_item_widgets(GtkWidget *parent, GtkSizeGroup *sg, struct GfThemeEditorItem *item) item->position = gfte_add_option_menu(parent, sg, GFTE_FLAGS_OBJECT, item->h_offset = gfte_add_spin_button(parent, sg, GFTE_FLAGS_H_OFFSET, _("_Horizontal Offset:"), -1024, 1023, gf_item_offset_get_value, gf_item_offset_set_value); item->h_offset_p = gfte_add_check(item->h_offset->parent, GFTE_FLAGS_H_OFFSET, _("Percentage"), gf_item_offset_get_is_percentage, gf_item_offset_set_is_percentage); item->v_offset = gfte_add_spin_button(parent, sg, GFTE_FLAGS_V_OFFSET, _("_Vertical Offset:"), -1024, 1023, gf_item_offset_get_value, gf_item_offset_set_value); item->v_offset_p = gfte_add_check(item->v_offset->parent, GFTE_FLAGS_V_OFFSET, _("Percentage"), gf_item_offset_get_is_percentage, gf_item_offset_set_is_percentage); sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL); page = gtk_vbox_new(FALSE, 4); gtk_container_set_border_width(GTK_CONTAINER(page), 12); gfte_make_item_widgets(page, sg, &editor.icon.item); editor.icon.type = gfte_add_option_menu(page, sg, GFTE_FLAGS_SUB_OBJECT, _("_Type:"), gf_menu_item_icon_type, editor.icon.size = gfte_add_option_menu(page, sg, GFTE_FLAGS_SUB_OBJECT, _("_Size:"), gf_menu_item_icon_size, sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL); page = gtk_vbox_new(FALSE, 4); gtk_container_set_border_width(GTK_CONTAINER(page), 12); gfte_make_item_widgets(page, sg, &editor.image.item); editor.image.filename = gfte_add_entry(page, sg, GFTE_FLAGS_SUB_OBJECT, gf_item_image_set_image); gtk_widget_set_sensitive(editor.image.filename, FALSE); editor.image.button = gfte_add_button(editor.image.filename->parent, GFTE_FLAGS_SUB_OBJECT, GFTE_BUTTON_FILE, gf_item_image_set_image); sg = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL); page = gtk_vbox_new(FALSE, 4); gtk_container_set_border_width(GTK_CONTAINER(page), 12); gfte_make_item_widgets(page, sg, &editor.text.item); editor.text.format = gfte_add_entry(page, sg, GFTE_FLAGS_SUB_OBJECT, gf_item_text_set_format); editor.text.width = gfte_add_spin_button(page, sg, GFTE_FLAGS_SUB_OBJECT, editor.text.clipping = gfte_add_option_menu(page, sg, GFTE_FLAGS_SUB_OBJECT, gf_menu_item_text_clipping, gf_item_text_get_clipping, gf_item_text_set_clipping); editor.text.font = gfte_add_button(NULL, GFTE_FLAGS_SUB_OBJECT, GFTE_BUTTON_FONT, GTK_STOCK_SELECT_FONT, hbox = gfte_add_label(editor.text.font, NULL, sg); gtk_box_pack_start(GTK_BOX(page), hbox, FALSE, FALSE, 0); editor.text.color = gfte_add_button(NULL, GFTE_FLAGS_SUB_OBJECT, GFTE_BUTTON_COLOR, GTK_STOCK_SELECT_COLOR, hbox = gfte_add_label(editor.text.color, NULL, sg); gtk_box_pack_start(GTK_BOX(page), hbox, FALSE, FALSE, 0); /******************************************************************************* ******************************************************************************/ gfte_toolbar_button_new(GtkWidget *parent, const gchar *stock_id, const gchar *tooltip, GCallback cb, gpointer data) GtkWidget *button, *image; button = gtk_button_new(); gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE); g_signal_connect(G_OBJECT(button), "clicked", cb, data); gtk_tooltips_set_tip(editor.tooltips, button, tooltip, NULL); image = gtk_image_new_from_stock(stock_id, GTK_ICON_SIZE_SMALL_TOOLBAR); gtk_container_add(GTK_CONTAINER(button), image); gtk_box_pack_start(GTK_BOX(parent), button, FALSE, FALSE, 0); gfte_toolbar_separator_new(GtkWidget *parent) { sep = gtk_vseparator_new(); gtk_box_pack_start(GTK_BOX(parent), sep, FALSE, FALSE, 0); GtkWidget *frame, *hbox, *help; frame = gtk_frame_new(NULL); gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_OUT); gtk_box_pack_start(GTK_BOX(editor.vbox), frame, FALSE, FALSE, 0); hbox = gtk_hbox_new(FALSE, 0); gtk_container_add(GTK_CONTAINER(frame), hbox); gfte_toolbar_button_new(hbox, GTK_STOCK_NEW, _("New theme"), G_CALLBACK(gfte_new_theme_cb), NULL); gfte_toolbar_button_new(hbox, GTK_STOCK_SAVE, _("Save theme"), G_CALLBACK(gfte_save_theme_cb), NULL); gfte_toolbar_separator_new(hbox); editor.tool_notification = gfte_toolbar_button_new(hbox, GTK_STOCK_EXECUTE, G_CALLBACK(gfte_new_notification_show), gfte_toolbar_button_new(hbox, GTK_STOCK_PROPERTIES, G_CALLBACK(gfte_new_item_show), NULL); gfte_toolbar_button_new(hbox, GTK_STOCK_COPY, G_CALLBACK(gfte_duplicate_object), gfte_toolbar_button_new(hbox, GTK_STOCK_DELETE, G_CALLBACK(gfte_delete_show), NULL); gfte_toolbar_separator_new(hbox); gfte_toolbar_button_new(hbox, GTK_STOCK_GO_UP, _("Move up"), G_CALLBACK(gfte_move_up), NULL); gfte_toolbar_button_new(hbox, GTK_STOCK_GO_DOWN, _("Move down"), G_CALLBACK(gfte_move_down), NULL); gfte_toolbar_separator_new(hbox); help = gfte_toolbar_button_new(hbox, GTK_STOCK_HELP, _("Help"), G_CALLBACK(gfte_help), NULL); gfte_toolbar_buttons_update(FALSE, FALSE, FALSE, FALSE, FALSE); editor.note = gtk_notebook_new(); gtk_notebook_set_show_tabs(GTK_NOTEBOOK(editor.note), FALSE); gtk_box_pack_start(GTK_BOX(editor.hbox), editor.note, TRUE, TRUE, 4); gtk_notebook_insert_page(GTK_NOTEBOOK(editor.note), gtk_notebook_insert_page(GTK_NOTEBOOK(editor.note), gtk_notebook_insert_page(GTK_NOTEBOOK(editor.note), gtk_notebook_insert_page(GTK_NOTEBOOK(editor.note), gfte_make_notification_page(), NULL, GFTE_PAGE_NOTIFICATION); gtk_notebook_insert_page(GTK_NOTEBOOK(editor.note), gtk_notebook_insert_page(GTK_NOTEBOOK(editor.note), gtk_notebook_insert_page(GTK_NOTEBOOK(editor.note), gfte_window_destroyed_cb(GtkWidget *widget, GdkEvent *event, gpointer data) { gfte_modified_show(GFTE_MODIFIED_CLOSE, NULL); editor.tooltips = gtk_tooltips_new(); g_object_ref(G_OBJECT(editor.tooltips)); gtk_object_sink(GTK_OBJECT(editor.tooltips)); editor.window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(editor.window), _("Guifications Theme Editor")); g_signal_connect(G_OBJECT(editor.window), "delete-event", G_CALLBACK(gfte_window_destroyed_cb), NULL); editor.vbox = gtk_vbox_new(FALSE, 4); gtk_container_add(GTK_CONTAINER(editor.window), editor.vbox); editor.hbox = gtk_hbox_new(FALSE, 4); gtk_box_pack_start(GTK_BOX(editor.vbox), editor.hbox, TRUE, TRUE, 0); /******************************************************************************* ******************************************************************************/ gtk_window_present(GTK_WINDOW(editor.window)); gtk_widget_show_all(editor.window); /******************************************************************************* ******************************************************************************/ gf_theme_editor_init(PurplePlugin *plugin) { gf_theme_editor_uninit() { gtk_widget_destroy(editor.window); gf_theme_editor_show(const gchar *filename) { /* if filename is NULL a new theme is being created */ /* theme editor isn't showing so we create it */ /* theme editor is showing, so we check the file names, if they match, we just show * the editor. If they don't, we check if the theme is modified. If it is, then we * show the modified dialog, and save it if the user wants it saved, and then open if(!g_ascii_strcasecmp(editor.filename, filename)) { gfte_modified_show(GFTE_MODIFIED_OPEN, filename);