[Gtk-sharp-list] GConf wrapping

Pablo Baena pbaena@uol.com.ar
12 May 2003 06:48:33 +0000


--=-nwjqIeM6BK56rsFCl8tZ
Content-Type: multipart/related; type="multipart/alternative"; boundary="=-L3dwK4nlFvMCjQrRtxmJ"


--=-L3dwK4nlFvMCjQrRtxmJ
Content-Type: multipart/alternative; boundary="=-GYmCY2ypMZ8fc3Zjb7pa"


--=-GYmCY2ypMZ8fc3Zjb7pa
Content-Type: text/plain
Content-Transfer-Encoding: 7bit

Attached is the documentation to GConf#. I tried to make it as easy to
understand as possible, and provided some introduction to GConf to
first-starters like me. :)

Sorry for not sending a diff, but I cannot check out all the
MonkeyGuide. Right now I have an sporadic connection to the Internet,
that I have to administer as if it were a telephone call to Japan.

This is suppossed to be complementary of Rachel Hestilow's
documentation, to be put before her documentation of the GConf# binding.

On Sun, 2003-05-11 at 00:55, Miguel de Icaza wrote:

> Hello!
> 
> > Remember my old GeSettings little project to replace GConf?. Well,
> > after some enlightenment by somebody I realized I could use GConf to
> > do the same thing without creating a schema. Because my first contact
> > with GConf was with GConf#, I thought it was mandatory to create and
> > install a schema and that's why all my whining was about.
> > 
> > Thank god I realized this before creating my own settings daemon!!! :)
> > 
> > I'll contribute some documentation for GConf# to warn future users of
> > this, and to point them to my little library that makes using GConf#
> > easier, as soon as I get an Internet connection (I'm phoneless for a
> > while) and could commit my code to my CVS repository. 
> > 
> > At least this will be one less thing to learn when people start using
> > Gtk#.
> 
> Would you be interested in helping to the GNOME.NET tutorial?  That
> seems like a good place to start.
> _______________________________________________
> Gtk-sharp-list maillist  -  Gtk-sharp-list@lists.ximian.com
> http://lists.ximian.com/mailman/listinfo/gtk-sharp-list

-- 
Pablo Baena <pbaena@uol.com.ar>

--=-GYmCY2ypMZ8fc3Zjb7pa
Content-Type: text/html; charset=utf-8
Content-Transfer-Encoding: 7bit

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 TRANSITIONAL//EN">
<HTML>
<HEAD>
  <META HTTP-EQUIV="Content-Type" CONTENT="text/html; CHARSET=UTF-8">
  <META NAME="GENERATOR" CONTENT="GtkHTML/1.1.10">
</HEAD>
<BODY>
Attached is the documentation to GConf#. I tried to make it as easy to understand as possible, and provided some introduction to GConf to first-starters like me. <IMG SRC="cid:1052721581.28294.2.camel@hal" ALIGN="middle" ALT=":)" BORDER="0"><BR>
<BR>
Sorry for not sending a diff, but I cannot check out all the MonkeyGuide. Right now I have an sporadic connection to the Internet, that I have to administer as if it were a telephone call to Japan.<BR>
<BR>
This is suppossed to be complementary of Rachel Hestilow's documentation, to be put before her documentation of the GConf# binding.<BR>
<BR>
On Sun, 2003-05-11 at 00:55, Miguel de Icaza wrote:
<BLOCKQUOTE TYPE=CITE>
<PRE><FONT COLOR="#737373" SIZE="3"><I>Hello!

&gt; Remember my old GeSettings little project to replace GConf?. Well,
&gt; after some enlightenment by somebody I realized I could use GConf to
&gt; do the same thing without creating a schema. Because my first contact
&gt; with GConf was with GConf#, I thought it was mandatory to create and
&gt; install a schema and that's why all my whining was about.
&gt; 
&gt; Thank god I realized this before creating my own settings daemon!!! :)
&gt; 
&gt; I'll contribute some documentation for GConf# to warn future users of
&gt; this, and to point them to my little library that makes using GConf#
&gt; easier, as soon as I get an Internet connection (I'm phoneless for a
&gt; while) and could commit my code to my CVS repository. 
&gt; 
&gt; At least this will be one less thing to learn when people start using
&gt; Gtk#.

Would you be interested in helping to the GNOME.NET tutorial?  That
seems like a good place to start.
_______________________________________________
Gtk-sharp-list maillist  -  Gtk-sharp-list@lists.ximian.com</FONT>
<A HREF="http://lists.ximian.com/mailman/listinfo/gtk-sharp-list"><FONT SIZE="3">http://lists.ximian.com/mailman/listinfo/gtk-sharp-list</I></FONT></A></PRE>
</BLOCKQUOTE>
<PRE><TABLE CELLSPACING="0" CELLPADDING="0" WIDTH="100%">
<TR>
<TD>
-- <BR>
Pablo Baena &lt;<A HREF="mailto:pbaena@uol.com.ar">pbaena@uol.com.ar</A>&gt;
</TD>
</TR>
</TABLE>
</PRE>
</BODY>
</HTML>

--=-GYmCY2ypMZ8fc3Zjb7pa--

--=-L3dwK4nlFvMCjQrRtxmJ
Content-ID: <1052721581.28294.2.camel@hal>
Content-Disposition: attachment; filename=smiley-3.png
Content-Type: image/png; name=smiley-3.png
Content-Transfer-Encoding: base64

iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAC+klEQVR42n2TbUjVdxTHP/+H69Xd
a2VWlFe69rzthZJUoxeNOWoFGxEhYRRFmZSVW2u9ab2KejWE1qDNBkEQhS82VoiaZkVPmoWaKNM5
mA+opbd771//997//T/+epHBarEPHA6Hc84XDnwP/JcwcBS4AVgzcR04ONN7C+md+pcPCz44dPLA
arZs/gg1UABuGkvvp7X1Iad+itE/YtUAle8TuH26sujzqq/LkJQsnOQQVmIASVJQMhehZORiJwc5
d76FH2pf3gY2Aigzy7+eObqmtOqbXbjGGHZqCM+eQpJ9AHhWFCc5CAjWf1KAkppc+qg3vRCol4Fw
0aqcisOVW3HTE7hmBElSKD/5GFkNMhH1KDvegST78CwNSfZxeM88VuYrh4CwAuxqvxL6MnPuWiy9
H1kNUPH9fZofDKPpHn8/z+Z6Yw8JK5stX5VhRO6h+OfiV3WaHxtPVKAwmF+KqXUDMkgqZ0+UoKcE
P57/GXOqh46ODqrPXUQfufb6YOGxJOQD2CaHQnnlAJ4zDXggHBYvK6ap6Rau+RIz1k7djd+YHrqM
pXUC4KQnWTRPAdiuRqNRkFQG/omRNJOsKVQw408xtS4QDsI10AaqEY6O8Fzq70fJy3XI8gsA5HTa
rBdOkvwFKj39EWrr/sJzEnj29OvsphGugfBsLlwbZnjcYN36LxiLuADtMtCUetFAcE4ee8s+pbHV
YtOemwhHx3MSaPEY3X9OUnqsk5a2OMeP7KC3t4u+3gRALUC4cEW2eN62Q4ze3SAiz74TDxvOiI+X
BcTsoCoyfJKYn6OKmrMbxGRnlXhyJSSqv80Vq0KSAFa+ceKl0wcK9lfsW42TGsE/pxhfcDmKfz6e
FUPg4iRH6Ov6g9EJh1t341xusWuAyn9b+c7BrbklJ8oDZGTOQpL9ePY08SmDpCEwbcHwuE370yku
Nlj3gM/e90yXliyU9+8sCVJYlEUgU8IwBZruMThm83uzxsAYV4Hd/A9h4BjQBthAFOgDLgDF7w6/
ArI6YJ0eTQeGAAAAAElFTkSuQmCC

--=-L3dwK4nlFvMCjQrRtxmJ--

--=-nwjqIeM6BK56rsFCl8tZ
Content-Disposition: attachment; filename=gconf_tutorial.html
Content-Type: text/html; name=gconf_tutorial.html; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit

<h1>GConf# tutorial</h1>

<h2>GConf introduction</h2>

<p>GConf is a system for storing configuration information and maintaining
it across application sessions, much like the Windows registry but more 
powerful. The complete documentation for the underlying technology is 
<a href="http://developer.gnome.org/doc/API/gconf/index.html">here</a>, but
as we Mono users are very high-level people (at the programming level, at 
least), I'll show you a quick and simple example of how to use it.</p>

<h2>The GConf# binding</h2>

<p>In this example, we just create a Mono program that stores and retrieves
a value from GConf.</p>

<pre>
using System;
class GConfExample
{
	static GConf.Client gconfClient = new GConf.Client ();

	public static void Main ()
	{
		string key = "/apps/monoapps/myAppName/mySetting";
		try
		{
			string val = (string) gconfClient.Get (key);
			Console.WriteLine ("The value is: '{0}'", val);
		}
		catch (GConf.NoSuchKeyException)
		{
			Console.WriteLine ("The value is not set. Setting it for the next time.");
			gconfClient.Set (key, "Value");	
		}
	}
}
</pre>

<p>Remember to add a reference to gconf-sharp.dll in the Mono C# compiler 
command line. If you don't have it installed, remember that GConf#
is part of the Gtk# bindings, although it can be in a separated package
(GConf doesn't depend on Gtk).</p>

<p>The 'key' used in the example, is a slash-separated path similar
to the ones used in the UNIX filesystem. Each slash denotes a level
in the GConf namespace. We use the apps/monoapps/ sub-level only 
to organize the tree in an orderly fashion. 
If you have the gconf-editor program installed, you can run it and
look for the key yourself in the tree structure. You'll see it stored
with the value we put it, so the next time you run the program,
it will retrieve the stored value.</p>

<p>There is a nifty feature of GConf that lets you notify your program
whenever a key's value is changed, either in your program or externally
(i.e. via gconf-editor). You only have to attach a GConf.NotifyEventHandler
delegate to a key, this way:</p>
<code>
gconfClient.AddNotify (key, new GConf.NotifyEventHandler(function));
</code>
<p>
This is very important for graphic interfaces, as it is a good practice
to make the application react instantly to preference changes.</p>

<h2>A quicker way</h2>

<p>The above example is perfect for a single setting, but what
if our application needs to store more settings, and we want 
to provide default values for some of our preferences
for when they aren't set. Or even more, we want to store data
types other than only strings. You have three options: 

<ul>
<li>to repeat the above example for all the settings, which is monkey 
labour</li>
<li>to use a <i>schema</i>, which is explained below but it's just too
much work</li>
<li>use a little library I created for automating this, in which
Mono does what it is meant to, the monkey labour!</li>
</ul>

<p>I'll explain the latter option so that you can see how Mono can 
turn some things that were very complicated into very easy ones. 
This is an example of the use of my library.</p>

<pre>
using System;

interface IMySettings 
{
	[GeSettings.Property ("myMonoApp", 10)]
	int SomeNumber
	{
		get; 
		set;
	}
	event GConf.NotifyEventHandler SomeNumberChanged;

	[GeSettings.Property ("myMonoApp", 1.4)]
	double SomeDoubleNumber
	{
		get; 
		set;
	}
}

class GConfExample2
{
	public static void Main ()
	{
		IMySettings mySettings = (IMySettings) 
			GeSettings.Builder.Build (typeof(IMySettings));

		mySettings.SomeNumberChanged += 
			new GConf.NotifyEventHandler (OnSomeNumberChanged);

		Console.WriteLine ("Value of 'SomeNumber': {0}", 
				mySettings.SomeNumber);

		Console.WriteLine ("Value of 'SomeDoubleNumber': {0}", 
				mySettings.SomeDoubleNumber);

		mySettings.SomeNumber = 14;
		mySettings.SomeDoubleNumber = 3.1;
	}

	static void OnSomeNumberChanged (object o, GConf.NotifyEventArgs a)
	{
		Console.WriteLine ("SomeNumber changed");
	}
}
</pre>


<p>To compile this example you'll have to reference gconf-sharp.dll and
ge_settings_gconf.dll. You can get the latter <a 
href="http://gnomencoder.sourceforge.net/index.html#GeSettings">here</a>. 
</p>

<p>What have we just done? Well, first we defined an interface with a few
properties. All the properties have a GeSettings.Property attribute
that indicates the name of the app and the default value.
If you define an event of type GConf.NotifyEventHandler with the same of
the property plus 'Changed', the delegates connected to this event will be
triggered whenever GConf notify a change of the property value.
<br>
Then we passed the interface as the argument of a function that returns
an implementation of that interface. This implementation uses GConf
transparently, thus whenever we set or get the property, it will use 
GConf to retrieve or store the setting on disk.
</p>

<p>

<p>Notice that we just used int and double data types transparently. This
is because of Mono facilities to serialize primitives to strings. Just
check before setting the value, that it is a valid one to the wanted type,
otherwise you'll get a crash with FormatException.</p>

<p>And there is more! With another class I created (it is apart so one
doesn't have to depend on Gtk# for other uses), one can do this:</p>

<pre>

interface IMySettings 
{
	[GeSettings.Property ("GnoMencoder",
				"/dev/cdroms/cdrom0",
				WidgetName = "dvddevice_entry")]
	string DVDDevice
	{
		get;
		set;
	}
}
</pre>

<p>And, with this function:<br>
<pre>	IMySettings mySettings = (IMySettings) <br>		GeSettings.<span
 style="font-weight: bold;">Glade</span>Builder.Build (typeof(IMySettings), <span
 style="font-weight: bold;">gxml</span>);<br><br></pre>
you'll have the property associated with the widget on the glade
resource, which will update the GConf value on any changes to the widget 
and display any external modifications (it is not advisable to use this 
if you're using other types but string as it is very easy to get wrong 
format exceptions all the time if you don't check the input)</p>

<p>
With this we avoided all the steps involved in creating and using
a schema, that are:
<br>
<ul>
  <li>create a GConf schema (learn how to make one)</li>
  <li>run gconf-schemagen over it to create the class</li>
  <li>you have to learn where to install the schema on different systems<br>
  </li>
  <li>have root priviledges to install the schema</li>
  <li>and even more steps if you want to connect a gconf key to a widget<br>
  </li>
</ul>
</p>

<h2>But, what is a GConf schema?</h2>

<p>From <a href="http://developer.gnome.org/doc/API/gconf/x42.html">the
documentation</a>:
"A schema describes some configuration key. Its primary purpose is to provide documentation about the key to system administrators manipulating the GConf database. Secondarily, schemas contain a good default value for the key; GConf will automatically return this value when a key is unset. Schemas also include the name of the application that created a key (useful when trying to clean old junk out of the database, for example)".<p>

<p>"But..." --I hear you say. "I don't care about manipulating a GConf 
database. I only want to store some settings and be done with it". That's
exactly why I created the above mentioned utility library, to escape
from this burden. Now, we cannot presume that nobody is going to need
to create schemas, so next is an explanation on how to utilize schemas
and the utilities that GConf# provides to deal with them.</p>

--=-nwjqIeM6BK56rsFCl8tZ--