Mercurial > grim > purple-plugin-pack
view buddytime/gtktimezone.c @ 1028:314cfd774bc4
s/purple.guifications.org/plugins.guifications.org/
author | Paul Aurich <paul@darkrain42.org> |
---|---|
date | Thu, 06 Aug 2009 12:30:12 -0700 |
parents | db4ad6aa002f |
children | 81a5336b6c5b 125cd93bc5fc |
line wrap: on
line source
/************************************************************************* * GTK Timezone widget module * by Martijn van Oosterhout <kleptog@svana.org> (C) April 2006 * Licenced under the GNU General Public Licence version 2. * * This module creates the GTK widget used to select timezones. It's here to * clearly seperate the GTK stuff from the plugin itself. *************************************************************************/ #include <gtk/gtk.h> #include <string.h> #include <ctype.h> #include "recurse.h" #define DISABLED_STRING "<Disabled>" #define DEFAULT_STRING "<Default>" #define MORE_STRING "More..." struct nodestate { GtkWidget *submenu; gchar *string; }; struct state { GtkWidget *base; GtkWidget *extra; int currdepth; struct nodestate stack[4]; }; static inline const char * menuitem_get_label(GtkMenuItem * menuitem) { return gtk_label_get_text(GTK_LABEL(gtk_bin_get_child(GTK_BIN(menuitem)))); } static GtkMenuItem * menu_get_first_menuitem(GtkWidget * menu) { GList *list = gtk_container_get_children(GTK_CONTAINER(menu)); GtkMenuItem *selection = GTK_MENU_ITEM(g_list_nth_data(list, 0)); g_list_free(list); return selection; } static int menu_select_cb(GtkMenuItem * menuitem, GtkWidget * menu) { const char *label = menuitem_get_label(menuitem); if(label[0] == '<') { GtkWidget *selection; gchar *selstring; if(strcmp(label, DEFAULT_STRING) == 0) selstring = ""; else if(strcmp(label, DISABLED_STRING) == 0) selstring = "none"; selection = GTK_WIDGET(menu_get_first_menuitem(menu)); gtk_widget_hide(selection); } else { char *str = g_strdup(label); GtkWidget *parent; for (;;) { GtkMenuItem *parentitem; const char *label2; char *temp; parent = gtk_widget_get_parent(GTK_WIDGET(menuitem)); if(menu == parent) break; parentitem = GTK_MENU_ITEM(gtk_menu_get_attach_widget(GTK_MENU(parent))); label2 = menuitem_get_label(parentitem); if(strcmp(label2, MORE_STRING) != 0) { temp = g_strconcat(label2, "/", str, NULL); g_free(str); str = temp; } menuitem = parentitem; } { GtkLabel *label; GtkMenuItem *selection = menu_get_first_menuitem(menu); GtkOptionMenu *optionmenu = GTK_OPTION_MENU(gtk_menu_get_attach_widget(GTK_MENU(menu))); label = GTK_LABEL(gtk_bin_get_child(GTK_BIN(selection))); gtk_label_set_text(label, str); gtk_widget_show(GTK_WIDGET(selection)); gtk_option_menu_set_history(optionmenu, 0); printf("optionmenu=%p, menu=%p, menuitem=%p, label=%p\n", optionmenu, menu, selection, label); g_free(str); } } return 0; } static int make_menu_cb(char *path, struct state *state) { int i, j; char **elements; /* Here we ignore strings not beginning with uppercase, since they are auxilliary files, not timezones */ if(!isupper(path[0])) return 0; elements = g_strsplit(path, "/", 4); for (i = 0; i < state->currdepth && state->stack[i].string; i++) { if(strcmp(elements[i], state->stack[i].string) != 0) break; } /* i is now the index of the first non-matching element, so free the rest */ for (j = i; j < state->currdepth; j++) g_free(state->stack[j].string); state->currdepth = i; while (elements[i]) { GtkWidget *parent = (i == 0) ? state->base : state->stack[i - 1].submenu; GtkWidget *menuitem; if(i == 0 && elements[1] == NULL) parent = state->extra; menuitem = gtk_menu_item_new_with_label(elements[i]); gtk_menu_append(parent, menuitem); if(elements[i + 1] != NULL) /* Has submenu */ { state->stack[i].submenu = gtk_menu_new(); gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), state->stack[i].submenu); state->currdepth++; state->stack[i].string = g_strdup(elements[i]); } else g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(menu_select_cb), state->base); i++; } g_strfreev(elements); return 0; } void * make_timezone_menu(const char *selected) { int i; struct state state; GtkWidget *menu; GtkWidget *optionmenu, *menuitem, *selection; if(selected == NULL) selected = ""; menu = gtk_menu_new(); menuitem = gtk_menu_item_new_with_label(selected); gtk_menu_append(menu, menuitem); selection = menuitem; menuitem = gtk_menu_item_new_with_label(DISABLED_STRING); g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(menu_select_cb), menu); gtk_menu_append(menu, menuitem); menuitem = gtk_menu_item_new_with_label(DEFAULT_STRING); g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(menu_select_cb), menu); gtk_menu_append(menu, menuitem); menuitem = gtk_menu_item_new_with_label(MORE_STRING); gtk_menu_append(menu, menuitem); state.base = menu; state.extra = gtk_menu_new(); gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), state.extra); state.currdepth = 0; recurse_directory("/usr/share/zoneinfo", (DirRecurseMatch) make_menu_cb, &state); for (i = 0; i < state.currdepth; i++) g_free(state.stack[i].string); optionmenu = gtk_option_menu_new(); gtk_option_menu_set_menu(GTK_OPTION_MENU(optionmenu), menu); gtk_widget_show_all(optionmenu); if(strcmp(selected, "") == 0) { gtk_option_menu_set_history(GTK_OPTION_MENU(optionmenu), 2); gtk_widget_hide(selection); } else if(strcmp(selected, "none") == 0) { gtk_option_menu_set_history(GTK_OPTION_MENU(optionmenu), 1); gtk_widget_hide(selection); } else { gtk_option_menu_set_history(GTK_OPTION_MENU(optionmenu), 0); } return optionmenu; } const char * get_timezone_menu_selection(void *widget) { GtkOptionMenu *menu = GTK_OPTION_MENU(widget); int sel = gtk_option_menu_get_history(menu); if(sel == 2) /* Default */ return NULL; if(sel == 1) /* Disabled */ return "none"; GtkLabel *l = GTK_LABEL(gtk_bin_get_child(GTK_BIN(menu))); return gtk_label_get_text(l); }