HHu ZhengInit!
dcd27489创建于 3 天前历史提交
/* 
 * This file part of StarDict - A international dictionary for GNOME.
 * http://stardict-4.sourceforge.net
 * Copyright (C) 2005 Evgeniy <dushistov@mail.ru>
 *
 * 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 Library 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.
 */

#ifdef HAVE_CONFIG_H
#  include "config.h"
#endif

#include <glib/gi18n.h>

#include "gconf_file.hpp"

gconf_file::gconf_file(const std::string& path)
{
  cfgname=path;
  if ((gconf_client = gconf_client_get_default())==NULL)
    g_warning("Cannot connect to gconf.\n");
  else
    gconf_client_add_dir(gconf_client, cfgname.c_str(), GCONF_CLIENT_PRELOAD_RECURSIVE, NULL);
}

gconf_file::~gconf_file()
{
	for (std::vector<guint>::iterator it=notification_ids.begin();
			 it!=notification_ids.end(); ++it)
		gconf_client_notify_remove(gconf_client, *it);

	if (!gconf_client)
		return;
  gconf_client_remove_dir(gconf_client, cfgname.c_str(), NULL);
  g_object_unref(gconf_client);
}

bool gconf_file::read_bool(const gchar *sect, const gchar *key, bool& val)
{
  if (!gconf_client)
    return false;
  
	std::string real_key(std::string(sect)+"/"+key);

	GConfValue *gval=gconf_client_get(gconf_client, real_key.c_str(), NULL);
	if (!gval)
		return false;
	val=gconf_value_get_bool(gval);
	gconf_value_free(gval);

	return true;
}

bool gconf_file::read_int(const gchar *sect, const gchar *key, int& val)
{
	if (!gconf_client)
    return false;
	std::string real_key(std::string(sect)+"/"+key);
	GConfValue *gval=gconf_client_get(gconf_client, real_key.c_str(), NULL);
	if (!gval)
		return false;
	val=gconf_value_get_int(gval);
	gconf_value_free(gval);

	return true;
}

bool gconf_file::read_string(const gchar * sect, const gchar *key, std::string& val)
{
	if (!gconf_client)
    return false;

	std::string real_key(std::string(sect)+"/"+key);
  gchar *gconf_val = gconf_client_get_string(gconf_client, real_key.c_str(), NULL);
	if (gconf_val!=NULL) 
		val=gconf_val;

	g_free(gconf_val); 

	return true;
}

bool gconf_file::read_strlist(const gchar * sect, const gchar * key, std::list<std::string>& slist)
{
	if (!gconf_client)
    return false;  

	std::string real_key(std::string(sect)+"/"+key);
	GSList  *gslist = gconf_client_get_list(gconf_client, real_key.c_str(), GCONF_VALUE_STRING, NULL);
	if (!gslist)
		return false;

	slist.clear();
	GSList *p = gslist; 
	while (p) {
		slist.push_back(static_cast<char *>(p->data));
		g_free(p->data);		
		p=g_slist_next(p);
	}
	g_slist_free(gslist);

	return true;
}

void gconf_file::write_bool(const gchar *sect, const gchar *key, bool val)
{
if (!gconf_client)
    return;
  gchar *real_key=g_strdup_printf("%s/%s", sect, key);
  gconf_client_set_bool(gconf_client, real_key, val, NULL);
  g_free(real_key);
}

void gconf_file::write_int(const gchar *sect, const gchar *key, int val)
{
	if (!gconf_client)
		return;
  gchar *real_key=g_strdup_printf("%s/%s", sect, key);
  gconf_client_set_int(gconf_client, real_key, val, NULL);
  g_free(real_key);
}

void gconf_file::write_string(const gchar *sect, const gchar *key, const std::string& val)
{
	if(!gconf_client)
    return;
  gchar *real_key=g_strdup_printf("%s/%s", sect, key);
  gconf_client_set_string(gconf_client, real_key, val.c_str(), NULL);
  g_free(real_key);
}

void gconf_file::write_strlist(const gchar *sect, const gchar *key, const std::list<std::string>& slist)
{
	if (!gconf_client)
		return;

 GSList *gslist = NULL;
 for (std::list<std::string>::const_iterator p=slist.begin(); p!=slist.end(); ++p)
	 gslist = g_slist_append(gslist, const_cast<char *>(p->c_str()));
 
 gchar *real_key=g_strdup_printf("%s/%s", sect, key);
 gconf_client_set_list(gconf_client, real_key, GCONF_VALUE_STRING, gslist, NULL);
 g_free(real_key);
 g_slist_free(gslist);
}

static void gconf_client_notify_func(GConfClient *client, guint cnxn_id,
																		 GConfEntry *entry, gpointer user_data)
{
	change_handler<const baseconfval *> *ch=static_cast<change_handler<const baseconfval *> *>(user_data);
	std::unique_ptr<baseconfval> cv;
	switch (entry->value->type) {
	case GCONF_VALUE_BOOL:
		cv.reset(new confval<bool>);
		static_cast<confval<bool> *>(cv.get())->val=gconf_value_get_bool(entry->value);
		break;
	case GCONF_VALUE_INT:
		cv.reset(new confval<int>);
		static_cast<confval<int> *>(cv.get())->val=gconf_value_get_int(entry->value);
		break;
	case GCONF_VALUE_STRING: {
		cv.reset(new confval<std::string>);
		const gchar *gconf_val=gconf_value_get_string(entry->value);
		if (gconf_val)
			static_cast<confval<std::string> *>(cv.get())->val=gconf_val;		
	}
	case GCONF_VALUE_LIST: {
		cv.reset(new confval<std::list<std::string> >);
		GSList *gslist=gconf_value_get_list(entry->value);
		
		GSList *p = gslist; 
		while (p) {
			static_cast< confval<std::list<std::string> > *>(cv.get())->val.push_back(static_cast<char *>(p->data));
			p=g_slist_next(p);
		}
		
	}
		break;
	default:
		return;
	}
	(*ch)(cv.get());
}

static void gfree_func(gpointer data)
{
	change_handler<baseconfval> *bcv=static_cast<change_handler<baseconfval> *>(data);
	delete bcv;
}

void gconf_file::notify_add(const gchar *sect, const gchar *key, 
														void (*on_change)(const baseconfval*, void *), void *arg)
{
	std::string name(std::string(sect)+"/"+key);
	change_handler<const baseconfval *> *ch=new change_handler<const baseconfval*>;
	ch->on_change=on_change;
	ch->arg=arg;
	guint id=gconf_client_notify_add(gconf_client, name.c_str(), 
																	 gconf_client_notify_func, ch, gfree_func, NULL);
	notification_ids.push_back(id);
}