/*
Silky - A GTK+ client for SILC.
Copyright (C) 2003, 2004, 2005 Toni Willberg
- All log and debug -related stuff lives here.
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
http://silky.sourceforge.net/
*/
#include <glib.h>
#include <glade/glade.h>
#include <gtk/gtk.h>
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "preferences.h"
#include "ui_preferences.h"
#include "ui_console.h"
#include "xmlconfig.h"
#include "xmllayout.h"
#include "log.h"
#include "support.h"
#include "gui.h"
#include "servers.h"
extern GladeXML *xmlmain;
extern gchar *prefpath;
extern xmlDocPtr config_main;
extern SilkyServer *servers;
static struct {
gchar *name; /* human-readable preference name, also used by /set */
gchar *widget; /* widget name */
gint widget_type; /* type of widget */
gint xmloption; /* xml option number */
} preferences[] = {
{ "nickname", "set_user_nickname", WIDGET_ENTRY, CM_USERINFO_NICKNAME },
{ "realname", "set_user_realname", WIDGET_ENTRY, CM_USERINFO_REALNAME },
{ "quit_message", "set_quitmessage", WIDGET_ENTRY, CM_USERINFO_QUITMESSAGE },
{ "highlight_words", "set_opt_hilightwords", WIDGET_ENTRY, CM_GUI_HIGHLIGHTS_WORD },
{ "font", "fontbutton", WIDGET_FONTBUTTON, CM_GUI_FONT },
{ "color_timestamp", "colorbutton_timestamp", WIDGET_COLORBUTTON, CM_GUI_COLORS_TIMESTAMP },
{ "color_nickname", "colorbutton_nickname", WIDGET_COLORBUTTON, CM_GUI_COLORS_NICKNAMES },
{ "color_text", "colorbutton_text", WIDGET_COLORBUTTON, CM_GUI_COLORS_TEXT },
{ "color_action", "colorbutton_action", WIDGET_COLORBUTTON, CM_GUI_COLORS_ACTIONS },
{ "color_background", "colorbutton_background", WIDGET_COLORBUTTON, CM_GUI_COLORS_BACKGROUND },
{ "color_server_messages", "colorbutton_server_messages", WIDGET_COLORBUTTON, CM_GUI_COLORS_SERVERMESSAGES },
{ "color_my_nickname", "colorbutton_my_nickname", WIDGET_COLORBUTTON, CM_GUI_COLORS_MYNICKNAME },
{ "color_my_text", "colorbutton_my_text", WIDGET_COLORBUTTON, CM_GUI_COLORS_MYTEXT },
{ "color_my_action", "colorbutton_my_action", WIDGET_COLORBUTTON, CM_GUI_COLORS_MYACTION },
{ "color_inputbox", "colorbutton_input_box_text", WIDGET_COLORBUTTON, CM_GUI_COLORS_INPUTBOX },
{ "highlight_own_nickname", "set_opt_hilight_own_nick", WIDGET_CHECKBUTTON, CM_GUI_HIGHLIGHTS_OWNNICK },
{ "sign_channel_messages", "set_sign_channel_messages", WIDGET_CHECKBUTTON, CM_SECURITY_SIGN_CHANNEL_MESSAGES },
{ "sign_channel_actions", "set_sign_channel_actions", WIDGET_CHECKBUTTON, CM_SECURITY_SIGN_CHANNEL_ACTIONS },
{ "sign_private_messages", "set_sign_private_messages", WIDGET_CHECKBUTTON, CM_SECURITY_SIGN_PRIVATE_MESSAGES },
{ "sign_private_actions", "set_sign_private_actions", WIDGET_CHECKBUTTON, CM_SECURITY_SIGN_PRIVATE_ACTIONS },
{ "command_history_depth", "set_command_history_depth", WIDGET_SPINBUTTON, CM_GUI_CMDHISTORYDEPTH },
{ "show_tips", "set_tips", WIDGET_CHECKBUTTON, CM_GUI_TIPS },
{ NULL, NULL, 0, 0 }
};
static gchar *boolean_values[2][5] = {
{ PREF_ON, "TRUE", "YES", "1", NULL },
{ PREF_OFF, "FALSE", "NO", "0", NULL }
};
/**
* prefs_load_config:
*
* Attempt to load config file, first from user's homedir. If the file is not
* found there, attempt to load config file from 'PREFIX/share/silky/'. If
* that fails as well, create new config, using hard-coded defaults.
*
* Config is loaded into global variable referenced with xmlDocPtr #config_main.
* This XML document entity is then cleaned up using xml_cleanup_config().
*
* Returns: true if a config was succesfully loaded, false otherwise
**/
gboolean prefs_load_config() {
gchar *globalprefpath;
debug("checking for file '%s'", prefpath);
if( g_file_test(prefpath, G_FILE_TEST_EXISTS) ) {
debug("..found, trying to load and parse it");
config_main = xml_read_config(CONFIG_MAIN, prefpath);
} else {
debug("..not found, trying to load a site-wide config...");
#ifdef SILKY_WIN32
globalprefpath = ".\\data\\silky.conf";
#else
globalprefpath = g_strconcat(GLADEDIR, "silky.conf", NULL);
#endif
if( g_file_test(globalprefpath, G_FILE_TEST_EXISTS) ) {
debug("..found, trying to load and parse it");
config_main = xml_read_config(CONFIG_MAIN, globalprefpath);
} else {
debug("..not found, loading config from hardcoded defaults");
if( !(config_main = xml_create_config(CONFIG_MAIN)) )
debug("could not create new config, aborting");
else debug("new config created, continuing");
}
}
if( !config_main ) return FALSE;
xml_cleanup_config(CONFIG_MAIN);
return TRUE;
}
/**
* prefs_str_to_bool:
* @val: a string with boolean meaning
*
* See array boolean_values[ ][ ] (preferences.c) for list of allowed values.
*
* Returns: true if val contains string meaning 'true', false otherwise
**/
gboolean prefs_str_to_bool(gchar *val) {
gint i = 0;
while(boolean_values[0][i]) {
if( !g_ascii_strcasecmp(val, boolean_values[0][i]) ) return TRUE;
i++;
}
return FALSE;
}
/**
* prefs_bool_to_str:
* @val: a boolean value
*
* Returns: PREF_ON macro if val is true, PREF_OFF otherwise
**/
gchar *prefs_bool_to_str(gboolean val) {
if(val) return PREF_ON;
return PREF_OFF;
}
gchar *pref_type_as_string(gint type) {
switch(type) {
case WIDGET_ENTRY: return "entry";
case WIDGET_CHECKBUTTON: return "checkbutton";
case WIDGET_COLORBUTTON: return "colorbutton";
case WIDGET_FONTBUTTON: return "fontbutton";
case WIDGET_SPINBUTTON: return "spinbutton";
default: return "<UNKNOWN>";
}
}
/**
* prefs_populate_gui:
*
* Take values from #xmlDocPtr #config_main and sets them to widgets in
* preferences window.
*
* Should always be called before preferences window is shown.
**/
void prefs_populate_gui() {
GtkWidget *w;
GdkColor color;
gchar *val;
gint i = 0;
debug("Starting to populate preferences GUI");
while( preferences[i].name ) {
if( !preferences[i].widget ) continue;
w = glade_xml_get_widget(xmlmain, preferences[i].widget);
val = xml_get_option(CONFIG_MAIN, preferences[i].xmloption);
debug("Setting %s '%s' to '%s'", pref_type_as_string(preferences[i].widget_type), preferences[i].widget, val);
switch(preferences[i].widget_type) {
case WIDGET_ENTRY:
gtk_entry_set_text(GTK_ENTRY(w), val);
break;
case WIDGET_CHECKBUTTON:
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), prefs_str_to_bool(val));
break;
case WIDGET_FONTBUTTON:
if (val && strlen(val) > 1) {
gtk_font_button_set_font_name(GTK_FONT_BUTTON(w), val);
} else {
debug_info("No font set in preferences, falling back to 'Sans 10'");
gtk_font_button_set_font_name(GTK_FONT_BUTTON(w), "Sans 10"); /* default font, GtkFontButton requires some */
}
break;
case WIDGET_COLORBUTTON:
if (gdk_color_parse(val, &color))
gtk_color_button_set_color(GTK_COLOR_BUTTON(w), &color);
break;
case WIDGET_SPINBUTTON:
gtk_spin_button_set_value(GTK_SPIN_BUTTON(w), atoi(val));
break;
default:
debug("!!! Unknown preference type found: '%s' !!!", preferences[i].name);
break;
}
i++;
}
/* populate servers list */
populate_prefs_serverlist();
/* special cases, populating other than preferences dialog */
/* set the "tip of the day" dialog's status */
w = glade_xml_get_widget(xmlmain, "set_tips_dialog");
val = xml_get_option(CONFIG_MAIN, CM_GUI_TIPS);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), prefs_str_to_bool(val));
debug("Finished");
}
/**
* prefs_save_gui:
*
* Take values from appropriate widgets in preferences window and sets
* corresponding #xmlDoc nodes in #xmlDocPtr #config_main.
*
* Should be called when user pressed Save button in preferences window.
* A call to xml_save_config() should follow.
**/
void prefs_save_gui() {
GtkWidget *w;
gchar *val = NULL;
gint i = 0;
GdkColor color;
debug("Starting to save values from preferences GUI");
while( preferences[i].name ) {
if( !preferences[i].widget ) continue;
w = glade_xml_get_widget(xmlmain, preferences[i].widget);
switch(preferences[i].widget_type) {
case WIDGET_ENTRY:
val = (gchar *)gtk_entry_get_text(GTK_ENTRY(w));
break;
case WIDGET_CHECKBUTTON:
val = prefs_bool_to_str(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w)));
break;
case WIDGET_FONTBUTTON:
val = (gchar *)gtk_font_button_get_font_name(GTK_FONT_BUTTON(w));
break;
case WIDGET_COLORBUTTON:
gtk_color_button_get_color(GTK_COLOR_BUTTON(w), &color);
val = gtk_color_selection_palette_to_string(&color, 1);
break;
case WIDGET_SPINBUTTON:
val = g_strdup_printf("%g", gtk_spin_button_get_value(GTK_SPIN_BUTTON(w)));
break;
default:
debug("!!! Unknown preference type found: '%s' !!!", preferences[i].name);
val = "";
break;
}
debug("Value of %s '%s' is '%s'", pref_type_as_string(preferences[i].widget_type), preferences[i].widget, val);
xml_set_option(CONFIG_MAIN, preferences[i].xmloption, val);
i++;
}
debug("Finished");
}
/**
* prefs_show_to_console:
*
* Take values from #xmlDocPtr #config_main and displays them to console
* window.
**/
void prefs_show_to_console() {
GtkWidget *w;
gchar *val;
gint i = 0;
debug("Starting to populate preferences GUI");
while( preferences[i].name ) {
if( !preferences[i].widget ) continue;
w = glade_xml_get_widget(xmlmain, preferences[i].widget);
val = xml_get_option(CONFIG_MAIN, preferences[i].xmloption);
printconsole(g_strdup_printf("%s = %s", preferences[i].name, val));
i++;
}
debug("Finished");
}
/**
* prefs_get:
* @name: name of config option to be retrieved
*
* Use this to retrieve preference values from user config in memory.
*
* Returns: value of requested preference, or NULL if name is invalid
**/
gchar *prefs_get(gchar *name) {
gint i = 0;
if(!name) {
debug("name == NULL");
return NULL;
}
while( preferences[i].name ) {
if( !g_ascii_strcasecmp(preferences[i].name, name) ) {
debug("found preference option '%s' = \"%s\"", preferences[i].name, xml_get_option(CONFIG_MAIN, preferences[i].xmloption) );
return xml_get_option(CONFIG_MAIN, preferences[i].xmloption);
}
i++;
}
debug("Non-existent preference option requested");
return NULL;
}
/**
* prefs_set:
* @name: name of config option to be set
* @value: desired value
*
* Use this to retrieve preference values from user config in memory.
*
* Returns: true if new value was succesfully set, false otherwise
**/
gboolean prefs_set(gchar *name, gchar *value) {
gint i = 0;
if(!name) {
debug("name == NULL");
return FALSE;
}
if(!value) {
debug("val == NULL");
return FALSE;
}
while( preferences[i].name ) {
if( !g_ascii_strcasecmp(preferences[i].name, name) ) {
debug("found preference option '%s'", preferences[i].name);
if( !xml_set_option(CONFIG_MAIN, preferences[i].xmloption, value) ) {
debug("couln't set option '%s'", name);
return FALSE;
}
debug("succesfully set '%s' to '%s'", name, value);
return TRUE;
}
i++;
}
debug("Non-existent preference option requested");
return FALSE;
}
/**
* prefs_widget_type:
* @name: name of preference in question
*
* Returns: Arbitrary widget type number, from PrefWidgetTypes enum, or 0
* if requested preference does not exist
**/
gint prefs_widget_type(gchar *name) {
gint i = 0;
if(!name) {
debug("name == NULL");
return 0;
}
while( preferences[i].name ) {
if( !g_ascii_strcasecmp(preferences[i].name, name) ) {
debug("found preference option '%s'", preferences[i].name);
return preferences[i].widget_type;
}
i++;
}
debug("Non-existent preference option requested");
return 0;
}
syntax highlighted by Code2HTML, v. 0.9.1