diff --git a/capplets/common/Bonobo_Control_Capplet_generic.oaf.in b/capplets/common/Bonobo_Control_Capplet_generic.oaf.in index 00058583f..4cef098ad 100644 --- a/capplets/common/Bonobo_Control_Capplet_generic.oaf.in +++ b/capplets/common/Bonobo_Control_Capplet_generic.oaf.in @@ -18,13 +18,4 @@ - - - - - - - - diff --git a/capplets/common/ChangeLog b/capplets/common/ChangeLog index 36134fb94..8aca6f9bd 100644 --- a/capplets/common/ChangeLog +++ b/capplets/common/ChangeLog @@ -1,3 +1,12 @@ +2001-11-03 Bradford Hovinen + + * Makefile.am (libcommon_a_SOURCES): Added gconf-property-editor.[ch] + +2001-10-27 Bradford Hovinen + + * capplet-util.c (get_default_moniker): Switch to gconf: moniker + (capplet_init): Remove legacy file hack + 2001-10-18 Bradford Hovinen * Bonobo_Control_Capplet_generic.oaf.in: Update listener name diff --git a/capplets/common/Makefile.am b/capplets/common/Makefile.am index ceb033fcc..d29151c37 100644 --- a/capplets/common/Makefile.am +++ b/capplets/common/Makefile.am @@ -12,4 +12,5 @@ noinst_LIBRARIES = libcommon.a libcommon_a_SOURCES = \ capplet-util.c capplet-util.h \ - bonobo-property-editor-range.c bonobo-property-editor-range.h + gconf-property-editor.c gconf-property-editor.h \ + gconf-property-editor-marshal.c gconf-property-editor-marshal.h diff --git a/capplets/common/capplet-util.c b/capplets/common/capplet-util.c index f6ceb25fa..9d607672b 100644 --- a/capplets/common/capplet-util.c +++ b/capplets/common/capplet-util.c @@ -36,10 +36,9 @@ static CreateDialogFn create_dialog_cb = NULL; static ApplySettingsFn apply_settings_cb = NULL; -static SetupPropertyEditorsFn setup_cb = NULL; +static SetupPropertyEditorsFn setup_property_editors_cb = NULL; -static BonoboListener *listener = NULL; -static Bonobo_EventSource_ListenerId listener_id; +static GConfChangeSet *changeset; /* apply_cb * @@ -50,120 +49,21 @@ static Bonobo_EventSource_ListenerId listener_id; static void apply_cb (BonoboPropertyControl *pc, Bonobo_PropertyControl_Action action) { - BonoboPropertyFrame *pf; - Bonobo_ConfigDatabase db; - CORBA_Environment ev; - - if (action == Bonobo_PropertyControl_APPLY) { - CORBA_exception_init (&ev); - - pf = gtk_object_get_data (GTK_OBJECT (pc), "property-frame"); - db = gtk_object_get_data (GTK_OBJECT (pf), "config-database"); - bonobo_pbproxy_update (pf->proxy); - Bonobo_ConfigDatabase_sync (db, &ev); - - CORBA_exception_free (&ev); - } + if (action == Bonobo_PropertyControl_APPLY) + gconf_engine_commit_change_set (gconf_engine_get_default (), + changeset, TRUE, NULL); } -/* changed_cb +/* properties_changed_cb * - * Callback issued when a setting in the ConfigDatabase changes. + * Callback issued when some setting has changed */ static void -changed_cb (BonoboListener *listener, - gchar *event_name, - CORBA_any *any, - CORBA_Environment *ev, - Bonobo_ConfigDatabase db) +properties_changed_cb (GConfEngine *engine, guint cnxn_id, GConfEntry *entry, gpointer user_data) { if (apply_settings_cb != NULL) - apply_settings_cb (db); -} - -/* get_moniker_cb - * - * Callback issued to retrieve the name of the moniker being used. This function - * is just a formality. - */ - -static void -get_moniker_cb (BonoboPropertyBag *bag, BonoboArg *arg, guint arg_id, - CORBA_Environment *ev, BonoboControl *control) -{ - BONOBO_ARG_SET_STRING (arg, gtk_object_get_data (GTK_OBJECT (control), "moniker")); -} - -/* pf_destroy_cb - * - * Callback issued when the property frame is destroyed. Ensures that the - * configuration database is properly unrefed - */ - -static void -pf_destroy_cb (BonoboPropertyFrame *pf, Bonobo_ConfigDatabase db) -{ - bonobo_object_release_unref (db, NULL); -} - -/* set_moniker_cb - * - * Callback issued when the name of the moniker to be used is set. This function - * does most of the dirty work -- creating the property editors that connect - * properties to the dialog box. - */ - -static void -set_moniker_cb (BonoboPropertyBag *bag, - BonoboArg *arg, - guint arg_id, - CORBA_Environment *ev, - BonoboControl *control) -{ - gchar *moniker; - gchar *full_moniker; - BonoboPropertyFrame *pf; - Bonobo_PropertyBag proxy; - Bonobo_ConfigDatabase db; - gboolean need_setup_cb = TRUE; - - if (arg_id != 1) return; - - moniker = BONOBO_ARG_GET_STRING (arg); - full_moniker = g_strconcat (moniker, "#config:/main", NULL); - - pf = BONOBO_PROPERTY_FRAME (bonobo_control_get_widget (control)); - bonobo_property_frame_set_moniker (pf, full_moniker); - g_free (full_moniker); - - if (pf->proxy->bag == CORBA_OBJECT_NIL) { - bonobo_exception_set (ev, ex_Bonobo_Property_InvalidValue); - return; - } - - proxy = BONOBO_OBJREF (pf->proxy); - - db = gtk_object_get_data (GTK_OBJECT (pf), "config-database"); - - if (db != CORBA_OBJECT_NIL) { - gtk_signal_disconnect_by_func (GTK_OBJECT (pf), - GTK_SIGNAL_FUNC (pf_destroy_cb), db); - bonobo_object_release_unref (db, ev); - need_setup_cb = FALSE; - } - - db = bonobo_get_object (moniker, "IDL:Bonobo/ConfigDatabase:1.0", ev); - - if (BONOBO_EX (ev) || db == CORBA_OBJECT_NIL) - g_critical ("Could not resolve configuration moniker; will not be able to apply settings"); - - gtk_object_set_data (GTK_OBJECT (pf), "config-database", db); - gtk_signal_connect (GTK_OBJECT (pf), "destroy", - GTK_SIGNAL_FUNC (pf_destroy_cb), db); - - if (setup_cb != NULL && need_setup_cb) - setup_cb (GTK_BIN (pf)->child, proxy); + apply_settings_cb (); } /* get_control_cb @@ -176,8 +76,6 @@ set_moniker_cb (BonoboPropertyBag *bag, static BonoboObject * get_control_cb (BonoboPropertyControl *property_control, gint page_number) { - BonoboPropertyBag *pb; - GtkWidget *pf; BonoboControl *control; GtkWidget *widget; @@ -186,23 +84,8 @@ get_control_cb (BonoboPropertyControl *property_control, gint page_number) if (widget == NULL) return NULL; - pf = bonobo_property_frame_new (NULL, NULL); - gtk_object_set_data (GTK_OBJECT (property_control), - "property-frame", pf); - gtk_container_add (GTK_CONTAINER (pf), widget); - gtk_widget_show_all (pf); - - control = bonobo_control_new (pf); - - pb = bonobo_property_bag_new ((BonoboPropertyGetFn) get_moniker_cb, - (BonoboPropertySetFn) set_moniker_cb, - control); - bonobo_control_set_properties (control, pb); - bonobo_object_unref (BONOBO_OBJECT (pb)); - - bonobo_property_bag_add (pb, "moniker", 1, BONOBO_ARG_STRING, NULL, - "Moniker for configuration", - BONOBO_PROPERTY_WRITEABLE); + control = bonobo_control_new (widget); + setup_property_editors_cb (widget, changeset); bonobo_control_set_automerge (control, TRUE); @@ -215,26 +98,21 @@ get_control_cb (BonoboPropertyControl *property_control, gint page_number) */ static BonoboObject * -create_control_cb (BonoboGenericFactory *factory, const gchar *component_id, gchar *default_moniker) +create_control_cb (BonoboGenericFactory *factory, const gchar *component_id) { BonoboObject *obj; BonoboPropertyControl *property_control; static const gchar *prefix1 = "OAFIID:Bonobo_Control_Capplet_"; - static const gchar *prefix2 = "OAFIID:Bonobo_Listener_Config_"; g_message ("%s: Enter", __FUNCTION__); if (!strncmp (component_id, prefix1, strlen (prefix1))) { property_control = bonobo_property_control_new ((BonoboPropertyControlGetControlFn) get_control_cb, 1, NULL); - gtk_signal_connect (GTK_OBJECT (property_control), "action", - GTK_SIGNAL_FUNC (apply_cb), NULL); + g_signal_connect (G_OBJECT (property_control), "action", + G_CALLBACK (apply_cb), NULL); obj = BONOBO_OBJECT (property_control); - } - else if (!strncmp (component_id, prefix2, strlen (prefix2))) { - obj = BONOBO_OBJECT (listener); - bonobo_object_ref (obj); } else { g_critical ("Not creating %s", component_id); obj = NULL; @@ -266,28 +144,6 @@ get_factory_name (const gchar *binary) return res; } -/* get_default_moniker - * - * Construct the default moniker for configuration from the binary name - */ - -static gchar * -get_default_moniker (const gchar *binary) -{ - gchar *s, *tmp, *tmp1, *res; - - s = g_strdup (binary); - tmp = strrchr (s, '/'); - if (tmp == NULL) tmp = s; - else tmp++; - if ((tmp1 = strstr (tmp, "-control")) != NULL) *tmp1 = '\0'; - if ((tmp1 = strstr (tmp, "-capplet")) != NULL) *tmp1 = '\0'; - - res = g_strconcat ("archive:user-archive#archiverdb:", tmp, NULL); - g_free (s); - return res; -} - /* get_property_name * * Get the property name associated with this capplet @@ -324,6 +180,9 @@ get_property_name (const gchar *binary) static void setup_session_mgmt (const gchar *binary_name) { +/* Disabled. I never really understood this code anyway, and I am absolutely + * unclear about how to port it to GNOME 2.0 */ +#if 0 GnomeClient *client; GnomeClientFlags flags; gint token; @@ -356,93 +215,7 @@ setup_session_mgmt (const gchar *binary_name) (client, GNOME_RESTART_NEVER); } } -} - -static gboolean -legacy_is_modified (Bonobo_ConfigDatabase db, const gchar *filename) -{ - time_t legacy_val, log_val; - CORBA_Environment ev; - Bonobo_PropertyBag pb; - BonoboArg *arg; - struct stat stbuf; - gchar *realfile; - struct tm *legacy_tm; - gboolean ret; - - g_return_val_if_fail (db != CORBA_OBJECT_NIL, FALSE); - - CORBA_exception_init (&ev); - - pb = Bonobo_Unknown_queryInterface (db, "IDL:Bonobo/PropertyBag:1.0", &ev); - - if (pb == CORBA_OBJECT_NIL || BONOBO_EX (&ev)) - return FALSE; - - arg = bonobo_property_bag_client_get_value_any (pb, "last_modified", &ev); - - bonobo_object_release_unref (pb, NULL); - - if (arg == NULL || BONOBO_EX (&ev)) - return FALSE; - - log_val = BONOBO_ARG_GET_GENERAL (arg, TC_ulonglong, CORBA_unsigned_long_long, NULL); - bonobo_arg_release (arg); - - if (filename[0] == '/') - realfile = g_strdup (filename); - else - realfile = g_strconcat (g_get_home_dir (), - "/.gnome/", - filename, - NULL); - - if (stat (realfile, &stbuf) != 0) { - ret = FALSE; - } else { - legacy_tm = localtime (&stbuf.st_mtime); - legacy_val = mktime (legacy_tm); - ret = (legacy_val > log_val); - } - - g_free (realfile); - - CORBA_exception_free (&ev); - - return ret; -} - -static int -add_listener_cb (Bonobo_ConfigDatabase db) -{ - Bonobo_EventSource es; - CORBA_Environment ev; - - CORBA_exception_init (&ev); - - /* We do this manually so that we have access to the resulting listener object */ - es = Bonobo_Unknown_queryInterface (db, "IDL:Bonobo/EventSource:1.0", &ev); - - if (BONOBO_EX (&ev) || es == CORBA_OBJECT_NIL) { - g_critical ("Cannot get event source interface (%s)", - bonobo_exception_get_text (&ev)); - } else { - listener = bonobo_listener_new ((BonoboListenerCallbackFn) changed_cb, db); - listener_id = Bonobo_EventSource_addListenerWithMask (es, BONOBO_OBJREF (listener), - "Bonobo/ConfigDatabase:sync", &ev); - - if (BONOBO_EX (&ev) || listener_id == 0) { - g_critical ("Could not add the listener to the event source (%s)", - bonobo_exception_get_text (&ev)); - } - - bonobo_object_release_unref (es, NULL); - bonobo_running_context_auto_exit_unref (BONOBO_OBJECT (listener)); - } - - CORBA_exception_free (&ev); - - return FALSE; +#endif } /* capplet_init -- see documentation in capplet-util.h @@ -451,32 +224,21 @@ add_listener_cb (Bonobo_ConfigDatabase db) void capplet_init (int argc, char **argv, - const gchar **legacy_files, ApplySettingsFn apply_fn, CreateDialogFn create_dialog_fn, SetupPropertyEditorsFn setup_fn, GetLegacySettingsFn get_legacy_fn) { gchar *factory_iid; - gchar *default_moniker; - gboolean needs_legacy = FALSE; - int i; - BonoboGenericFactory *factory; - CORBA_ORB orb; - Bonobo_ConfigDatabase db; - - CORBA_Environment ev; - static gboolean apply_only; - static gboolean init_session; static gboolean get_legacy; static struct poptOption cap_options[] = { { "apply", '\0', POPT_ARG_NONE, &apply_only, 0, N_("Just apply settings and quit"), NULL }, - { "init-session-settings", '\0', POPT_ARG_NONE, &init_session, 0, - N_("Initialize the session"), NULL }, + { "init-session-settings", '\0', POPT_ARG_NONE, &apply_only, 0, + N_("Just apply settings and quit"), NULL }, { "get-legacy", '\0', POPT_ARG_NONE, &get_legacy, 0, N_("Retrieve and store legacy settings"), NULL }, { NULL, '\0', 0, NULL, 0, NULL, NULL } @@ -485,71 +247,37 @@ capplet_init (int argc, bindtextdomain (PACKAGE, GNOMELOCALEDIR); textdomain (PACKAGE); - CORBA_exception_init (&ev); + gnome_program_init (argv[0], VERSION, LIBGNOMEUI_MODULE, argc, argv, + GNOME_PARAM_POPT_TABLE, cap_options, + NULL); - gnomelib_register_popt_table (cap_options, _("Capplet options")); - gnome_init_with_popt_table (argv[0], VERSION, argc, argv, - oaf_popt_options, 0, NULL); - - orb = oaf_init (argc, argv); - if (bonobo_init (orb, CORBA_OBJECT_NIL, CORBA_OBJECT_NIL) == FALSE) + if (!bonobo_init (&argc, argv)) g_error ("Cannot initialize bonobo"); - default_moniker = get_default_moniker (argv[0]); - db = bonobo_get_object (default_moniker, "IDL:Bonobo/ConfigDatabase:1.0", &ev); - - if (db == CORBA_OBJECT_NIL) { - g_critical ("Cannot open configuration database %s", default_moniker); - exit (-1); - } - - if (legacy_files && get_legacy_fn && !get_legacy) { - for (i = 0; legacy_files[i] != NULL; i++) { - if (legacy_is_modified (db, legacy_files[i])) { - needs_legacy = TRUE; - break; - } - } - } - - if ((apply_only || init_session) && apply_fn != NULL) { + if (apply_only && apply_fn != NULL) { setup_session_mgmt (argv[0]); - if (needs_legacy) - get_legacy_fn (db); - - apply_fn (db); + apply_fn (); } else if (get_legacy && get_legacy_fn != NULL) { setup_session_mgmt (argv[0]); - get_legacy_fn (db); - Bonobo_ConfigDatabase_sync (db, &ev); + get_legacy_fn (); } else { setup_session_mgmt (argv[0]); - if (needs_legacy) - get_legacy_fn (db); + create_dialog_cb = create_dialog_fn; apply_settings_cb = apply_fn; - setup_cb = setup_fn; + setup_property_editors_cb = setup_fn; + factory_iid = get_factory_name (argv[0]); - factory = bonobo_generic_factory_new_multi - (factory_iid, (GnomeFactoryCallback) create_control_cb, default_moniker); + factory = bonobo_generic_factory_new + (factory_iid, (BonoboFactoryCallback) create_control_cb, NULL); g_free (factory_iid); bonobo_running_context_auto_exit_unref (BONOBO_OBJECT (factory)); - gtk_idle_add ((GtkFunction) add_listener_cb, db); + changeset = gconf_change_set_new (); bonobo_main (); - if (listener_id != 0) { - bonobo_event_source_client_remove_listener (db, listener_id, &ev); - - if (BONOBO_EX (&ev)) - g_critical ("Could not remove listener (%s)", bonobo_exception_get_text (&ev)); - } + gconf_change_set_unref (changeset); } - - g_free (default_moniker); - bonobo_object_release_unref (db, NULL); - - CORBA_exception_free (&ev); } diff --git a/capplets/common/capplet-util.h b/capplets/common/capplet-util.h index 6605244cf..2cdfae605 100644 --- a/capplets/common/capplet-util.h +++ b/capplets/common/capplet-util.h @@ -26,12 +26,9 @@ #include #include - -/* FIXME: We should really have a single bonobo-conf.h header */ - -#include -#include -#include +#include +#include +#include /* Macros to make certain repetitive tasks a bit easier */ @@ -51,29 +48,20 @@ val_##type = gnome_config_get_##legacy_type##_with_default (legacy_key, &def); \ \ if (!def) \ - bonobo_config_set_##type (db, key, val_##type, NULL); - -/* Create a property editor */ - -#define CREATE_PEDITOR(type, key, widget) \ - { \ - BonoboPEditor *ed = BONOBO_PEDITOR \ - (bonobo_peditor_##type##_construct (WID (widget))); \ - bonobo_peditor_set_property (ed, bag, key, TC_##type, NULL); \ - } + gconf_engine_set_##type (engine, key, val_##type, NULL); /* Callback to apply the settings in the given database */ -typedef void (*ApplySettingsFn) (Bonobo_ConfigDatabase db); +typedef void (*ApplySettingsFn) (void); /* Callback to set up the dialog proper */ typedef GtkWidget *(*CreateDialogFn) (void); /* Callback to set up property editors for the dialog */ -typedef void (*SetupPropertyEditorsFn) (GtkWidget *dialog, Bonobo_PropertyBag bag); +typedef void (*SetupPropertyEditorsFn) (GtkWidget *dialog, GConfChangeSet *changeset); /* Callback to retrieve legacy settings and store them in the new configuration * database */ -typedef void (*GetLegacySettingsFn) (Bonobo_ConfigDatabase db); +typedef void (*GetLegacySettingsFn) (void); /* Wrapper function for the entire capplet. This handles all initialization and * runs the capplet for you. Just supply the appropriate callbacks and your argc @@ -93,7 +81,6 @@ typedef void (*GetLegacySettingsFn) (Bonobo_ConfigDatabase db); void capplet_init (int argc, gchar **argv, - const gchar **legacy_files, ApplySettingsFn apply_fn, CreateDialogFn create_dialog_fn, SetupPropertyEditorsFn setup_property_editors_fn, diff --git a/capplets/common/gconf-property-editor-marshal.c b/capplets/common/gconf-property-editor-marshal.c new file mode 100644 index 000000000..bb6c9b056 --- /dev/null +++ b/capplets/common/gconf-property-editor-marshal.c @@ -0,0 +1,41 @@ +#include +#include +#include "gconf-property-editor-marshal.h" + +/* VOID:STRING,POINTER (peditor-marshal.list:25) */ +void +gconf_property_editor_marshal_VOID__STRING_POINTER (GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data) +{ + typedef void (*GMarshalFunc_VOID__STRING_POINTER) (gpointer data1, + gpointer arg_1, + gpointer arg_2, + gpointer data2); + register GMarshalFunc_VOID__STRING_POINTER callback; + register GCClosure *cc = (GCClosure*) closure; + register gpointer data1, data2; + + g_return_if_fail (n_param_values == 3); + + if (G_CCLOSURE_SWAP_DATA (closure)) + { + data1 = closure->data; + data2 = g_value_peek_pointer (param_values + 0); + } + else + { + data1 = g_value_peek_pointer (param_values + 0); + data2 = closure->data; + } + callback = (GMarshalFunc_VOID__STRING_POINTER) (marshal_data ? marshal_data : cc->callback); + + callback (data1, + (char*) g_value_get_string (param_values + 1), + g_value_get_pointer (param_values + 2), + data2); +} + diff --git a/capplets/common/gconf-property-editor-marshal.h b/capplets/common/gconf-property-editor-marshal.h new file mode 100644 index 000000000..78306b2ab --- /dev/null +++ b/capplets/common/gconf-property-editor-marshal.h @@ -0,0 +1,15 @@ + +#include + +G_BEGIN_DECLS + +/* VOID:STRING,POINTER (peditor-marshal.list:25) */ +extern void gconf_property_editor_marshal_VOID__STRING_POINTER (GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data); + +G_END_DECLS + diff --git a/capplets/common/gconf-property-editor.c b/capplets/common/gconf-property-editor.c new file mode 100644 index 000000000..2a0868e3d --- /dev/null +++ b/capplets/common/gconf-property-editor.c @@ -0,0 +1,545 @@ +/* -*- mode: c; style: linux -*- */ + +/* gconf-property-editor.c + * Copyright (C) 2001 Ximian, Inc. + * + * Written by Bradford Hovinen + * + * 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, 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. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "gconf-property-editor.h" +#include "gconf-property-editor-marshal.h" + +enum { + VALUE_CHANGED, + LAST_SIGNAL +}; + +enum { + PROP_0, + PROP_KEY, + PROP_CALLBACK, + PROP_CHANGESET, + PROP_OBJECT +}; + +struct _GConfPropertyEditorPrivate +{ + gchar *key; + guint handler_id; + GConfChangeSet *changeset; +}; + +static guint peditor_signals[LAST_SIGNAL]; + +static GObjectClass *parent_class; + +static void gconf_property_editor_init (GConfPropertyEditor *gconf_property_editor, GConfPropertyEditorClass *class); +static void gconf_property_editor_class_init (GConfPropertyEditorClass *class); +static void gconf_property_editor_base_init (GConfPropertyEditorClass *class); + +static void gconf_property_editor_set_prop (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec); +static void gconf_property_editor_get_prop (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec); + +static void gconf_property_editor_finalize (GObject *object); + +GType +gconf_property_editor_get_type (void) +{ + static GType gconf_property_editor_type = 0; + + if (!gconf_property_editor_type) { + GTypeInfo gconf_property_editor_info = { + sizeof (GConfPropertyEditorClass), + (GBaseInitFunc) gconf_property_editor_base_init, + NULL, /* GBaseFinalizeFunc */ + (GClassInitFunc) gconf_property_editor_class_init, + NULL, /* GClassFinalizeFunc */ + NULL, /* user-supplied data */ + sizeof (GConfPropertyEditor), + 0, /* n_preallocs */ + (GInstanceInitFunc) gconf_property_editor_init, + NULL + }; + + gconf_property_editor_type = + g_type_register_static (G_TYPE_OBJECT, + "GConfPropertyEditor", + &gconf_property_editor_info, 0); + } + + return gconf_property_editor_type; +} + +static void +gconf_property_editor_init (GConfPropertyEditor *gconf_property_editor, GConfPropertyEditorClass *class) +{ + gconf_property_editor->p = g_new0 (GConfPropertyEditorPrivate, 1); +} + +static void +gconf_property_editor_base_init (GConfPropertyEditorClass *class) +{ +} + +static void +gconf_property_editor_class_init (GConfPropertyEditorClass *class) +{ + GObjectClass *object_class; + + object_class = G_OBJECT_CLASS (class); + + g_object_class_install_property + (object_class, PROP_KEY, + g_param_spec_string ("key", + _("Key"), + _("GConf key to which this property editor is attached"), + NULL, + G_PARAM_READWRITE)); + g_object_class_install_property + (object_class, PROP_CALLBACK, + g_param_spec_pointer ("callback", + _("Callback"), + _("Issue this callback when the value associated with key gets changed"), + G_PARAM_WRITABLE)); + g_object_class_install_property + (object_class, PROP_OBJECT, + g_param_spec_object ("object", + _("Destroy notify object"), + _("Destroy the property editor when this object gets destroyed"), + G_TYPE_OBJECT, + G_PARAM_WRITABLE)); + g_object_class_install_property + (object_class, PROP_CHANGESET, + g_param_spec_object ("changeset", + _("Change set"), + _("GConf change set containing data to be forwarded to the gconf engine on apply"), + G_TYPE_OBJECT, + G_PARAM_READWRITE)); + + peditor_signals[VALUE_CHANGED] = + g_signal_new ("value-changed", + 0, G_TYPE_FROM_CLASS (object_class), + G_STRUCT_OFFSET (GConfPropertyEditorClass, value_changed), + NULL, NULL, + (GSignalCMarshaller) gconf_property_editor_marshal_VOID__STRING_POINTER, + G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_POINTER); + + object_class->finalize = gconf_property_editor_finalize; + object_class->set_property = gconf_property_editor_set_prop; + object_class->get_property = gconf_property_editor_get_prop; + + parent_class = G_OBJECT_CLASS + (g_type_class_ref (G_TYPE_OBJECT)); +} + +static void +gconf_property_editor_set_prop (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + GConfPropertyEditor *peditor; + GConfEngine *engine; + GConfNotifyFunc cb; + GObject *det_obj; + + g_return_if_fail (object != NULL); + g_return_if_fail (IS_GCONF_PROPERTY_EDITOR (object)); + + peditor = GCONF_PROPERTY_EDITOR (object); + + switch (prop_id) { + case PROP_KEY: + peditor->p->key = g_value_dup_string (value); + break; + + case PROP_CALLBACK: + engine = gconf_engine_get_default (); + cb = g_value_get_pointer (value); + peditor->p->handler_id = + gconf_engine_notify_add (engine, peditor->p->key, + cb, peditor, NULL); + break; + + case PROP_CHANGESET: + peditor->p->changeset = g_value_get_pointer (value); + break; + + case PROP_OBJECT: + det_obj = g_value_get_pointer (value); + g_signal_connect_swapped (det_obj, "destroy", + (GCallback) g_object_unref, + object); + break; + + default: + g_warning ("Bad argument set"); + break; + } +} + +static void +gconf_property_editor_get_prop (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + GConfPropertyEditor *peditor; + + g_return_if_fail (object != NULL); + g_return_if_fail (IS_GCONF_PROPERTY_EDITOR (object)); + + peditor = GCONF_PROPERTY_EDITOR (object); + + switch (prop_id) { + case PROP_KEY: + g_value_set_string (value, peditor->p->key); + break; + + case PROP_CHANGESET: + g_value_set_pointer (value, peditor->p->changeset); + break; + + default: + g_warning ("Bad argument get"); + break; + } +} + +static void +gconf_property_editor_finalize (GObject *object) +{ + GConfPropertyEditor *gconf_property_editor; + + g_return_if_fail (object != NULL); + g_return_if_fail (IS_GCONF_PROPERTY_EDITOR (object)); + + gconf_property_editor = GCONF_PROPERTY_EDITOR (object); + + g_free (gconf_property_editor->p); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +peditor_boolean_value_changed (GConfEngine *engine, guint cnxn_id, GConfEntry *entry, GConfPropertyEditor *peditor) +{ + GtkToggleButton *tb; + GConfValue *value; + + tb = g_object_get_data (G_OBJECT (peditor), "toggle-button"); + + value = gconf_entry_get_value (entry); + if (gtk_toggle_button_get_active (tb) != gconf_value_get_bool (value)) + gtk_toggle_button_set_active (tb, gconf_value_get_bool (value)); +} + +static void +peditor_boolean_widget_changed (GConfPropertyEditor *peditor, GtkToggleButton *tb) +{ + GConfValue *value; + + gconf_change_set_set_bool (peditor->p->changeset, peditor->p->key, gtk_toggle_button_get_active (tb)); + gconf_change_set_check_value (peditor->p->changeset, peditor->p->key, &value); + g_signal_emit (peditor, peditor_signals[VALUE_CHANGED], 0, peditor->p->key, value); + gconf_value_free (value); +} + +GObject * +gconf_peditor_new_boolean (GConfChangeSet *changeset, gchar *key, GtkWidget *checkbox) +{ + GObject *peditor; + GConfEngine *engine; + GConfEntry *gconf_entry; + + peditor = g_object_new (gconf_property_editor_get_type (), + "key", key, + "callback", peditor_boolean_value_changed, + "changeset", changeset, + "object", checkbox); + g_signal_connect_swapped (G_OBJECT (checkbox), "toggled", + (GCallback) peditor_boolean_widget_changed, peditor); + g_object_set_data (peditor, "toggle-button", checkbox); + + engine = gconf_engine_get_default (); + gconf_entry = gconf_engine_get_entry (engine, key, NULL, TRUE, NULL); + peditor_boolean_value_changed (engine, 0, gconf_entry, GCONF_PROPERTY_EDITOR (peditor)); + + return peditor; +} + +static void +peditor_string_value_changed (GConfEngine *engine, guint cnxn_id, GConfEntry *entry, GConfPropertyEditor *peditor) +{ + GtkEntry *gtk_entry; + GConfValue *value; + + gtk_entry = g_object_get_data (G_OBJECT (peditor), "entry"); + + value = gconf_entry_get_value (entry); + if (strcmp (gtk_entry_get_text (gtk_entry), gconf_value_get_string (value))) { + gconf_change_set_remove (peditor->p->changeset, peditor->p->key); + gtk_entry_set_text (gtk_entry, gconf_value_get_string (value)); + } +} + +static void +peditor_string_widget_changed (GConfPropertyEditor *peditor, GtkEntry *entry) +{ + GConfValue *value; + + gconf_change_set_set_string (peditor->p->changeset, peditor->p->key, gtk_entry_get_text (entry)); + gconf_change_set_check_value (peditor->p->changeset, peditor->p->key, &value); + g_signal_emit (peditor, peditor_signals[VALUE_CHANGED], 0, peditor->p->key, value); + gconf_value_free (value); +} + +GObject * +gconf_peditor_new_string (GConfChangeSet *changeset, gchar *key, GtkWidget *entry) +{ + GObject *peditor; + GConfEngine *engine; + GConfEntry *gconf_entry; + + peditor = g_object_new (gconf_property_editor_get_type (), + "key", key, + "callback", peditor_string_value_changed, + "changeset", changeset, + "object", entry); + g_signal_connect_swapped (G_OBJECT (entry), "insert_at_cursor", + (GCallback) peditor_string_widget_changed, peditor); + g_signal_connect_swapped (G_OBJECT (entry), "delete_from_cursor", + (GCallback) peditor_string_widget_changed, peditor); + g_signal_connect_swapped (G_OBJECT (entry), "paste_clipboard", + (GCallback) peditor_string_widget_changed, peditor); + g_object_set_data (peditor, "entry", entry); + + engine = gconf_engine_get_default (); + gconf_entry = gconf_engine_get_entry (engine, key, NULL, TRUE, NULL); + peditor_string_value_changed (engine, 0, gconf_entry, GCONF_PROPERTY_EDITOR (peditor)); + + return peditor; +} + +GObject * +gconf_peditor_new_filename (GConfChangeSet *changeset, gchar *key, GtkWidget *file_entry) +{ + gconf_peditor_new_string (changeset, key, gnome_file_entry_gtk_entry (GNOME_FILE_ENTRY (file_entry))); +} + +static void +peditor_color_value_changed (GConfEngine *engine, guint cnxn_id, GConfEntry *entry, GConfPropertyEditor *peditor) +{ + GnomeColorPicker *cp; + GConfValue *value; + GdkColor *color; + guint16 r, g, b, a; + + cp = g_object_get_data (G_OBJECT (peditor), "cp"); + value = gconf_entry_get_value (entry); + gdk_color_parse (gconf_value_get_string (value), color); + gnome_color_picker_get_i16 (cp, &r, &g, &b, &a); + + if (r != color->red || g != color->green || b != color->blue) { + gconf_change_set_remove (peditor->p->changeset, peditor->p->key); + gnome_color_picker_set_i16 (cp, color->red, color->green, color->blue, 65535); + } +} + +static void +peditor_color_widget_changed (GConfPropertyEditor *peditor, GnomeColorPicker *cp) +{ + gchar *str; + guint8 r, g, b, a; + GConfValue *value; + + gnome_color_picker_get_i8 (cp, &r, &g, &b, &a); + str = g_strdup_printf ("#%02x%02x%02x", r, g, b); + gconf_change_set_set_string (peditor->p->changeset, peditor->p->key, str); + + gconf_change_set_check_value (peditor->p->changeset, peditor->p->key, &value); + g_signal_emit (peditor, peditor_signals[VALUE_CHANGED], 0, peditor->p->key, value); + gconf_value_free (value); +} + +GObject * +gconf_peditor_new_color (GConfChangeSet *changeset, gchar *key, GtkWidget *cp) +{ + GObject *peditor; + GConfEngine *engine; + GConfEntry *gconf_entry; + + peditor = g_object_new (gconf_property_editor_get_type (), + "key", key, + "callback", peditor_color_value_changed, + "changeset", changeset, + "object", cp); + g_signal_connect_swapped (G_OBJECT (cp), "color_set", + (GCallback) peditor_color_widget_changed, peditor); + g_object_set_data (peditor, "cp", cp); + + engine = gconf_engine_get_default (); + gconf_entry = gconf_engine_get_entry (engine, key, NULL, TRUE, NULL); + peditor_color_value_changed (engine, 0, gconf_entry, GCONF_PROPERTY_EDITOR (peditor)); + + return peditor; +} + +static void +peditor_select_menu_value_changed (GConfEngine *engine, guint cnxn_id, GConfEntry *entry, GConfPropertyEditor *peditor) +{ + GtkOptionMenu *option_menu; + GtkMenu *menu; + GList *item; + GConfValue *value; + + gconf_change_set_remove (peditor->p->changeset, peditor->p->key); + value = gconf_entry_get_value (entry); + + option_menu = g_object_get_data (G_OBJECT (peditor), "option-menu"); + menu = GTK_MENU (gtk_option_menu_get_menu (option_menu)); + item = g_list_nth (GTK_MENU_SHELL (menu)->children, gconf_value_get_int (value)); + gtk_menu_item_activate (GTK_MENU_ITEM (item->data)); +} + +static void +peditor_select_menu_widget_changed (GConfPropertyEditor *peditor, GtkMenuItem *item) +{ + GtkOptionMenu *option_menu; + GtkMenu *menu; + gint idx; + GConfValue *value; + + option_menu = g_object_get_data (G_OBJECT (peditor), "option-menu"); + menu = GTK_MENU (gtk_option_menu_get_menu (option_menu)); + idx = g_list_index (GTK_MENU_SHELL (menu)->children, item); + + gconf_change_set_set_int (peditor->p->changeset, peditor->p->key, idx); + + gconf_change_set_check_value (peditor->p->changeset, peditor->p->key, &value); + g_signal_emit (peditor, peditor_signals[VALUE_CHANGED], 0, peditor->p->key, value); + gconf_value_free (value); +} + +GObject * +gconf_peditor_new_select_menu (GConfChangeSet *changeset, gchar *key, GtkWidget *option_menu) +{ + GObject *peditor; + GConfEngine *engine; + GConfEntry *gconf_entry; + GtkMenu *menu; + GList *item; + + peditor = g_object_new (gconf_property_editor_get_type (), + "key", key, + "callback", peditor_select_menu_value_changed, + "changeset", changeset, + "object", option_menu); + + menu = GTK_MENU (gtk_option_menu_get_menu (GTK_OPTION_MENU (option_menu))); + + for (item = GTK_MENU_SHELL (menu)->children; item != NULL; item = item->next) + g_signal_connect_swapped (G_OBJECT (item->data), "activate", + (GCallback) peditor_select_menu_widget_changed, peditor); + + g_object_set_data (peditor, "option-menu", option_menu); + + engine = gconf_engine_get_default (); + gconf_entry = gconf_engine_get_entry (engine, key, NULL, TRUE, NULL); + peditor_select_menu_value_changed (engine, 0, gconf_entry, GCONF_PROPERTY_EDITOR (peditor)); + + return peditor; +} + +static void +peditor_select_radio_value_changed (GConfEngine *engine, guint cnxn_id, GConfEntry *entry, GConfPropertyEditor *peditor) +{ + GSList *group; + GConfValue *value; + + gconf_change_set_remove (peditor->p->changeset, peditor->p->key); + value = gconf_entry_get_value (entry); + + group = g_object_get_data (G_OBJECT (peditor), "group"); + group = g_slist_nth (group, gconf_value_get_int (value)); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (group->data), TRUE); +} + +static void +peditor_select_radio_widget_changed (GConfPropertyEditor *peditor, GtkToggleButton *tb) +{ + GSList *group; + gint idx; + GConfValue *value; + + group = g_object_get_data (G_OBJECT (peditor), "group"); + idx = g_slist_index (group, tb); + + gconf_change_set_set_int (peditor->p->changeset, peditor->p->key, idx); + + gconf_change_set_check_value (peditor->p->changeset, peditor->p->key, &value); + g_signal_emit (peditor, peditor_signals[VALUE_CHANGED], 0, peditor->p->key, value); + gconf_value_free (value); +} + +GObject * +gconf_peditor_new_select_radio (GConfChangeSet *changeset, gchar *key, GSList *radio_group) +{ + GObject *peditor; + GConfEngine *engine; + GConfEntry *gconf_entry; + GSList *item; + + peditor = g_object_new (gconf_property_editor_get_type (), + "key", key, + "callback", peditor_select_radio_value_changed, + "changeset", changeset, + "object", radio_group); + + for (item = radio_group; item != NULL; item = item->next) + g_signal_connect_swapped (G_OBJECT (item->data), "toggled", + (GCallback) peditor_select_radio_widget_changed, peditor); + + g_object_set_data (peditor, "group", radio_group); + + engine = gconf_engine_get_default (); + gconf_entry = gconf_engine_get_entry (engine, key, NULL, TRUE, NULL); + peditor_select_radio_value_changed (engine, 0, gconf_entry, GCONF_PROPERTY_EDITOR (peditor)); + + return peditor; +} + +static void +guard_value_changed (GConfEngine *engine, guint cnxn_id, GConfEntry *entry, GtkWidget *widget) +{ +} + +static void +guard_widget_changed (GConfPropertyEditor *peditor, gchar *key, GConfValue *value, GtkWidget *widget) +{ +} + +void +peditor_widget_set_guard (GConfPropertyEditor *peditor, GtkWidget *widget, gchar *key) +{ +} + diff --git a/capplets/common/gconf-property-editor.h b/capplets/common/gconf-property-editor.h new file mode 100644 index 000000000..76df6143f --- /dev/null +++ b/capplets/common/gconf-property-editor.h @@ -0,0 +1,82 @@ +/* -*- mode: c; style: linux -*- */ + +/* gconf-property-editor.h + * Copyright (C) 2001 Ximian, Inc. + * + * Written by Bradford Hovinen + * + * 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, 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. + */ + +#ifndef __GCONF_PROPERTY_EDITOR_H +#define __GCONF_PROPERTY_EDITOR_H + +#include +#include +#include + +G_BEGIN_DECLS + +#define GCONF_PROPERTY_EDITOR(obj) G_TYPE_CHECK_INSTANCE_CAST (obj, gconf_property_editor_get_type (), GConfPropertyEditor) +#define GCONF_PROPERTY_EDITOR_CLASS(klass) G_TYPE_CHECK_CLASS_CAST (klass, gconf_property_editor_get_type (), GConfPropertyEditorClass) +#define IS_GCONF_PROPERTY_EDITOR(obj) G_TYPE_CHECK_INSTANCE_TYPE (obj, gconf_property_editor_get_type ()) + +typedef struct _GConfPropertyEditor GConfPropertyEditor; +typedef struct _GConfPropertyEditorClass GConfPropertyEditorClass; +typedef struct _GConfPropertyEditorPrivate GConfPropertyEditorPrivate; + +struct _GConfPropertyEditor +{ + GObject parent; + + GConfPropertyEditorPrivate *p; +}; + +struct _GConfPropertyEditorClass +{ + GObjectClass g_object_class; + + void (*value_changed) (GConfPropertyEditor *peditor, gchar *key, GConfValue *value); +}; + +GType gconf_property_editor_get_type (void); + +GObject *gconf_peditor_new_boolean (GConfChangeSet *changeset, + gchar *key, + GtkWidget *checkbox); +GObject *gconf_peditor_new_string (GConfChangeSet *changeset, + gchar *key, + GtkWidget *entry); +GObject *gconf_peditor_new_filename (GConfChangeSet *changeset, + gchar *key, + GtkWidget *file_entry); +GObject *gconf_peditor_new_color (GConfChangeSet *changeset, + gchar *key, + GtkWidget *color_entry); +GObject *gconf_peditor_new_select_menu (GConfChangeSet *changeset, + gchar *key, + GtkWidget *option_menu); +GObject *gconf_peditor_new_select_radio (GConfChangeSet *changeset, + gchar *key, + GSList *radio_group); + +void gconf_peditor_widget_set_guard (GConfPropertyEditor *peditor, + GtkWidget *widget, + gchar *key); + +G_END_DECLS + +#endif /* __GCONF_PROPERTY_EDITOR_H */