blob: 48c0d67e7267bbc730e6e4bf9c0a38ef4d34993c [file] [log] [blame]
static gint verboseLevel=0;
void G_DEBUG_MSG(gint level, const char *format, ...){
va_list ap;
if (level<verboseLevel){
va_start(ap, format);
g_logv("MakerDialog",G_LOG_LEVEL_DEBUG, format, ap);
va_end(ap);
}
}
static PropertyContext *propertyContext_new(PropertySpec *spec, gpointer userData){
PropertyContext *ctx=g_new(PropertyContext,1);
ctx->spec=spec;
ctx->userData=userData;
return ctx;
}
static void propertyContext_free(gpointer ctx_ptr){
PropertyContext *ctx=(PropertyContext *) ctx_ptr;
g_free(ctx);
}
static void listStore_append(GtkListStore *listStore,const gchar *str,
const gchar *translationContext,
MakerDialogPropertyFlags propertyFlags){
GtkTreeIter iter;
gtk_list_store_append (listStore, &iter);
if (propertyFlags & MAKER_DIALOG_PROPERTY_FLAG_HAS_TRANSLATION){
if (translationContext || propertyFlags & MAKER_DIALOG_PROPERTY_FLAG_TRANSLATION_WITH_CONTEXT){
G_DEBUG_MSG(5,"*** str=%s, _(str)=%s",str,g_dpgettext2(NULL,translationContext,str));
gtk_list_store_set (listStore, &iter,
0, str,
1, g_dpgettext2(NULL,translationContext,str),
-1);
}else{
G_DEBUG_MSG(5,"*** str=%s, _(str)=%s",str,_(str));
gtk_list_store_set (listStore, &iter,
0, str,
1, _(str),
-1);
}
}else{
G_DEBUG_MSG(5,"*** str=%s",str);
gtk_list_store_set (listStore, &iter,
0, str,
-1);
}
}
static gint listStore_find_string(GtkListStore *listStore,const gchar *str,
const gchar *translationContext,
MakerDialogPropertyFlags propertyFlags){
g_assert(str);
G_DEBUG_MSG(4,"*** listStore_find_string(%s,%u)",str,propertyFlags);
int i=0,index=-1;
GtkTreeIter iter;
GValue gValue={0};
if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(listStore), &iter)){
do{
gtk_tree_model_get_value (GTK_TREE_MODEL(listStore), &iter,0,&gValue);
if (strcmp(str,g_value_get_string(&gValue))==0){
index= i;
break;
}
i++;
g_value_unset(&gValue);
}while(gtk_tree_model_iter_next (GTK_TREE_MODEL(listStore), &iter));
}
if (index<0 && !(propertyFlags & MAKER_DIALOG_PROPERTY_FLAG_INEDITABLE)){
/* Add new item*/
listStore_append(listStore, str,translationContext,propertyFlags);
index=i;
}
G_DEBUG_MSG(4,",listStore_find_string(%s,%u) index=%d",str,propertyFlags,index);
return index;
}
static gint combo_find_string_index(GtkComboBox *combo,const gchar *str,
const gchar *translationContext,
MakerDialogPropertyFlags propertyFlags){
GtkListStore *listStore=GTK_LIST_STORE(gtk_combo_box_get_model(combo));
return listStore_find_string(listStore,str, translationContext,propertyFlags);
}
static const gchar *combo_get_active_text(GtkComboBox *combo,GValue *gValue){
GtkTreeIter iter;
if (!gtk_combo_box_get_active_iter(combo,&iter)){
return NULL;
}
GtkListStore *listStore=GTK_LIST_STORE(gtk_combo_box_get_model(combo));
gtk_tree_model_get_value (GTK_TREE_MODEL(listStore), &iter,0,gValue);
return g_value_get_string(gValue);
}
static void propList_free_deep_callback(gpointer data, gpointer user_data){
propertyContext_free(data);
}
static gchar *widget_get_id(gchar *buffer, gint buffer_size,
const gchar *widget_label, const gchar *widget_type){
g_snprintf(buffer,buffer_size,"%s%s%s%s",
WIDGET_ID_PREFIX, widget_label,
(widget_type)? "_" : "",
(widget_type)? widget_type : ""
);
return buffer;
}
/*===== Widget Callback function wraps =====*/
static void on_comboBox_changed_wrap (GtkComboBox *comboBox, gpointer user_data)
{
PropertyContext *ctx=(PropertyContext *)user_data;
GValue value={0};
combo_get_active_text(comboBox, &value);
G_DEBUG_MSG(2,"on_comboBox_changed_wrap(), key=%s value=%s",ctx->spec->key,g_value_get_string(&value));
ctx->spec->setFunc(ctx,&value);
}
static void on_entry_activate_wrap (GtkEntry *entry, gpointer user_data)
{
PropertyContext *ctx=(PropertyContext *)user_data;
GValue value={0};
g_value_init(&value, ctx->spec->valueType);
g_value_set_string(&value,gtk_entry_get_text(entry));
G_DEBUG_MSG(2,"on_entry_activate_wrap(), key=%s value=%s",ctx->spec->key,g_value_get_string(&value));
ctx->spec->setFunc(ctx,&value);
}
static void on_spinButton_value_changed_wrap (GtkSpinButton *button, gpointer user_data)
{
PropertyContext *ctx=(PropertyContext *)user_data;
GValue value={0};
g_value_init(&value, ctx->spec->valueType);
switch(ctx->spec->valueType){
case G_TYPE_INT:
g_value_set_int(&value,(gint) gtk_spin_button_get_value(button));
G_DEBUG_MSG(2,"on_spinButton_value_changed_wrap(), key=%s value=%d",
ctx->spec->key,g_value_get_int(&value));
break;
case G_TYPE_UINT:
g_value_set_uint(&value,(guint) gtk_spin_button_get_value(button));
G_DEBUG_MSG(2,"on_spinButton_value_changed_wrap(), key=%s value=%u",
ctx->spec->key,g_value_get_uint(&value));
break;
case G_TYPE_DOUBLE:
g_value_set_uint(&value, gtk_spin_button_get_value(button));
G_DEBUG_MSG(2,"on_spinButton_value_changed_wrap(), key=%s value=%g",
ctx->spec->key,g_value_get_double(&value));
break;
default:
break;
}
ctx->spec->setFunc(ctx,&value);
}
static void on_toggleButton_toggled_wrap (GtkToggleButton *button, gpointer user_data)
{
PropertyContext *ctx=(PropertyContext *)user_data;
GValue value={0};
g_value_init(&value, ctx->spec->valueType);
g_value_set_boolean(&value, gtk_toggle_button_get_active(button));
G_DEBUG_MSG(2,"on_entry_activate_wrap(), key=%s value=%s",ctx->spec->key,g_value_get_string(&value));
ctx->spec->setFunc(ctx,&value);
}
/*===== End of Widget Callback function wraps =====*/
static gboolean isEmptyString(const gchar *str){
if (!str)
return TRUE;
if (str[0]=='\0')
return TRUE;
return FALSE;
}
typedef enum{
XML_TAG_TYPE_NO_TAG,
XML_TAG_TYPE_EMPTY,
XML_TAG_TYPE_SHORT,
XML_TAG_TYPE_LONG,
XML_TAG_TYPE_BEGIN_ONLY,
XML_TAG_TYPE_END_ONLY,
} XmlTagsType;
#define INDENT_SPACES 4
static void append_indent_space(GString *strBuf, gint indentLevel){
int i,indentLen=indentLevel*INDENT_SPACES;
for(i=0;i<indentLen;i++){
g_string_append_c(strBuf,' ');
}
}
static GString *xml_tags_to_string(const gchar *tagName, XmlTagsType type,
const gchar *attribute, const gchar *value,gint indentLevel){
GString *strBuf=g_string_new(NULL);
append_indent_space(strBuf,indentLevel);
if(type!=XML_TAG_TYPE_NO_TAG){
g_string_append_printf(strBuf,"<%s%s%s%s%s>",
(type==XML_TAG_TYPE_END_ONLY) ? "/": "",
(!isEmptyString(tagName))? tagName : "",
(!isEmptyString(attribute)) ? " ":"", (!isEmptyString(attribute))? attribute : "",
(type==XML_TAG_TYPE_EMPTY) ? "/": ""
);
}
if (type==XML_TAG_TYPE_EMPTY)
return strBuf;
if (type==XML_TAG_TYPE_BEGIN_ONLY)
return strBuf;
if (type==XML_TAG_TYPE_END_ONLY)
return strBuf;
if (type==XML_TAG_TYPE_LONG){
g_string_append_c(strBuf,'\n');
}
if (value){
if (type==XML_TAG_TYPE_LONG || type==XML_TAG_TYPE_NO_TAG){
append_indent_space(strBuf,indentLevel+1);
int i, valueLen=strlen(value);
for(i=0;i<valueLen;i++){
g_string_append_c(strBuf,value[i]);
if (value[i]=='\n'){
append_indent_space(strBuf,indentLevel+1);
}
}
g_string_append_c(strBuf,'\n');
if (type==XML_TAG_TYPE_LONG){
append_indent_space(strBuf,indentLevel);
}
}else{
g_string_append(strBuf,value);
}
}
if (type==XML_TAG_TYPE_LONG || type==XML_TAG_TYPE_SHORT){
g_string_append_printf(strBuf,"</%s>",tagName);
}
return strBuf;
}
static void xml_tags_write(FILE *outF, const gchar *tagName, XmlTagsType type,
const gchar *attribute, const gchar *value){
static int indentLevel=0;
if (type==XML_TAG_TYPE_END_ONLY)
indentLevel--;
GString *strBuf=xml_tags_to_string(tagName, type, attribute, value, indentLevel);
G_DEBUG_MSG(3,",xml_tags_write:%s",strBuf->str);
fprintf(outF,"%s\n",strBuf->str);
if (type==XML_TAG_TYPE_BEGIN_ONLY)
indentLevel++;
g_string_free(strBuf,TRUE);
}
typedef struct{
const gchar *schemasHome;
const gchar *owner;
const gchar *locales;
FILE *outF;
} SchemasFileData;
static void ctx_write_locale(PropertyContext *ctx, SchemasFileData *sData, const gchar *localeStr){
gchar buf[50];
g_snprintf(buf,50,"name=\"%s\"",localeStr);
setlocale(LC_MESSAGES,localeStr);
xml_tags_write(sData->outF,"locale",XML_TAG_TYPE_BEGIN_ONLY,buf,NULL);
xml_tags_write(sData->outF,"short",XML_TAG_TYPE_SHORT,NULL, gettext(ctx->spec->label));
xml_tags_write(sData->outF,"long",XML_TAG_TYPE_LONG,NULL, gettext(ctx->spec->tooltip));
xml_tags_write(sData->outF,"locale",XML_TAG_TYPE_END_ONLY,NULL,NULL);
}
static void ctx_write_callback(gpointer data, gpointer user_data){
PropertyContext *ctx=(PropertyContext *) data;
SchemasFileData *sData=(SchemasFileData *) user_data;
xml_tags_write(sData->outF,"schema",XML_TAG_TYPE_BEGIN_ONLY,NULL,NULL);
gchar buf[STRING_BUFFER_SIZE_DEFAULT];
g_snprintf(buf,STRING_BUFFER_SIZE_DEFAULT,"/schemas%s/%s",sData->schemasHome,ctx->spec->key);
xml_tags_write(sData->outF,"key",XML_TAG_TYPE_SHORT,NULL,buf);
xml_tags_write(sData->outF,"applyto",XML_TAG_TYPE_SHORT,NULL,buf+strlen("/schemas"));
xml_tags_write(sData->outF,"owner",XML_TAG_TYPE_SHORT,NULL,sData->owner);
switch(ctx->spec->valueType){
case G_TYPE_BOOLEAN:
xml_tags_write(sData->outF,"type",XML_TAG_TYPE_SHORT,NULL,"bool");
break;
case G_TYPE_INT:
case G_TYPE_UINT:
xml_tags_write(sData->outF,"type",XML_TAG_TYPE_SHORT,NULL,"int");
break;
case G_TYPE_STRING:
xml_tags_write(sData->outF,"type",XML_TAG_TYPE_SHORT,NULL,"string");
break;
default:
break;
}
if (ctx->spec->defaultValue){
xml_tags_write(sData->outF,"default",XML_TAG_TYPE_SHORT,NULL,ctx->spec->defaultValue);
}
gchar **localeArray=g_strsplit_set(sData->locales,":;",-1);
int i;
for(i=0;localeArray[i]!=NULL;i++){
ctx_write_locale(ctx,sData,localeArray[i]);
}
setlocale(LC_ALL,NULL);
xml_tags_write(sData->outF,"schema",XML_TAG_TYPE_END_ONLY,NULL,NULL);
}
typedef struct{
MakerDialog *self;
gint currentMaxWidth;
const gchar *pageName;
gfloat xalign;
gfloat yalign;
} WidgetAlignment;
static void caculate_max_label_width_callback(gpointer key, gpointer value, gpointer user_data){
WidgetAlignment *wAlignment=(WidgetAlignment *) user_data;
if (!isEmptyString(wAlignment->pageName)){
if (isEmptyString(value) || strcmp(wAlignment->pageName,value)!=0)
return;
}
gchar *keyStr=(gchar *) keyStr;
GtkWidget *widget=maker_dialog_get_widget(wAlignment->self,key,"label");
GtkRequisition requisition;
gtk_widget_size_request (widget,&requisition);
wAlignment->currentMaxWidth=MAX(wAlignment->currentMaxWidth, requisition.width);
}
static void set_label_width_callback(gpointer key, gpointer value, gpointer user_data){
WidgetAlignment *wAlignment=(WidgetAlignment *) user_data;
if (!isEmptyString(wAlignment->pageName)){
if (isEmptyString(value) || strcmp(wAlignment->pageName,value)!=0)
return;
}
gchar *keyStr=(gchar *) keyStr;
GtkWidget *widget=maker_dialog_get_widget(wAlignment->self,key,"label");
gtk_widget_set_size_request(widget, wAlignment->currentMaxWidth,-1);
gtk_misc_set_alignment (GTK_MISC(widget),wAlignment->xalign,wAlignment->yalign);
}
/**
* atob:
* @string: A string.
* @returns: Boolean value represented by @string.
*
* String to boolean.
* It returns FALSE if:
* 1. @string is NULL or have 0 length.
* 2. @string starts with 'F', 'f', 'N' or 'n'.
* 3. @string can be converted to a numeric 0.
*
* Everything else is TRUE.
*/
gboolean atob(const gchar *string){
if (!string)
return FALSE;
if (strlen(string)<=0)
return FALSE;
if (string[0]=='F' || string[0]=='f' || string[0]=='N' || string[0]=='n')
return FALSE;
char *endPtr=NULL;
long int longValue=strtol(string, &endPtr, 10);
if (longValue==0 && *endPtr=='\0'){
// 0
return FALSE;
}
return TRUE;
}