[svn] / beryl-settings / trunk / src / main.c Project Root: cvssvn svn: beryl-settings/trunk/src/main.c File: [svn] / beryl-settings / trunk / src / main.c (download) (as text) Revision: 272, Tue Sep 26 16:08:28 2006 UTC (12 hours, 24 minutes ago) by cyberorg File size: 81923 byte(s) Preparing for internationalisation, test french(partial) and portugese ones /* * Copyright (C) 2006 Quinn Storm * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifdef HAVE_CONFIG_H #include #endif #include #include #define DBUS_API_SUBJECT_TO_CHANGE #include #include #include #include #include #include #include //locale stuff #include #include #define _(String) gettext (String) #define gettext_noop(String) String #define N_(String) gettext_noop (String) typedef enum _SETOptionType { SETString, SETColor, SETInt, SETBool, SETFloat, SETAction, SETList, SETMAX } SETOptionType; gchar * SETOptionTypes[]={ "string", "color", "int", "bool", "float", "action", "list", }; typedef union _SETOptionValue SETOptionValue; union _SETOptionValue { gchar * s; gint i; gdouble f; SETOptionValue * l; gint c[4]; gint a[6]; gboolean b; }; typedef struct _SETNumericWidgets { GtkSpinButton * s; GtkHScale * h; } SETNumericWidgets; gint nModifiers[]={ ShiftMask, ControlMask, CompAltMask, CompSuperMask, CompHyperMask, CompMetaMask, CompModeSwitchMask, Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask, }; gchar * modifiers[]={ "Shift", "Control", "Alt", "Super", "Hyper", "Meta", "Mode", "Mod1", "Mod2", "Mod3", "Mod4", "Mod5", }; #define NMODIFIERS (sizeof(modifiers)/sizeof(gchar *)) #define MODROWS 2 gchar * edges[]={ "Left", "Right", "Top", "Bottom", "Top-Left", "Top-Right", "Bottom-Left", "Bottom-Right", }; // intuitive layout of edge checkboxes in the table gint edgecols[]= { 0, 2, 1, 1, 0, 2, 0, 2, }; gint edgerows[]= { 1, 1, 0, 2, 0, 0, 2, 2, }; typedef struct _SETActionWidgets { GtkCheckButton * kmod[NMODIFIERS]; // modifiers for key GtkEntry * key; // keysym(string in entrybox) GtkCheckButton * bmod[NMODIFIERS]; // modifiers for mouse button GtkEntry * but; // mouse button GtkCheckButton * b; // bell GtkCheckButton * e[SCREEN_EDGE_NUM]; // edges (checklist) } SETActionWidgets; typedef struct _SETStringListWidgets { GtkListStore * backing; GtkTreeView * view; GtkButton * add; GtkButton * rem; GtkButton * bro; GtkButton * up; GtkButton * dn; } SETStringListWidgets; typedef struct _SETStringBrowseWidgets { GtkEntry * e; GtkButton * b; } SETStringBrowseWidgets; typedef union _SETOptionWidgets { GtkWidget * w; GtkCheckButton * b; SETStringBrowseWidgets sb; SETNumericWidgets n; SETActionWidgets a; GtkWidget ** l; SETStringListWidgets s; } SETOptionWidgets; typedef union _SETOptionRestrictions { gchar ** s; // NULL terminated list of possible strings, NULL for anything goes gint i[2]; // min, max gdouble f[3]; // min, max, prec gboolean a[4]; // button, key, edge, bell } SETOptionRestrictions; typedef struct _SETOption { gchar * name; gchar * section; gchar * sdesc; gchar * ldesc; SETOptionType type; SETOptionType listtype; SETOptionValue value; SETOptionValue defaultValue; SETOptionRestrictions rest; gchar ** hints; // NULL terminated list of hints gint nValue; gint nDValue; SETOptionWidgets widgets; gboolean defined; } SETOption; typedef struct _SETGroupWidget { gchar * group; GtkWidget * widget; gboolean hasany; } SETGroupWidget; typedef struct _SETPage { gchar * name; GtkWidget * widget; } SETPage; typedef struct _SETResetOption { SETOption * o; gint resetType; // for action options, 0=button,1=key,2=edge,3=bell } SETResetOption; SETPage * SETOptionPages; GSList * SETOptions=NULL; GSList * reloadOptions=NULL; GKeyFile * schemaFile; GKeyFile * settingsFile; GtkListStore * pluginList; GtkTreeView * SETPluginList; GtkWidget * pluginContainer; GtkWidget * infoLabel; GtkWidget * infoContainer; gint nPages=0; gint nOthers=0; gchar ** oplugs=NULL; GtkWidget * mainWindow; static gboolean suspend_signals=FALSE; enum _SETPluginListEntry { PluginName, ShortDesc, LongDesc, Markup, PluginIcon, PluginEnabled, PluginCanEnable, PluginEntryCount }; DBusConnection *dbcon; void send_option_changed_signal(gchar * section, gchar * option) { DBusMessage * mesg; const char * sstring="section"; const char * ostring="option"; mesg = dbus_message_new_method_call("org.freedesktop.beryl", "/org/freedesktop/beryl/settings/allscreens/reload", "org.freedesktop.beryl","activate"); dbus_message_append_args(mesg, DBUS_TYPE_STRING,&sstring, DBUS_TYPE_STRING,§ion, DBUS_TYPE_STRING,&ostring, DBUS_TYPE_STRING,&option, DBUS_TYPE_INVALID); dbus_connection_send(dbcon,mesg,NULL); dbus_message_unref(mesg); } gboolean dequeue_sig(gpointer p) { if (reloadOptions) { SETOption * o = reloadOptions->data; reloadOptions=g_slist_remove_all(reloadOptions,o); send_option_changed_signal(o->section,o->name); } return TRUE; } void queue_option_changed(SETOption * o) { if (!g_slist_find(reloadOptions,o)) reloadOptions=g_slist_append(reloadOptions,o); } void import_key_file(GKeyFile * dest, gchar * source) { GKeyFile * f = g_key_file_new(); gchar ** gr; gint i; g_key_file_load_from_file(f,source,0,NULL); gr = g_key_file_get_groups(f,NULL); for (i=0;gr && gr[i];i++) { gint j; gchar ** ke; ke = g_key_file_get_keys(f,gr[i],NULL,NULL); for (j=0;ke && ke[j];j++) g_key_file_set_value(dest,gr[i],ke[j], g_key_file_get_value(f,gr[i],ke[j],NULL)); g_strfreev(ke); } g_strfreev(gr); g_key_file_free(f); } void load_schema_files() { GDir * d; gchar * dpos; gchar * temp1; settingsFile = g_key_file_new(); temp1=g_strconcat(g_get_home_dir(),"/.beryl/settings",NULL); g_key_file_load_from_file(settingsFile,temp1,0,NULL); g_free(temp1); schemaFile = g_key_file_new(); import_key_file(schemaFile,DATADIR "/beryl/settings"); import_key_file(schemaFile,DATADIR "/beryl/hints"); d=g_dir_open(DATADIR "/beryl/",0,NULL); if (d) { const gchar * e; while((e=g_dir_read_name(d))) { gchar * xfile; if (g_str_has_suffix(e,".settings")) { xfile = g_strconcat(DATADIR "/beryl/",e,NULL); import_key_file(schemaFile,xfile); g_free(xfile); } } g_dir_close(d); } dpos = g_strconcat(g_get_home_dir(),"/.beryl/plugins/",NULL); d=g_dir_open(dpos,0,NULL); if (d) { const gchar * e; while((e=g_dir_read_name(d))) { gchar * xfile; if (g_str_has_suffix(e,".settings")) { xfile = g_strconcat(g_get_home_dir(),"/.beryl/plugins/",e,NULL); import_key_file(schemaFile,xfile); g_free(xfile); } } g_dir_close(d); } g_free(dpos); } SETOptionType string_to_type(gchar * optype) { gint i; for (i=0;itype == SETString) { if (o->value.s) g_free(o->value.s); o->value.s=NULL; } if (o->type == SETList && o->value.l) { gint i; if (o->listtype==SETString) for(i=0;inValue;i++) { if (o->value.l[i].s) g_free(o->value.l[i].s); } free(o->value.l); o->value.l=NULL; o->nValue=0; } } void copy_option_from_default(SETOption * o) { memcpy(&o->value,&o->defaultValue,sizeof(SETOptionValue)); if (o->type == SETString) o->value.s=g_strdup(o->defaultValue.s); if (o->type == SETList) { gint i; o->nValue=o->nDValue; if (o->nValue) { o->value.l=malloc(sizeof(SETOptionValue)*o->nValue); memcpy(o->value.l,o->defaultValue.l,sizeof(SETOptionValue)*o->nValue); if (o->listtype==SETString) for(i=0;inValue;i++) o->value.l[i].s=g_strdup(o->defaultValue.l[i].s); } } } void load_option(SETOption *o, gboolean dfl) { gchar * dkey = dfl?g_strconcat("d_",o->name,NULL):g_strdup(o->name); SETOptionValue * v = dfl?(&o->defaultValue):(&o->value); GKeyFile * f = dfl?schemaFile:settingsFile; GError * e = NULL; gint * nv = dfl?(&o->nDValue):(&o->nValue); gboolean useDfl=FALSE; if (!dfl) free_option_value(o); // default values never need freed :-P switch(o->type) { case SETString: { gchar * s; s=g_key_file_get_string(f,o->section,dkey,NULL); if (!s) { useDfl=TRUE; break; } if (o->rest.s && !dfl) { gboolean allowed=FALSE; gchar * e; gint i; for (i=0;(e=o->rest.s[i]);i++) { if (strcmp(e,s)==0) allowed=TRUE; } if (!allowed) { g_free(s); s=g_strdup(o->defaultValue.s); } if (o->value.s) g_free(o->value.s); v->s=s; } else v->s=s; } break; case SETBool: { gboolean b; b=g_key_file_get_boolean(f,o->section,dkey,&e); if (e) { useDfl=TRUE; break; } v->b=b; } break; case SETInt: { gint i; i=g_key_file_get_integer(f,o->section,dkey,&e); if (e) { useDfl=TRUE; break; } v->i=MAX(i,o->rest.i[0]); v->i=MIN(v->i,o->rest.i[1]); } break; case SETFloat: { gchar * s; gdouble fl; s=g_key_file_get_string(f,o->section,dkey,NULL); if (!s) { useDfl=TRUE; break; } fl=g_ascii_strtod(s,NULL); g_free(s); v->f=MAX(fl,o->rest.f[0]); v->f=MIN(v->f,o->rest.f[1]); //not bothering with prec for right now. } break; case SETColor: { gint * i; gsize l=0; i=g_key_file_get_integer_list(f,o->section,dkey,&l,&e); if (e || l!=4) { if (!e) g_free(i); useDfl=TRUE; break; } v->c[0]=i[0]; v->c[1]=i[1]; v->c[2]=i[2]; v->c[3]=i[3]; if (!e && l==4) g_free(i); } break; case SETAction: { gint * i; gsize l=0; i=g_key_file_get_integer_list(f,o->section,dkey,&l,&e); if (e || l!=6) { if (!e) g_free(i); useDfl=TRUE; break; } v->a[0]=i[0]; v->a[1]=i[1]; v->a[2]=i[2]; v->a[3]=i[3]; v->a[4]=i[4]; v->a[5]=i[5]; if (!e && l==6) g_free(i); } break; case SETList: { gsize l=0; switch(o->listtype) { case SETString: { gint i; gchar ** s=g_key_file_get_string_list(f,o->section,dkey,&l,&e); if (e) { useDfl=TRUE; break; } //prune invalid values from s if (o->rest.s) { for (i=0;irest.s[j]);j++) { if (strcmp(s[i],e)==0) keep=TRUE; } if (!keep) { g_free(s[i]); // I think this is ok memmove(s+i,s+i+1, sizeof(gchar *)*(l-i)); // one beyond l for the NULL l--; i--; } } } *nv=l; if (l) v->l=malloc(l*sizeof(SETOptionValue)); else v->l=NULL; for (i=0;il[i].s=g_strdup(s[i]); } g_strfreev(s); } break; case SETBool: { gint i; gboolean * b; b=g_key_file_get_boolean_list(f,o->section,dkey,&l,&e); if (e) { useDfl=TRUE; break; } *nv=l; if (l) v->l=malloc(sizeof(SETOptionValue)*l); else v->l=NULL; for (i=0;il[i].b=b[i]; } g_free(b); } case SETInt: { gint i; gint * b; b=g_key_file_get_integer_list(f,o->section,dkey,&l,&e); if (e) { useDfl=TRUE; break; } *nv=l; if (l) v->l=malloc(sizeof(SETOptionValue)*l); else v->l=NULL; for (i=0;il[i].i=b[i]; } g_free(b); } break; case SETFloat: { gint i; gchar ** s; s=g_key_file_get_string_list(f,o->section,dkey,&l,&e); if (e) { useDfl=TRUE; break; } *nv=l; if (l) v->l=malloc(sizeof(SETOptionValue)*l); else v->l=NULL; for (i=0;il[i].f=g_ascii_strtod(s[i],NULL); } g_strfreev(s); } break; case SETColor: { gint i; gint * b; b=g_key_file_get_integer_list(schemaFile,o->section,o->name,&l,&e); if (e || l%4!=0) { useDfl=TRUE; break; } *nv=l/4; if (l/4) v->l=malloc(sizeof(SETOptionValue)*l/4); else v->l=NULL; for (i=0;il[i].c[0]=b[i*4]; v->l[i].c[1]=b[i*4+1]; v->l[i].c[2]=b[i*4+2]; v->l[i].c[3]=b[i*4+3]; } g_free(b); } break; case SETAction: { gint i; gint * b; b=g_key_file_get_integer_list(f,o->section,dkey,&l,&e); if (e || l%6!=0) { useDfl=TRUE; break; } *nv=l/6; if (l/6) v->l=malloc(sizeof(SETOptionValue)*l/6); else v->l=NULL; for (i=0;il[i].a[0]=b[i*6]; v->l[i].a[1]=b[i*6+1]; v->l[i].a[2]=b[i*6+2]; v->l[i].a[3]=b[i*6+3]; v->l[i].a[4]=b[i*6+4]; v->l[i].a[5]=b[i*6+5]; } g_free(b); } break; default: g_error("invalid t_ for %s",o->name); } } break; default: g_error("invalid o_ for %s",o->name); } if (useDfl && dfl) g_error("no d_ for %s",o->name); else if (useDfl) copy_option_from_default(o); g_free(dkey); } void init_option(gchar * group, gchar * option) { SETOption * o; gchar * val; gchar * key; gboolean screen; if (g_str_has_prefix(option,"s_")) screen=TRUE; else if (g_str_has_prefix(option,"a_")) screen=FALSE; else return; o = malloc(sizeof(SETOption)); bzero(o,sizeof(SETOption)); o->name = g_strdup(option); o->section=g_strdup(group); key = g_strconcat("h_",option,NULL); o->hints = g_key_file_get_string_list(schemaFile,o->section,key,NULL,NULL); g_free(key); key = g_strconcat("o_",option,NULL); val = g_key_file_get_string(schemaFile,group,key,NULL); if (!val) g_error("missing o_ for %s",option); // SHOULD be impossible o->type = string_to_type(val); g_free(val); g_free(key); key=g_strconcat("n_",option,NULL); val = g_key_file_get_string(schemaFile,group,key,NULL); if (!val) g_warning("missing n_ for %s",option); else o->sdesc=val; g_free(key); key=g_strconcat("l_",option,NULL); val = g_key_file_get_string(schemaFile,group,key,NULL); if (!val) g_warning("missing l_ for %s",option); else o->ldesc = val; g_free(key); if (o->type==SETList) { key=g_strconcat("t_",option,NULL); val=g_key_file_get_string(schemaFile,group,key,NULL); if (!val) g_error("list option with no t_ %s",option); o->listtype=string_to_type(val); g_free(val); g_free(key); } if (o->type==SETString || (o->type==SETList && o->listtype==SETString)) { key=g_strconcat("s_",option,NULL); o->rest.s=g_key_file_get_string_list(schemaFile,group,key,NULL,NULL); g_free(key); } else if (o->type==SETInt) { gint * i; gsize l; GError * e = NULL; key=g_strconcat("s_",option,NULL); i=g_key_file_get_integer_list(schemaFile,group,key,&l,&e); if (!e && l==2) { o->rest.i[0]=i[0]; o->rest.i[1]=i[1]; } else { g_error("int option with no or invalid s_ %s",option); } } else if (o->type==SETFloat) { gchar ** s; gsize l; GError * e = NULL; key=g_strconcat("s_",option,NULL); s=g_key_file_get_string_list(schemaFile,group,key,&l,&e); if (s) { if (!e && l==3) { o->rest.f[0]=g_ascii_strtod(s[0],NULL); o->rest.f[1]=g_ascii_strtod(s[1],NULL); o->rest.f[2]=g_ascii_strtod(s[2],NULL); } else g_error ("float option with no or invalid s_ %s",option); g_strfreev(s); } else g_error ("float option with no or invalid s_ %s",option); } else if (o->type==SETAction) { gboolean * b; gsize l; GError * e = NULL; key=g_strconcat("s_",option,NULL); b=g_key_file_get_boolean_list(schemaFile,group,key,&l,&e); if (!e && l==4) { o->rest.a[0]=b[0]; o->rest.a[1]=b[1]; o->rest.a[2]=b[2]; o->rest.a[3]=b[3]; } else g_error("action option with no or invalid s_ %s",option); } load_option(o,TRUE); // load defaults load_option(o,FALSE); SETOptions=g_slist_append(SETOptions,o); } void load_options_for(gchar * group) { gsize nKeys; gint i; gchar ** keys = g_key_file_get_keys(schemaFile,group,&nKeys,NULL); for (i=0;itype) { case SETBool: g_key_file_set_boolean(settingsFile,o->section,o->name,o->value.b); break; case SETInt: g_key_file_set_integer(settingsFile,o->section,o->name,o->value.i); break; case SETString: g_key_file_set_string(settingsFile,o->section,o->name,o->value.s); break; case SETColor: g_key_file_set_integer_list(settingsFile,o->section,o->name,o->value.c,4); break; case SETAction: g_key_file_set_integer_list(settingsFile,o->section,o->name,o->value.a,6); break; case SETFloat: g_ascii_dtostr(fb,G_ASCII_DTOSTR_BUF_SIZE,o->value.f); g_key_file_set_string(settingsFile,o->section,o->name,fb); break; case SETList: switch(o->listtype) { case SETBool: { gboolean * b = malloc(sizeof(gboolean)*o->nValue); for(i=0;inValue;i++) b[i]=o->value.l[i].b; g_key_file_set_boolean_list(settingsFile,o->section,o->name,b,o->nValue); free(b); } break; case SETInt: { gint * b = malloc(sizeof(gint)*o->nValue); for(i=0;inValue;i++) b[i]=o->value.l[i].i; g_key_file_set_integer_list(settingsFile,o->section,o->name,b,o->nValue); free(b); } break; case SETColor: { gint * b = malloc(sizeof(gint)*o->nValue*4); for(i=0;inValue;i++) { b[i*4]=o->value.l[i].c[0]; b[i*4+1]=o->value.l[i].c[1]; b[i*4+2]=o->value.l[i].c[2]; b[i*4+3]=o->value.l[i].c[3]; } g_key_file_set_integer_list(settingsFile,o->section,o->name,b,o->nValue*4); free(b); } break; case SETAction: { gint * b = malloc(sizeof(gint)*o->nValue*6); for(i=0;inValue;i++) { b[i*6]=o->value.l[i].a[0]; b[i*6+1]=o->value.l[i].a[1]; b[i*6+2]=o->value.l[i].a[2]; b[i*6+3]=o->value.l[i].a[3]; b[i*6+4]=o->value.l[i].a[4]; b[i*6+5]=o->value.l[i].a[5]; } g_key_file_set_integer_list(settingsFile,o->section,o->name,b,o->nValue*6); free(b); } break; case SETString: { gchar ** s = malloc(sizeof(gchar *)*o->nValue); for(i=0;inValue;i++) s[i]=o->value.l[i].s; g_key_file_set_string_list(settingsFile,o->section,o->name,(const gchar **)s,o->nValue); free(s); } break; case SETFloat: { gchar ** s = malloc(sizeof(gchar)*o->nValue); for(i=0;inValue;i++) { s[i]=malloc(G_ASCII_DTOSTR_BUF_SIZE); g_ascii_dtostr(s[i],G_ASCII_DTOSTR_BUF_SIZE,o->value.l[i].f); } g_key_file_set_string_list(settingsFile,o->section,o->name,(const gchar **)s,o->nValue); for(i=0;inValue;i++) free(s[i]); free(s); } break; default: g_error("Bad list type"); } break; default: g_error("invalid type in save option."); } fn = g_strconcat(g_get_home_dir(),"/.beryl/settings",NULL); g_file_set_contents(fn,g_key_file_to_data(settingsFile,NULL,NULL),-1,NULL); queue_option_changed(o); } void cb_option(GtkWidget * w, SETOption * o) { if (suspend_signals) return; switch(o->type) { case SETBool: if (o->value.b==gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(o->widgets.b))) return; o->value.b=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(o->widgets.b)); break; case SETInt: case SETFloat: { gdouble f; if (GTK_WIDGET(w)==GTK_WIDGET(o->widgets.n.s)) { f=gtk_spin_button_get_value(GTK_SPIN_BUTTON(w)); } else { f=gtk_range_get_value(GTK_RANGE(w)); } if (o->type==SETInt) { if ((gint)f==o->value.i) return; o->value.i=(gint)f; } else { if (f==o->value.f) return; o->value.f=f; } gtk_range_set_value(GTK_RANGE(o->widgets.n.h),f); gtk_spin_button_set_value(GTK_SPIN_BUTTON(o->widgets.n.s),f); } break; case SETString: { const gchar * s; if (o->rest.s && o->rest.s[0]) s = gtk_combo_box_get_active_text(GTK_COMBO_BOX(o->widgets.w)); else s = gtk_entry_get_text(GTK_ENTRY(o->widgets.w)); if (strcmp(s,o->value.s)==0) return; o->value.s=g_strdup(s); } break; case SETColor: { GdkColor c; gint a; gtk_color_button_get_color(GTK_COLOR_BUTTON(o->widgets.w),&c); a=gtk_color_button_get_alpha(GTK_COLOR_BUTTON(o->widgets.w)); if (c.red!=o->value.c[0] || c.green!=o->value.c[1] || c.blue!=o->value.c[2] || a!=o->value.c[3]) { o->value.c[0]=c.red; o->value.c[1]=c.green; o->value.c[2]=c.blue; o->value.c[3]=a; } else return; } break; case SETAction: { gint a[6]={0,0,0,0,0,0}; gint i; if (o->rest.a[0]) { a[0]=0; for(i=0;iwidgets.a.bmod[i]))) a[0]|=nModifiers[i]; a[1]=atoi(gtk_entry_get_text(GTK_ENTRY(o->widgets.a.but))); } if (o->rest.a[1]) { a[2]=0; for(i=0;iwidgets.a.kmod[i]))) a[2]|=nModifiers[i]; a[3]=XStringToKeysym(gtk_entry_get_text(GTK_ENTRY(o->widgets.a.key))); if (a[3]==NoSymbol) a[3]=0; } if (o->rest.a[2]) { a[4]=0; for(i=0;iwidgets.a.e[i]))) a[4]|=1<rest.a[3]) { a[5]=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(o->widgets.a.b))?1:0; } if ((!o->rest.a[0] || (o->value.a[0]==a[0] && o->value.a[1]==a[1])) && (!o->rest.a[1] || (o->value.a[2]==a[2] && o->value.a[3]==a[3])) && (!o->rest.a[2] || o->value.a[4]==a[4]) && (!o->rest.a[3] || o->value.a[5]==a[5])) return; for (i=0;i<6;i++) o->value.a[i]=a[i]; } break; case SETList: { if (o->listtype==SETString && o->rest.s && o->rest.s[0]) { //multiple-choice gint i; gint ns=0; gchar ** s; i=0; while(o->rest.s[i]) i++; s=malloc(sizeof(gchar *)*i); for (i=0;o->rest.s[i];i++) { if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(o->widgets.l[i]))) s[ns++]=o->rest.s[i]; } for (i=0;inValue;i++) g_free(o->value.l[i].s); free(o->value.l); o->value.l=malloc(sizeof(SETOptionValue)*ns); o->nValue=ns; for (i=0;ivalue.l[i].s=g_strdup(s[i]); free(s); //that should work } } break; default: g_warning("Unhandled type for %s",o->name); } save_option(o); } void set_info_pane(GtkWidget * w, gchar * labelMarkup) { if (strcmp(labelMarkup,"")==0) { gtk_widget_hide(infoContainer); } else { gtk_window_set_resizable(GTK_WINDOW(mainWindow),FALSE); gtk_label_set_markup(GTK_LABEL(infoLabel),labelMarkup); gtk_widget_show_all(infoContainer); gtk_window_set_resizable(GTK_WINDOW(mainWindow),TRUE); } } gchar * getmark(SETOption * o) { return g_markup_printf_escaped( "%s\n" "(%s/%s)\n" "%s", o->sdesc, o->section, o->name+2, o->ldesc ); } GtkWidget * my_label_new(gchar * t) { GtkWidget * w = gtk_label_new(t); gtk_misc_set_alignment(GTK_MISC(w),0,0); return w; } void set_widgets_from_option(SETOption * o) { suspend_signals=TRUE; switch(o->type) { case SETBool: gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(o->widgets.w),o->value.b); break; case SETString: if (o->rest.s && o->rest.s[0]) { gint i; for (i=0;o->rest.s[i];i++) { if (strcmp(o->rest.s[i],o->value.s)==0) gtk_combo_box_set_active(GTK_COMBO_BOX(o->widgets.w),i); } } else gtk_entry_set_text(GTK_ENTRY(o->widgets.w),o->value.s); break; case SETInt: case SETFloat: gtk_range_set_value(GTK_RANGE(o->widgets.n.h), (o->type==SETInt?o->value.i:o->value.f)); gtk_spin_button_set_value(GTK_SPIN_BUTTON(o->widgets.n.s), (o->type==SETInt?o->value.i:o->value.f)); break; case SETColor: { GdkColor c; c.red=o->value.c[0]; c.green=o->value.c[1]; c.blue=o->value.c[2]; gtk_color_button_set_color(GTK_COLOR_BUTTON(o->widgets.w),&c); gtk_color_button_set_alpha(GTK_COLOR_BUTTON(o->widgets.w), o->value.c[3]); } break; case SETAction: if (o->rest.a[0]) { gint i; for(i=0;iwidgets.a.bmod[i]), (o->value.a[0] & nModifiers[i])); } gtk_entry_set_text(GTK_ENTRY(o->widgets.a.but),o->value.a[1]? g_strdup_printf("%d",o->value.a[1]):"Disabled"); } if (o->rest.a[1]) { gint i; gchar * s; for(i=0;iwidgets.a.kmod[i]), (o->value.a[2] & nModifiers[i])); } s=XKeysymToString(o->value.a[3]); if (!s) { o->value.a[2]=0; s="Disabled"; } gtk_entry_set_text(GTK_ENTRY(o->widgets.a.key),s); } if (o->rest.a[2]) { gint i; for (i=0;iwidgets.a.e[i]) ,(o->value.a[4]&(1<rest.a[3]) { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(o->widgets.a.b),o->value.a[5]); } break; case SETList: if (o->listtype==SETString && o->rest.s && o->rest.s[0]) { gint i,j; for (i=0;o->rest.s[i];i++) { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(o->widgets.l[i]),FALSE); for (j=0;jnValue;j++) { if (strcmp(o->value.l[j].s,o->rest.s[i])==0) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(o->widgets.l[i]),TRUE); } } } else if (o->listtype==SETString) { gint i; gtk_list_store_clear(o->widgets.s.backing); for (i=0;inValue;i++) { GtkTreeIter it; gtk_list_store_append(o->widgets.s.backing,&it); gtk_list_store_set(o->widgets.s.backing,&it,0,o->value.l[i].s,-1); } } default: break; } suspend_signals=FALSE; } void reset_option(GtkWidget * but, SETResetOption * ro) { SETOption * o = ro->o; if (o->type==SETAction) { switch(ro->resetType) { case 0: o->value.a[0]=o->defaultValue.a[0]; o->value.a[1]=o->defaultValue.a[1]; break; case 1: o->value.a[2]=o->defaultValue.a[2]; o->value.a[3]=o->defaultValue.a[3]; break; case 2: o->value.a[4]=o->defaultValue.a[4]; break; case 3: o->value.a[5]=o->defaultValue.a[5]; break; } } else copy_option_from_default(o); set_widgets_from_option(o); save_option(o); } gboolean has_hint(SETOption * o, const gchar * hint) { gint i; for (i=0;o->hints && o->hints[i];i++) { if (strcmp(o->hints[i],hint)==0) return TRUE; } return FALSE; } static void cb_preview (GtkFileChooser *file_chooser, gpointer data) { GtkWidget *preview; char *filename; GdkPixbuf *pixbuf; gboolean have_preview; preview = GTK_WIDGET (data); filename = gtk_file_chooser_get_preview_filename (file_chooser); pixbuf = NULL; have_preview = FALSE; if (filename) { pixbuf = gdk_pixbuf_new_from_file_at_size (filename, 128, 128, NULL); have_preview = (pixbuf != NULL); g_free (filename); if (pixbuf) gtk_image_set_from_pixbuf (GTK_IMAGE (preview), pixbuf); } if (pixbuf) g_object_unref (pixbuf); gtk_file_chooser_set_preview_widget_active (file_chooser, have_preview); } void modify_sl(SETOption * o) { //re-write the o->nValue/o->value.l based on o->widgets.s.backing gint i; GtkTreeIter it; if (suspend_signals) return; if (o->nValue) { for (i=0;inValue;i++) { g_free(o->value.l[i].s); } free(o->value.l); } //now we have to figure out how many rows... o->nValue=gtk_tree_model_iter_n_children(GTK_TREE_MODEL(o->widgets.s.backing),NULL); if (o->nValue) { o->value.l=malloc(sizeof(SETOptionValue)*o->nValue); for (i=0;inValue;i++) { gtk_tree_model_iter_nth_child(GTK_TREE_MODEL(o->widgets.s.backing),&it,NULL,i); gtk_tree_model_get(GTK_TREE_MODEL(o->widgets.s.backing),&it,0,&o->value.l[i].s,-1); } } else { o->value.l=NULL; } save_option(o); } void cb_browse(GtkWidget * w, SETOption * o) { //make up a file widget GtkWidget * fd; gchar * titl=g_strconcat(_("Browse for "),o->sdesc,NULL); fd = gtk_file_chooser_dialog_new(titl,GTK_WINDOW(mainWindow), has_hint(o,"directory")?GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER: GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL,GTK_RESPONSE_CANCEL, GTK_STOCK_OPEN,GTK_RESPONSE_ACCEPT,NULL); g_free(titl); if (has_hint(o,"image")) { GtkFileFilter * f; GtkWidget * pr; f = gtk_file_filter_new(); if (has_hint(o,"pngonly")) { gtk_file_filter_set_name(f,"PNG Images"); } else { gtk_file_filter_set_name(f,_("Beryl Image Types (PNG,SVG)")); gtk_file_filter_add_mime_type(f,"image/svg"); gtk_file_filter_add_pattern(f,"*.svg"); gtk_file_filter_add_pattern(f,"*.SVG"); } gtk_file_filter_add_mime_type(f,"image/png"); gtk_file_filter_add_pattern(f,"*.png"); gtk_file_filter_add_pattern(f,"*.PNG"); gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(fd),f); gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(fd),f); pr = gtk_image_new(); gtk_file_chooser_set_preview_widget(GTK_FILE_CHOOSER(fd),pr); g_signal_connect(fd,_("update-preview"),G_CALLBACK(cb_preview),pr); } if (o->type == SETString) if (g_file_test(gtk_entry_get_text(o->widgets.sb.e),G_FILE_TEST_EXISTS)) gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(fd),gtk_entry_get_text(o->widgets.sb.e)); if (gtk_dialog_run(GTK_DIALOG(fd))==GTK_RESPONSE_ACCEPT) { gchar * s; s=gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fd)); if (o->type == SETString) gtk_entry_set_text(o->widgets.sb.e,s); else { GtkTreeIter it; GtkTreeSelection * se = gtk_tree_view_get_selection(o->widgets.s.view); if (suspend_signals) return; gtk_tree_selection_unselect_all(se); gtk_list_store_append(o->widgets.s.backing,&it); gtk_list_store_set(o->widgets.s.backing,&it,0,s,-1); gtk_tree_selection_select_iter(se,&it); modify_sl(o); } g_free(s); } gtk_widget_destroy(fd); } GtkWidget * make_info_button_full(SETOption * o,gint rt) { GtkWidget * but; GtkWidget * img; GtkWidget * hb; SETResetOption * ro = malloc(sizeof(SETResetOption)); gboolean str=((o->type==SETAction && rt!=3) || o->type==SETList); if (str) hb = gtk_vbox_new(FALSE,2); else hb = gtk_hbox_new(TRUE,2); but = gtk_button_new(); img = gtk_image_new_from_stock(GTK_STOCK_INFO,GTK_ICON_SIZE_BUTTON); gtk_container_add(GTK_CONTAINER(but),img); g_signal_connect(but,"clicked",G_CALLBACK(set_info_pane),getmark(o)); gtk_box_pack_start(GTK_BOX(hb),but,str,str,0); but = gtk_button_new(); img = gtk_image_new_from_stock(GTK_STOCK_CLEAR,GTK_ICON_SIZE_BUTTON); gtk_container_add(GTK_CONTAINER(but),img); ro->o=o; ro->resetType=rt; g_signal_connect(but,"clicked",G_CALLBACK(reset_option),ro); gtk_box_pack_start(GTK_BOX(hb),but,str,str,0); return hb; } GtkWidget * make_info_button(SETOption * o) { return make_info_button_full(o,0); } void do_if_toggle_group(SETOption * o, SETGroupWidget * w) { if (o->defined) return; if (o->type==SETBool && strcmp(o->section,w->group)==0) { GtkWidget * cbox; GtkWidget * box; box = gtk_hbox_new(FALSE,2); cbox = gtk_check_button_new_with_label(o->sdesc); gtk_box_pack_start(GTK_BOX(w->widget),box,FALSE,FALSE,0); gtk_box_pack_start(GTK_BOX(box),make_info_button(o),FALSE,FALSE,0); gtk_box_pack_start(GTK_BOX(box),cbox,TRUE,TRUE,0); o->widgets.w=cbox; g_signal_connect(cbox,"toggled",G_CALLBACK(cb_option),o); o->defined=TRUE; set_widgets_from_option(o); w->hasany=TRUE; } } void do_if_numeric_group(SETOption * o, SETGroupWidget * w) { if (o->defined) return; if ((o->type==SETInt || o->type==SETFloat) && strcmp(o->section,w->group)==0) { GtkWidget * slid; GtkWidget * spun; GtkWidget * box; GtkWidget * slidbox; gdouble min = (o->type==SETInt?o->rest.i[0]:o->rest.f[0]); gdouble max = (o->type==SETInt?o->rest.i[1]:o->rest.f[1]); gdouble pre = (o->type==SETInt?1:o->rest.f[2]); slid = gtk_hscale_new_with_range(min,max,pre); spun = gtk_spin_button_new_with_range(min,max,pre); box = gtk_hbox_new(FALSE,2); slidbox = gtk_vbox_new(FALSE,2); gtk_box_pack_start(GTK_BOX(w->widget),box,FALSE,FALSE,0); gtk_box_pack_start(GTK_BOX(box),make_info_button(o),FALSE,FALSE,0); gtk_box_pack_start(GTK_BOX(box),slidbox,TRUE,TRUE,0); gtk_box_pack_start(GTK_BOX(box),spun,FALSE,FALSE,0); gtk_box_pack_start(GTK_BOX(slidbox),my_label_new(o->sdesc),FALSE,FALSE,0); gtk_box_pack_start(GTK_BOX(slidbox),slid,FALSE,FALSE,0); o->widgets.n.h=GTK_HSCALE(slid); o->widgets.n.s=GTK_SPIN_BUTTON(spun); gtk_scale_set_draw_value(GTK_SCALE(slid),FALSE); gtk_range_set_update_policy(GTK_RANGE(slid),GTK_UPDATE_DISCONTINUOUS); gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spun),GTK_UPDATE_IF_VALID); g_signal_connect(slid,"value-changed",G_CALLBACK(cb_option),o); g_signal_connect(spun,"value-changed",G_CALLBACK(cb_option),o); o->defined=TRUE; set_widgets_from_option(o); w->hasany=TRUE; } } void do_if_string_choice_group(SETOption * o, SETGroupWidget * w) { if (o->defined) return; if ((o->type==SETString) && strcmp(o->section,w->group)==0 && o->rest.s && o->rest.s[0]) { GtkWidget * hbox = gtk_hbox_new(FALSE,2); GtkWidget * vbox = gtk_vbox_new(FALSE,2); gint i; gtk_box_pack_start(GTK_BOX(w->widget),hbox,FALSE,FALSE,0); gtk_box_pack_start(GTK_BOX(hbox),make_info_button(o),FALSE,FALSE,0); gtk_box_pack_start(GTK_BOX(hbox),vbox,TRUE,TRUE,0); gtk_box_pack_start(GTK_BOX(vbox),my_label_new(o->sdesc),FALSE,FALSE,0); o->widgets.w=gtk_combo_box_new_text(); for (i=0;o->rest.s[i];i++) { gtk_combo_box_append_text(GTK_COMBO_BOX(o->widgets.w),o->rest.s[i]); } set_widgets_from_option(o); g_signal_connect(o->widgets.w,"changed",G_CALLBACK(cb_option),o); gtk_box_pack_start(GTK_BOX(vbox),o->widgets.w,FALSE,FALSE,0); o->defined=TRUE; w->hasany=TRUE; } } void do_if_string_group(SETOption * o, SETGroupWidget * w) { if (o->defined) return; if ((o->type==SETString) && strcmp(o->section,w->group)==0 && (!o->rest.s || !o->rest.s[0])) { GtkWidget * hbox = gtk_hbox_new(FALSE,2); GtkWidget * vbox = gtk_vbox_new(FALSE,2); GtkWidget * hbox2 = gtk_hbox_new(FALSE,2); gtk_box_pack_start(GTK_BOX(w->widget),hbox,FALSE,FALSE,0); gtk_box_pack_start(GTK_BOX(hbox),make_info_button(o),FALSE,FALSE,0); gtk_box_pack_start(GTK_BOX(hbox),vbox,TRUE,TRUE,0); gtk_box_pack_start(GTK_BOX(vbox),my_label_new(o->sdesc),FALSE,FALSE,0); o->widgets.w = gtk_entry_new(); if (!o->value.s) o->value.s=g_strdup(""); // wuh? set_widgets_from_option(o); g_signal_connect(o->widgets.w,"changed",G_CALLBACK(cb_option),o); gtk_box_pack_start(GTK_BOX(hbox2),o->widgets.w,TRUE,TRUE,0); if (has_hint(o,"file")) { o->widgets.sb.b=GTK_BUTTON(gtk_button_new_with_label(_("Browse"))); gtk_button_set_image(o->widgets.sb.b,gtk_image_new_from_stock(GTK_STOCK_OPEN,GTK_ICON_SIZE_BUTTON)); gtk_box_pack_start(GTK_BOX(hbox2),GTK_WIDGET(o->widgets.sb.b),FALSE,FALSE,0); g_signal_connect(o->widgets.sb.b,"clicked",G_CALLBACK(cb_browse),o); } gtk_box_pack_start(GTK_BOX(vbox),hbox2,FALSE,FALSE,0); o->defined=TRUE; w->hasany=TRUE; } } void do_if_color_group(SETOption * o, SETGroupWidget * w) { if (o->defined) return; if ((o->type==SETColor) && strcmp(o->section,w->group)==0) { GtkWidget * hbox; GtkWidget * cbut; hbox = gtk_hbox_new(FALSE,2); gtk_box_pack_start(GTK_BOX(w->widget),hbox,FALSE,FALSE,0); gtk_box_pack_start(GTK_BOX(hbox),make_info_button(o),FALSE,FALSE,0); gtk_box_pack_start(GTK_BOX(hbox),my_label_new(o->sdesc),TRUE,TRUE,0); cbut=gtk_color_button_new(); gtk_color_button_set_use_alpha(GTK_COLOR_BUTTON(cbut),TRUE); gtk_box_pack_start(GTK_BOX(hbox),cbut,FALSE,FALSE,0); o->widgets.w=cbut; g_signal_connect(cbut,"color-set",G_CALLBACK(cb_option),o); o->defined=TRUE; set_widgets_from_option(o); w->hasany=TRUE; } } void do_if_action_group(SETOption * o, SETGroupWidget * w) { if (o->defined) return; if ((o->type==SETAction) && strcmp(o->section,w->group)==0) { if (!o->rest.a[0] && !o->rest.a[1] && !o->rest.a[2] && !o->rest.a[3]) { o->defined=TRUE; return; //these are dbus-only calls } o->defined=TRUE; w->hasany=TRUE; set_widgets_from_option(o); } } void do_if_bell_group(SETOption * o, SETGroupWidget * w) { if ((o->type==SETAction) && strcmp(o->section,w->group)==0) { if (o->rest.a[3]) { GtkWidget * hbox = gtk_hbox_new(FALSE,2); gtk_box_pack_start(GTK_BOX(w->widget),hbox,FALSE,FALSE,0); gtk_box_pack_start(GTK_BOX(hbox),make_info_button_full(o,3),FALSE,FALSE,0); o->widgets.a.b=GTK_CHECK_BUTTON(gtk_check_button_new_with_label( g_strconcat(o->sdesc," on System Bell",NULL))); gtk_box_pack_start(GTK_BOX(hbox),GTK_WIDGET(o->widgets.a.b),TRUE,TRUE,0); g_signal_connect(o->widgets.a.b,"toggled",G_CALLBACK(cb_option),o); w->hasany=TRUE; } } } void make_key_button_stuff(SETOption * o, SETGroupWidget * w, gint p) { GtkEntry * entry; GtkCheckButton ** mods; gint i; GtkWidget * tab; GtkWidget * vbox2; GtkWidget * hbox2; GtkWidget * hbox; GtkWidget * fram; if (p==1) mods=o->widgets.a.kmod; else mods=o->widgets.a.bmod; fram = gtk_frame_new(o->sdesc); gtk_box_pack_start(GTK_BOX(w->widget),fram,FALSE,FALSE,0); hbox = gtk_hbox_new(FALSE,2); gtk_container_add(GTK_CONTAINER(fram),hbox); gtk_box_pack_start(GTK_BOX(hbox),make_info_button_full(o,p),FALSE,FALSE,0); vbox2 = gtk_vbox_new(FALSE,2); gtk_box_pack_start(GTK_BOX(hbox),vbox2,TRUE,TRUE,0); entry = GTK_ENTRY(gtk_entry_new()); if (p==1) o->widgets.a.key=entry; else o->widgets.a.but=entry; gtk_entry_set_width_chars(entry,8); hbox2=gtk_hbox_new(FALSE,2); gtk_box_pack_start(GTK_BOX(vbox2),hbox2,FALSE,FALSE,0); if (o->value.a[3]==0) o->value.a[2]=0; tab = gtk_table_new(0,0,FALSE); gtk_box_pack_start(GTK_BOX(hbox2),my_label_new(_("Modifier Keys:")),FALSE,FALSE,0); gtk_box_pack_start(GTK_BOX(hbox2),tab,TRUE,TRUE,0); for(i=0;itype==SETAction) && strcmp(o->section,w->group)==0) { if (o->rest.a[1]) { make_key_button_stuff(o,w,1); w->hasany=TRUE; } } } void do_if_button_group(SETOption * o, SETGroupWidget * w) { if ((o->type==SETAction) && strcmp(o->section,w->group)==0) { if (o->rest.a[0]) { make_key_button_stuff(o,w,0); w->hasany=TRUE; } } } void do_if_edge_group(SETOption * o, SETGroupWidget * w) { if ((o->type==SETAction) && strcmp(o->section,w->group)==0) { if (o->rest.a[2]) { gint i; GtkWidget * fram2; GtkWidget * tab; GtkWidget * hbox; fram2=gtk_frame_new(o->sdesc); tab=gtk_table_new(0,0,FALSE); gtk_box_pack_start(GTK_BOX(w->widget),fram2,FALSE,FALSE,0); hbox = gtk_hbox_new(FALSE,2); gtk_container_add(GTK_CONTAINER(fram2),hbox); gtk_box_pack_start(GTK_BOX(hbox),make_info_button_full(o,2),FALSE,FALSE,0); gtk_box_pack_start(GTK_BOX(hbox),tab,TRUE,TRUE,0); for (i=0;iwidgets.a.e[i]=GTK_CHECK_BUTTON(gtk_check_button_new_with_label(edges[i])); gtk_table_attach_defaults(GTK_TABLE(tab),GTK_WIDGET(o->widgets.a.e[i]),edgecols[i],edgecols[i]+1,edgerows[i],edgerows[i]+1); g_signal_connect(o->widgets.a.e[i],"toggled",G_CALLBACK(cb_option),o); } w->hasany=TRUE; } } } #define OPT_PER_LINE 3 void do_if_option_list_group(SETOption * o, SETGroupWidget * w) { if (o->defined) return; if (strcmp(o->section,w->group)==0 && o->type==SETList && o->listtype==SETString && o->rest.s && o->rest.s[0]) { GtkWidget * hbox, *vbox, *tabl, *fram; gint i, l=-1, c=0; hbox = gtk_hbox_new(FALSE,2); fram = gtk_frame_new(o->sdesc); gtk_box_pack_start(GTK_BOX(w->widget),fram,FALSE,FALSE,0); gtk_container_add(GTK_CONTAINER(fram),hbox); gtk_box_pack_start(GTK_BOX(hbox),make_info_button(o),FALSE,FALSE,0); vbox = gtk_vbox_new(FALSE,2); gtk_box_pack_start(GTK_BOX(hbox),vbox,TRUE,TRUE,0); tabl=gtk_table_new(OPT_PER_LINE,1,TRUE); gtk_box_pack_start(GTK_BOX(vbox),tabl,FALSE,FALSE,0); i=0; while(o->rest.s[i]) i++; o->widgets.l=malloc(sizeof(GtkWidget *)*i); for (i=0;o->rest.s[i];i++) { GtkWidget * cbut; if (i%OPT_PER_LINE==0) { l++; c=0; } else c++; cbut = gtk_check_button_new_with_label(o->rest.s[i]); gtk_table_attach_defaults(GTK_TABLE(tabl),cbut,c,c+1,l,l+1); o->widgets.l[i]=cbut; g_signal_connect(cbut,"toggled",G_CALLBACK(cb_option),o); } set_widgets_from_option(o); o->defined=TRUE; w->hasany=TRUE; } } void cb_sl_edited(GtkWidget * w, gchar * treepath, gchar * value, SETOption * o) { GtkTreeIter it; if (suspend_signals) return; gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(o->widgets.s.backing),&it,treepath); gtk_list_store_set(o->widgets.s.backing,&it,0,value,-1); //modify_sl(o); } void cb_sl_select(GtkTreeSelection * sel, SETOption * o) { GtkTreeIter it; GtkTreeModel * mod; gboolean p; p=gtk_tree_selection_get_selected(sel,&mod,&it); gtk_widget_set_sensitive(GTK_WIDGET(o->widgets.s.rem),p); gtk_widget_set_sensitive(GTK_WIDGET(o->widgets.s.up),p); gtk_widget_set_sensitive(GTK_WIDGET(o->widgets.s.dn),p); } void cb_sl_add(GtkWidget * w, SETOption * o) { GtkTreeIter it; GtkTreeSelection * s = gtk_tree_view_get_selection(o->widgets.s.view); if (suspend_signals) return; gtk_tree_selection_unselect_all(s); gtk_list_store_append(o->widgets.s.backing,&it); gtk_list_store_set(o->widgets.s.backing,&it,0,"",-1); gtk_tree_selection_select_iter(s,&it); } void cb_sl_rem(GtkWidget * w, SETOption * o) { GtkTreeIter it; GtkTreeModel * mod; GtkTreeSelection * s = gtk_tree_view_get_selection(o->widgets.s.view); if (suspend_signals) return; if (gtk_tree_selection_get_selected(s,&mod,&it)) gtk_list_store_remove(GTK_LIST_STORE(mod),&it); } void cb_row_changed(GtkWidget * w, GtkTreePath * p, GtkTreeIter * i, SETOption *o) { if (suspend_signals) return; modify_sl(o); } void cb_row_del(GtkWidget * w, GtkTreePath * p, SETOption *o) { if (suspend_signals) return; modify_sl(o); } void move_item(SETOption * o, gboolean up) { GtkTreeIter it; GtkTreeModel * mod; GtkTreeSelection * s = gtk_tree_view_get_selection(o->widgets.s.view); if (suspend_signals) return; if (gtk_tree_selection_get_selected(s,&mod,&it)) { GtkTreeIter nit; if (up) { gchar * s = gtk_tree_model_get_string_from_iter(mod,&it); GtkTreePath * p = gtk_tree_path_new_from_string(s); g_free(s); if (!gtk_tree_path_prev(p)) { g_free(p); return; } s=gtk_tree_path_to_string(p); gtk_tree_model_get_iter_from_string(mod,&nit,s); g_free(s); } else { nit=it; if (!gtk_tree_model_iter_next(mod,&nit)) return; } gtk_list_store_swap(GTK_LIST_STORE(mod),&it,&nit); } } void cb_move_up(GtkWidget * w, SETOption * o) { move_item(o,TRUE); } void cb_move_dn(GtkWidget * w, SETOption * o) { move_item(o,FALSE); } void do_if_string_list_group(SETOption * o, SETGroupWidget * w) { if (o->defined) return; if (strcmp(o->section,w->group)==0 && o->type==SETList && o->listtype==SETString && (!o->rest.s || !o->rest.s[0])) { GtkWidget * hbox; GtkCellRenderer * celr; GtkWidget * fram; GtkTreeViewColumn * col; GtkScrolledWindow * win; GtkWidget * vbox; if (strcmp(o->section,"_")==0 && strcmp(o->name,"a_active_plugins")==0) { o->defined=TRUE; return; } fram = gtk_frame_new(o->sdesc); hbox = gtk_hbox_new(FALSE,2); gtk_box_pack_start(GTK_BOX(w->widget),fram,FALSE,FALSE,0); gtk_container_add(GTK_CONTAINER(fram),hbox); gtk_box_pack_start(GTK_BOX(hbox),make_info_button(o),FALSE,FALSE,0); o->widgets.s.backing=gtk_list_store_new(1,G_TYPE_STRING); celr = GTK_CELL_RENDERER(gtk_cell_renderer_text_new()); g_signal_connect(celr,"edited",G_CALLBACK(cb_sl_edited),o); g_object_set(celr,"editable",TRUE,NULL); col = gtk_tree_view_column_new_with_attributes(o->sdesc,GTK_CELL_RENDERER(celr),"text",0,NULL); o->widgets.s.view=GTK_TREE_VIEW(gtk_tree_view_new_with_model(GTK_TREE_MODEL(o->widgets.s.backing))); gtk_tree_view_set_reorderable(o->widgets.s.view,TRUE); gtk_tree_view_set_headers_visible(o->widgets.s.view,FALSE); gtk_tree_view_append_column(o->widgets.s.view,col); win = GTK_SCROLLED_WINDOW(gtk_scrolled_window_new(NULL,NULL)); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(win),GTK_POLICY_AUTOMATIC,GTK_POLICY_AUTOMATIC); gtk_container_add(GTK_CONTAINER(win),GTK_WIDGET(o->widgets.s.view)); gtk_box_pack_start(GTK_BOX(hbox),GTK_WIDGET(win),TRUE,TRUE,0); o->widgets.s.add=GTK_BUTTON(gtk_button_new_from_stock(GTK_STOCK_ADD)); if (has_hint(o,"file")) { o->widgets.s.bro=GTK_BUTTON(gtk_button_new_with_label(_("Browse"))); gtk_button_set_image(o->widgets.s.bro,gtk_image_new_from_stock( GTK_STOCK_OPEN,GTK_ICON_SIZE_BUTTON)); g_signal_connect(o->widgets.s.bro,"clicked",G_CALLBACK(cb_browse),o); } o->widgets.s.rem=GTK_BUTTON(gtk_button_new_from_stock(GTK_STOCK_DELETE)); vbox = gtk_vbox_new(FALSE,2); gtk_box_pack_start(GTK_BOX(hbox),vbox,FALSE,FALSE,0); gtk_box_pack_start(GTK_BOX(vbox),GTK_WIDGET( o->widgets.s.up=GTK_BUTTON(gtk_button_new())),FALSE,FALSE,0); gtk_box_pack_end(GTK_BOX(vbox),GTK_WIDGET( o->widgets.s.dn=GTK_BUTTON(gtk_button_new())),FALSE,FALSE,0); gtk_container_add(GTK_CONTAINER(o->widgets.s.up), gtk_image_new_from_stock(GTK_STOCK_GO_UP,GTK_ICON_SIZE_BUTTON)); gtk_container_add(GTK_CONTAINER(o->widgets.s.dn), gtk_image_new_from_stock(GTK_STOCK_GO_DOWN,GTK_ICON_SIZE_BUTTON)); gtk_widget_set_sensitive(GTK_WIDGET(o->widgets.s.rem),FALSE); gtk_widget_set_sensitive(GTK_WIDGET(o->widgets.s.up),FALSE); gtk_widget_set_sensitive(GTK_WIDGET(o->widgets.s.dn),FALSE); vbox = gtk_vbox_new(FALSE,2); gtk_box_pack_start(GTK_BOX(hbox),vbox,FALSE,FALSE,0); gtk_box_pack_start(GTK_BOX(vbox),GTK_WIDGET(o->widgets.s.add),FALSE,FALSE,0); if (has_hint(o,"file")) gtk_box_pack_start(GTK_BOX(vbox),GTK_WIDGET(o->widgets.s.bro),FALSE,FALSE,0); gtk_box_pack_start(GTK_BOX(vbox),GTK_WIDGET(o->widgets.s.rem),FALSE,FALSE,0); g_signal_connect(gtk_tree_view_get_selection(o->widgets.s.view),"changed", G_CALLBACK(cb_sl_select),o); g_signal_connect(o->widgets.s.add,"clicked",G_CALLBACK(cb_sl_add),o); g_signal_connect(o->widgets.s.rem,"clicked",G_CALLBACK(cb_sl_rem),o); g_signal_connect(o->widgets.s.up,"clicked",G_CALLBACK(cb_move_up),o); g_signal_connect(o->widgets.s.dn,"clicked",G_CALLBACK(cb_move_dn),o); gtk_tree_view_set_rules_hint(o->widgets.s.view,TRUE); set_widgets_from_option(o); g_signal_connect(o->widgets.s.backing,"row-changed",G_CALLBACK(cb_row_changed),o); g_signal_connect(o->widgets.s.backing,"row-inserted",G_CALLBACK(cb_row_changed),o); g_signal_connect(o->widgets.s.backing,"row-deleted",G_CALLBACK(cb_row_del),o); o->defined=TRUE; w->hasany=TRUE; } } void do_if_command_string_group(SETOption * o, SETGroupWidget * w) { if (o->defined) return; if (has_hint(o,"command")) do_if_string_group(o,w); } void do_if_simple_string_group(SETOption * o, SETGroupWidget * w) { if (o->defined) return; if (!has_hint(o,"file") && !has_hint(o,"command")) do_if_string_group(o,w); } void do_if_file_string_group(SETOption * o, SETGroupWidget * w) { if (o->defined) return; if (has_hint(o,"file")) { do_if_string_group(o,w); do_if_string_list_group(o,w); } } void do_if_undefined_group(SETOption * o, SETGroupWidget * w) { if (o->defined) return; if (strcmp(o->section,w->group)==0 && !(o->defined)) { //undefined GtkWidget * hbox; hbox=gtk_hbox_new(FALSE,2); gtk_box_pack_start(GTK_BOX(w->widget),hbox,FALSE,FALSE,0); gtk_box_pack_start(GTK_BOX(hbox),make_info_button(o),FALSE,FALSE,0); gtk_box_pack_start(GTK_BOX(hbox),my_label_new(o->sdesc),TRUE,TRUE,0); o->widgets.w=hbox; w->hasany=TRUE; } } void do_if_choice_option_group(SETOption * o, SETGroupWidget * w) { if (o->defined) return; do_if_toggle_group(o,w); do_if_string_choice_group(o,w); do_if_option_list_group(o,w); do_if_bell_group(o,w); } void setup_actions(gchar * group) { SETGroupWidget z; z.group=group; z.widget=NULL; z.hasany=FALSE; g_slist_foreach(SETOptions,(GFunc)do_if_action_group,&z); } void do_page(gchar * group,GFunc func,gchar * label, GtkWidget * notebook) { SETGroupWidget z; GtkWidget * scrol = gtk_scrolled_window_new(NULL,NULL); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrol) ,GTK_POLICY_AUTOMATIC,GTK_POLICY_AUTOMATIC); GtkWidget * vbox = gtk_vbox_new(FALSE,6); gtk_container_set_border_width(GTK_CONTAINER(vbox),4); z.group=group; z.widget=vbox; z.hasany=FALSE; g_slist_foreach(SETOptions,func,&z); gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrol),vbox); if (z.hasany) gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrol,gtk_label_new(label)); } void do_option_page(gchar * group, GtkWidget * notebook) { load_options_for(group); //okay now we can lay out a notebook gtk_notebook_set_scrollable(GTK_NOTEBOOK(notebook),TRUE); do_page(group,(GFunc)do_if_choice_option_group,_("Choices"),notebook); do_page(group,(GFunc)do_if_numeric_group,_("Numeric Values"),notebook); do_page(group,(GFunc)do_if_command_string_group,_("Commands"),notebook); do_page(group,(GFunc)do_if_simple_string_group,_("Strings"),notebook); do_page(group,(GFunc)do_if_file_string_group,_("Filenames"),notebook); do_page(group,(GFunc)do_if_color_group,_("Colors"),notebook); do_page(group,(GFunc)do_if_key_group,_("Keyboard"),notebook); do_page(group,(GFunc)do_if_button_group,_("Mouse"),notebook); do_page(group,(GFunc)do_if_edge_group,_("Screen Edges & Corners"),notebook); do_page(group,(GFunc)do_if_string_list_group,_("String Lists"),notebook); setup_actions(group); //gtk_notebook_append_page(GTK_NOTEBOOK(notebook), // do_page(group,(GFunc)do_if_undefined_group),gtk_label_new("Unhandled")); } void set_plugin_active(gchar * plugin,gboolean active) { GtkTreeIter it; gboolean k; for(k=gtk_tree_model_get_iter_first(GTK_TREE_MODEL(pluginList),&it);k; k=gtk_tree_model_iter_next(GTK_TREE_MODEL(pluginList),&it)) { gchar * pl; gtk_tree_model_get(GTK_TREE_MODEL(pluginList),&it,PluginName,&pl,-1); if (strcmp(pl,plugin)==0) gtk_list_store_set(pluginList,&it,PluginEnabled,active,-1); g_free(pl); } } gboolean get_plugin_active(gchar * plugin) { GtkTreeIter it; gboolean k,b; if (strcmp(plugin,"dbus")==0) return TRUE; if (strcmp(plugin,"settings")==0) return TRUE; b=FALSE; for(k=gtk_tree_model_get_iter_first(GTK_TREE_MODEL(pluginList),&it);k; k=gtk_tree_model_iter_next(GTK_TREE_MODEL(pluginList),&it)) { gchar * pl; gtk_tree_model_get(GTK_TREE_MODEL(pluginList),&it,PluginName,&pl,-1); if (strcmp(pl,plugin)==0) { gtk_tree_model_get(GTK_TREE_MODEL(pluginList),&it,PluginEnabled,&b,-1); } g_free(pl); } return b; } void doing_active_plugins(SETOption * o, gpointer p) { if (strcmp(o->name,"a_active_plugins")==0 && strcmp(o->section,"_")==0) { //o is of type list[string] gint i; for(i=0;inValue;i++) { //set the plugins active //by first finding them... GtkTreeIter it; gboolean k; for(k=gtk_tree_model_get_iter_first(GTK_TREE_MODEL(pluginList),&it);k; k=gtk_tree_model_iter_next(GTK_TREE_MODEL(pluginList),&it)) { gchar * pl; gtk_tree_model_get(GTK_TREE_MODEL(pluginList),&it,PluginName,&pl,-1); if (strcmp(pl,o->value.l[i].s)==0 || strcmp(pl,"_")==0) // yeah sets it more than once, I know gtk_list_store_set(pluginList,&it,PluginEnabled,TRUE,-1); if (strcmp(pl,"_")==0) gtk_list_store_set(pluginList,&it,PluginCanEnable,FALSE,-1); g_free(pl); } } } } void do_active_plugins() { g_slist_foreach(SETOptions,(GFunc)doing_active_plugins,NULL); } void cb_showpage(GtkWidget * w, GtkWidget * p) { gint i; GtkTreeIter it; GtkTreeSelection * Select; Select=GTK_TREE_SELECTION(w); GtkTreeModel * mod; gchar * nam; if (gtk_bin_get_child(GTK_BIN(p))) { gtk_container_remove(GTK_CONTAINER(p),gtk_bin_get_child(GTK_BIN(p))); } if (gtk_tree_selection_get_selected(Select,&mod,&it)) { gtk_tree_model_get(mod,&it,PluginName,&nam,-1); } else return; if (!nam) return; for (i=0;i%s\n" "[%s] %s", _(shortdesc),groups[i],_(longdesc)); gtk_list_store_set(pluginList,&t,PluginName,groups[i],ShortDesc,shortdesc, LongDesc,longdesc,Markup,mark,PluginIcon,p,PluginEnabled,FALSE,PluginCanEnable,TRUE,-1); g_free(mark); g_free(shortdesc); g_free(longdesc); SETOptionPages[page].name=g_strdup(groups[i]); SETOptionPages[page].widget=gtk_notebook_new(); g_object_ref(SETOptionPages[page].widget); do_option_page(groups[i],SETOptionPages[page].widget); page++; } g_strfreev(groups); do_unlisted_plugins(); gtk_box_pack_start(box,GTK_WIDGET(win),FALSE,FALSE,0); gtk_box_pack_start(box,gtk_vseparator_new(),FALSE,FALSE,0); pluginContainer = gtk_alignment_new(0,0,1,1); gtk_container_add(GTK_CONTAINER(pluginContainer),SETOptionPages[0].widget); { GtkWidget * vbox, *hbox; GtkWidget * but; GtkWidget * win; vbox = gtk_vbox_new(FALSE,2); gtk_box_pack_start(GTK_BOX(vbox),GTK_WIDGET(pluginContainer),TRUE,TRUE,0); infoLabel=gtk_label_new(""); hbox = gtk_hbox_new(FALSE,2); infoContainer=hbox; g_object_ref(hbox); gtk_box_pack_start(GTK_BOX(vbox),hbox,FALSE,FALSE,0); but=gtk_button_new_with_label(_("Hide")); gtk_button_set_image(GTK_BUTTON(but), gtk_image_new_from_stock(GTK_STOCK_CLOSE,GTK_ICON_SIZE_BUTTON)); g_signal_connect(but,"clicked",G_CALLBACK(set_info_pane),""); win = gtk_scrolled_window_new(NULL,NULL); gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(win),infoLabel); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(win), GTK_POLICY_AUTOMATIC,GTK_POLICY_NEVER); gtk_box_pack_start(GTK_BOX(hbox),but,FALSE,FALSE,0); gtk_box_pack_start(GTK_BOX(hbox),win,TRUE,TRUE,0); gtk_box_pack_start(box,GTK_WIDGET(vbox),TRUE,TRUE,0); gtk_misc_set_alignment(GTK_MISC(infoLabel),0,0); gtk_label_set_line_wrap(GTK_LABEL(_(infoLabel)),TRUE); //gtk_widget_set_size_request(GTK_LABEL(infoLabel),200,-1); //gtk_label_set_max_width_chars(GTK_LABEL(infoLabel),50); } do_active_plugins(); g_signal_connect(rend,"toggled",G_CALLBACK(cb_toggled),NULL); g_signal_connect(gtk_tree_view_get_selection(SETPluginList),"changed", G_CALLBACK(cb_showpage),pluginContainer); gtk_box_pack_start(ebox,gtk_hseparator_new(),FALSE,FALSE,0); bbox=GTK_BOX(gtk_hbox_new(FALSE,0)); gtk_box_pack_start(ebox,GTK_WIDGET(bbox),FALSE,FALSE,0); { GtkWidget * quitbutton; quitbutton=gtk_button_new_from_stock(GTK_STOCK_QUIT); gtk_box_pack_end(bbox,quitbutton,FALSE,FALSE,0); g_signal_connect(quitbutton,"clicked",G_CALLBACK(cb_main_destroy),NULL); } } void setup_main_window() { mainWindow = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(mainWindow),N_("Beryl Settings Manager ") VERSION); gtk_window_set_resizable(GTK_WINDOW(mainWindow),TRUE); //gtk_window_set_position(GTK_WINDOW(mainWindow),GTK_WIN_POS_CENTER); gtk_window_set_default_size(GTK_WINDOW(mainWindow),780,500); gtk_window_set_default_icon_from_file(PIXMAPS_DIR "/beryl-settings.svg",NULL); gtk_container_set_border_width(GTK_CONTAINER(mainWindow),5); layout_main_window(); g_signal_connect(G_OBJECT (mainWindow), "destroy", G_CALLBACK(cb_main_destroy), NULL); gtk_widget_show_all(mainWindow); gtk_widget_hide(infoContainer); g_timeout_add(1000,dequeue_sig,NULL); } int main(int argc, char ** argv) { gtk_init(&argc,&argv); gchar * smmser; //set the locale stuff setlocale(LC_ALL,""); bindtextdomain("beryl-settings","/usr/share/locale"); textdomain("beryl-settings"); //end locale smmser=g_strconcat(g_get_home_dir(),"/.beryl",NULL); g_mkdir_with_parents(smmser,00755); g_chmod(smmser,00755); g_free(smmser); if (!g_thread_supported()) g_thread_init(NULL); dbus_g_thread_init(); dbcon = dbus_bus_get (DBUS_BUS_SESSION,NULL); if (!dbcon) g_error("couldn't get dbus."); dbus_connection_setup_with_g_main(dbcon,NULL); // send_option_changed_signal("_","active_plugins"); load_schema_files(); setup_main_window(); gtk_main(); return 0; } CVS Admin Powered by ViewCVS 1.0-dev (Powered by ViewCVS) ViewCVS and CVS Help