[Gtk-sharp-list] [PATCH] problems with gconf list type

Gonzalo Paniagua Javier gonzalo@ximian.com
Wed, 20 Aug 2003 19:49:33 +0200


--=-Ljh0a3bsqpflLDgJneXo
Content-Type: text/plain; charset=iso-8859-1
Content-Transfer-Encoding: 8bit

El mié, 20-08-2003 a las 10:20, ddt escribió:
> hi
> 
> I'm writing a little program that get list type from gconf.
> when i get string type no exception raise but list type is raise
> exception.
> 
> here is my code
> ----
> using Gconf;
> public class test
> {
>   public static void Main()
>   {
>     GConf.Client gc = new GConf.Client();
>     //string
>     gc.Get("/apps/epiphany/web/cache_size");
>     //list    
>     gc.Get("/apps/epiphany/web/language");
>   }
> }
> ----
> and error message here
> ----
> $ mono gconf_get_list.exe 
> Unhandled Exception: GConf.InvalidValueTypeException: Exception of type
> GConf.InvalidValueTypeException was thrown.
> in <0x000f0> 00 GConf.Value:Get ()
> in <0x0012a> 00 GConf.Client:Get (string)
> in <0x0003c> 00 .test:Main ()
> ----
> Is this bug? or am I wrong?
> Thanks

Support for lists was not implemented.

Attached you can get a patch that implements it (Mike, Rachel, may I
commit?) and a your sample modified to update the languages.

Cheers.

-Gonzalo



--=-Ljh0a3bsqpflLDgJneXo
Content-Disposition: attachment; filename=gconf-lists.patch
Content-Type: text/plain; name=gconf-lists.patch; charset=iso-8859-1
Content-Transfer-Encoding: 7bit

? entry
? warnings.txt
? doc/documentation.tree
? doc/documentation.zip
? gdk/PixbufLoader.cu
? gtk/DataBoundModel.csssssssssssssss
? parser/gl.sources
Index: ChangeLog
===================================================================
RCS file: /cvs/public/gtk-sharp/ChangeLog,v
retrieving revision 1.445
diff -u -r1.445 ChangeLog
--- ChangeLog	19 Aug 2003 21:07:23 -0000	1.445
+++ ChangeLog	20 Aug 2003 17:58:48 -0000
@@ -1,3 +1,10 @@
+2003-08-20  Gonzalo Paniagua Javier <gonzalo@ximian.com>
+
+	* gconf/GConf/Value.cs: implemented support for lists.
+
+	* glib/ListBase.cs: implemented the IDisposable stuff and created a new method,
+	FreeList, to free the list when needed.
+
 2003-08-19  John Luke  <jluke@cfl.rr.com>
 
 	* glib/ListBase.cs:  Add convenience .Append (string) method
Index: gconf/GConf/Value.cs
===================================================================
RCS file: /cvs/public/gtk-sharp/gconf/GConf/Value.cs,v
retrieving revision 1.2
diff -u -r1.2 Value.cs
--- gconf/GConf/Value.cs	10 Jun 2003 18:09:45 -0000	1.2
+++ gconf/GConf/Value.cs	20 Aug 2003 17:58:49 -0000
@@ -1,6 +1,7 @@
 namespace GConf
 {
 	using System;
+	using System.Collections;
 	using System.Runtime.InteropServices;
 
 	internal enum ValueType
@@ -49,6 +50,8 @@
 				return ValueType.Float;
 			} else if (data is bool) {
 				return ValueType.Bool;
+			} else if (data is ICollection) {
+				return ValueType.List;
 			} else {
 				return ValueType.Invalid;
 			}
@@ -63,6 +66,12 @@
 			Set (data, type);
 		}
 
+		[DllImport("gconf-2")]
+		static extern IntPtr gconf_value_set_list_nocopy (IntPtr value, IntPtr list);
+		
+		[DllImport("gconf-2")]
+		static extern IntPtr gconf_value_set_list_type (IntPtr value, ValueType vtype);
+		
 		void Set (object data, ValueType type)
 		{
 			if (data == null)
@@ -82,10 +91,41 @@
 				case ValueType.Bool:
 					gconf_value_set_bool (Raw, (bool) data);
 					break;
+				case ValueType.List:
+					ValueType listType;
+					GLib.SList list = GetListFromCollection ((ICollection) data, out listType);
+					gconf_value_set_list_type (Raw, listType);
+					gconf_value_set_list_nocopy (Raw, list.Handle);
+					break;
 				default:
 					throw new InvalidValueTypeException ();
 			}
 		}
+		
+		GLib.SList GetListFromCollection (ICollection data, out ValueType listType)
+		{
+			object [] arr = (object []) Array.CreateInstance (typeof (object), data.Count);
+			data.CopyTo (arr, 0);
+
+			listType = ValueType.Invalid;
+			GLib.SList list = new GLib.SList (IntPtr.Zero);
+			GC.SuppressFinalize (list);
+
+			foreach (object o in arr) {
+				ValueType type = LookupType (o);
+				if (listType == ValueType.Invalid)
+					listType = type;
+
+				if (listType == ValueType.Invalid || type != listType)
+					throw new InvalidValueTypeException ();
+
+				Value v = new Value (o);
+				GC.SuppressFinalize (v);
+				list.Append (v.Raw);
+			}
+			
+			return list;
+		}
 
 		[DllImport("gconf-2")]
 		static extern IntPtr gconf_value_get_string (IntPtr value);
@@ -99,6 +139,9 @@
 		[DllImport("gconf-2")]
 		static extern bool gconf_value_get_bool (IntPtr value);
 		
+		[DllImport("gconf-2")]
+		static extern IntPtr gconf_value_get_list (IntPtr value);
+		
 		public object Get ()
 		{
 			switch (val_type)
@@ -111,12 +154,45 @@
 					return gconf_value_get_float (Raw);
 				case ValueType.Bool:
 					return gconf_value_get_bool (Raw);
+				case ValueType.List:
+					GLib.SList list = new GLib.SList (gconf_value_get_list (Raw), typeof (Value));
+					Array result = Array.CreateInstance (GetListType (), list.Count);
+					int i = 0;
+					foreach (Value v in list) {
+						((IList) result) [i] =  v.Get ();
+						v.managed = false; // This is the trick to prevent a crash
+						i++;
+					}
+
+					return result;
 				default:
 					throw new InvalidValueTypeException ();
 			}
 		}
 
 		[DllImport("gconf-2")]
+		static extern ValueType gconf_value_get_list_type (IntPtr value);
+
+		Type GetListType ()
+		{
+			ValueType vt = gconf_value_get_list_type (Raw);
+			switch (vt) {
+			case ValueType.String:
+				return typeof (string);
+			case ValueType.Int:
+				return typeof (int);
+			case ValueType.Float:
+				return typeof (float);
+			case ValueType.Bool:
+				return typeof (bool);
+			case ValueType.List:
+				return typeof (GLib.SList);
+			default:
+				throw new InvalidValueTypeException ();
+			}
+		}
+
+		[DllImport("gconf-2")]
 		static extern IntPtr gconf_value_new (ValueType type);
 		
 		public Value (ValueType type)
@@ -173,10 +249,16 @@
 		
 		~Value ()
 		{
-			Dispose ();
+			Dispose (false);
 		}
 		
 		public void Dispose ()
+		{
+			Dispose (true);
+			GC.SuppressFinalize (this);
+		}
+
+		protected virtual void Dispose (bool disposing)
 		{
 			if (managed && Raw != IntPtr.Zero)
 			{
Index: glade/HandlerNotFoundExeception.cs
===================================================================
RCS file: /cvs/public/gtk-sharp/glade/HandlerNotFoundExeception.cs,v
retrieving revision 1.1
diff -u -r1.1 HandlerNotFoundExeception.cs
--- glade/HandlerNotFoundExeception.cs	13 Sep 2002 11:38:36 -0000	1.1
+++ glade/HandlerNotFoundExeception.cs	20 Aug 2003 17:58:49 -0000
@@ -14,7 +14,7 @@
 	///	Exception thrown when signal autoconnection fails.
 	/// </summary>
 	[Serializable]
-	public class HandlerNotFoundException : Exception 
+	public class HandlerNotFoundException : SystemException 
 	{
 		string handler_name;
 		string signal_name;
@@ -23,6 +23,14 @@
 
 		public HandlerNotFoundException (string handler_name, string signal_name, 
 						 EventInfo evnt, Type delegate_type)
+			: this (handler_name, signal_name, evnt, delegate_type, null)
+		{
+		}				 
+
+		public HandlerNotFoundException (string handler_name, string signal_name, 
+						 EventInfo evnt, Type delegate_type, Exception inner)
+			: base ("No handler " + handler_name + " found for signal " + signal_name,
+				inner)
 		{
 			this.handler_name = handler_name;
 			this.signal_name = signal_name;
@@ -37,13 +45,6 @@
 			signal_name = info.GetString ("SignalName");
 			evnt = info.GetValue ("Event", typeof (EventInfo)) as EventInfo;
 			delegate_type = info.GetValue ("DelegateType", typeof (Type)) as Type;
-		}
-
-		public override string Message
-		{
-			get { 
-				return "No handler " + handler_name + " found for signal " + signal_name;
-			}
 		}
 
 		public string HandlerName
Index: glib/ListBase.cs
===================================================================
RCS file: /cvs/public/gtk-sharp/glib/ListBase.cs,v
retrieving revision 1.7
diff -u -r1.7 ListBase.cs
--- glib/ListBase.cs	19 Aug 2003 21:07:24 -0000	1.7
+++ glib/ListBase.cs	20 Aug 2003 17:58:49 -0000
@@ -49,7 +49,7 @@
 		
 		~ListBase ()
 		{
-			Dispose ();
+			Dispose (false);
 		}
 		
 		public bool Managed {
@@ -76,7 +76,8 @@
 			}
 			set {
 				if (managed && list_ptr != IntPtr.Zero)
-					Dispose ();
+					FreeList ();
+
 				list_ptr = value;
 			}
 		}
@@ -180,15 +181,26 @@
 		// IDisposable
 		public void Dispose ()
 		{
+			Dispose (true);
+			GC.SuppressFinalize (this);
+		}
+
+		protected virtual void Dispose (bool disposing)
+		{
 			if (!managed)
 				return;
 
+			FreeList ();
+		}
+		
+		void FreeList ()
+		{
 			if (list_ptr != IntPtr.Zero)
 				Free (list_ptr);
 			list_ptr = IntPtr.Zero;
 			length = -1;
 		}
-		
+
 		// ICloneable
 		abstract public object Clone ();
 	}

--=-Ljh0a3bsqpflLDgJneXo
Content-Disposition: attachment; filename=gcs.cs
Content-Type: text/plain; name=gcs.cs; charset=iso-8859-1
Content-Transfer-Encoding: 7bit

using System;
using GConf;
public class test
{
	public static void Main()
	{
		GConf.Client gc = new GConf.Client ();
		//string
		gc.Get ("/apps/epiphany/web/cache_size");
		//list    
		Array list = (Array) gc.Get ("/apps/epiphany/web/language");
		foreach (object o in list)
			Console.WriteLine ("{0}: {1}", o.GetType (), o);

		string [] mylist = new string [] {"us", "system", "es"};
		gc.Set ("/apps/epiphany/web/language", mylist);
		list = (Array) gc.Get ("/apps/epiphany/web/language");
		foreach (object o in list) 
			Console.WriteLine ("{0}: {1}", o.GetType (), o);
	}
}


--=-Ljh0a3bsqpflLDgJneXo--