/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */ /* vim:set et sts=4: */ /* IBus - The Input Bus * Copyright (C) 2008-2010 Peng Huang * Copyright (C) 2008-2010 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 * USA */ #include "ibusinternal.h" #include "ibusproperty.h" #include "ibusproplist.h" #include "ibusenumtypes.h" enum { LAST_SIGNAL, }; enum { PROP_0 = 0, PROP_KEY, PROP_ICON, PROP_LABEL, PROP_SYMBOL, PROP_TOOLTIP, PROP_SENSITIVE, PROP_VISIBLE, PROP_PROP_TYPE, PROP_STATE, PROP_SUB_PROPS, }; /* _IBusPropertyPrivate */ struct _IBusPropertyPrivate { gchar *key; gchar *icon; IBusText *label; IBusText *symbol; IBusText *tooltip; gboolean sensitive; gboolean visible; IBusPropType type; IBusPropState state; IBusPropList *sub_props; }; #define IBUS_PROPERTY_GET_PRIVATE(o) \ (G_TYPE_INSTANCE_GET_PRIVATE ((o), IBUS_TYPE_PROPERTY, IBusPropertyPrivate)) /* functions prototype */ static void ibus_property_set_property (IBusProperty *prop, guint prop_id, const GValue *value, GParamSpec *pspec); static void ibus_property_get_property (IBusProperty *prop, guint prop_id, GValue *value, GParamSpec *pspec); static void ibus_property_destroy (IBusProperty *prop); static gboolean ibus_property_serialize (IBusProperty *prop, GVariantBuilder *builder); static gint ibus_property_deserialize (IBusProperty *prop, GVariant *variant); static gboolean ibus_property_copy (IBusProperty *dest, const IBusProperty *src); G_DEFINE_TYPE (IBusProperty, ibus_property, IBUS_TYPE_SERIALIZABLE) static void ibus_property_class_init (IBusPropertyClass *class) { GObjectClass *gobject_class = G_OBJECT_CLASS (class); IBusObjectClass *object_class = IBUS_OBJECT_CLASS (class); IBusSerializableClass *serializable_class = IBUS_SERIALIZABLE_CLASS (class); g_type_class_add_private (class, sizeof (IBusPropertyPrivate)); gobject_class->set_property = (GObjectSetPropertyFunc) ibus_property_set_property; gobject_class->get_property = (GObjectGetPropertyFunc) ibus_property_get_property; object_class->destroy = (IBusObjectDestroyFunc) ibus_property_destroy; serializable_class->serialize = (IBusSerializableSerializeFunc) ibus_property_serialize; serializable_class->deserialize = (IBusSerializableDeserializeFunc) ibus_property_deserialize; serializable_class->copy = (IBusSerializableCopyFunc) ibus_property_copy; /* install properties */ /** * IBusPropert:key: * * The key of property */ g_object_class_install_property (gobject_class, PROP_KEY, g_param_spec_string ("key", "key", "The key of property", "", G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); /** * IBusPropert:icon: * * The icon of property */ g_object_class_install_property (gobject_class, PROP_ICON, g_param_spec_string ("icon", "icon", "The icon of property", "", G_PARAM_READWRITE)); /** * IBusPropert:label: * * The label of property */ g_object_class_install_property (gobject_class, PROP_LABEL, g_param_spec_object("label", "label", "The label of property", IBUS_TYPE_TEXT, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); /** * IBusPropert:symbol: * * The symbol of property */ g_object_class_install_property (gobject_class, PROP_SYMBOL, g_param_spec_object("symbol", "symbol", "The symbol of property", IBUS_TYPE_TEXT, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); /** * IBusPropert:tooltip: * * The tooltip of property */ g_object_class_install_property (gobject_class, PROP_TOOLTIP, g_param_spec_object("tooltip", "tooltip", "The tooltip of property", IBUS_TYPE_TEXT, G_PARAM_READWRITE)); /** * IBusPropert:sensitive: * * The sensitive of property */ g_object_class_install_property (gobject_class, PROP_SENSITIVE, g_param_spec_boolean("sensitive", "sensitive", "The sensitive of property", TRUE, G_PARAM_READWRITE)); /** * IBusPropert:visible: * * The visible of property */ g_object_class_install_property (gobject_class, PROP_VISIBLE, g_param_spec_boolean("visible", "visible", "The visible of property", TRUE, G_PARAM_READWRITE)); /** * IBusPropert:type: * * The type of property */ g_object_class_install_property (gobject_class, PROP_PROP_TYPE, g_param_spec_enum("prop-type", "prop-type", "The type of property", IBUS_TYPE_PROP_TYPE, PROP_TYPE_NORMAL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); /** * IBusPropert:state: * * The state of property */ g_object_class_install_property (gobject_class, PROP_STATE, g_param_spec_enum("state", "state", "The state of property", IBUS_TYPE_PROP_STATE, PROP_STATE_UNCHECKED, G_PARAM_READWRITE)); /** * IBusPropert:sub-props: * * The sub properties of property */ g_object_class_install_property (gobject_class, PROP_SUB_PROPS, g_param_spec_object("sub-props", "sub properties", "The sub properties of property", IBUS_TYPE_PROP_LIST, G_PARAM_READWRITE)); } static void ibus_property_init (IBusProperty *prop) { prop->priv = IBUS_PROPERTY_GET_PRIVATE (prop); ibus_property_set_label (prop, NULL); ibus_property_set_symbol (prop, NULL); ibus_property_set_tooltip (prop, NULL); ibus_property_set_sub_props (prop, NULL); } static void ibus_property_set_property (IBusProperty *prop, guint prop_id, const GValue *value, GParamSpec *pspec) { switch (prop_id) { case PROP_KEY: g_assert (prop->priv->key == NULL); prop->priv->key = g_value_dup_string (value); break; case PROP_ICON: ibus_property_set_icon (prop, g_value_get_string (value)); break; case PROP_LABEL: ibus_property_set_label (prop, g_value_get_object (value)); break; case PROP_SYMBOL: ibus_property_set_symbol (prop, g_value_get_object (value)); break; case PROP_TOOLTIP: ibus_property_set_tooltip (prop, g_value_get_object (value)); break; case PROP_SENSITIVE: ibus_property_set_sensitive (prop, g_value_get_boolean (value)); break; case PROP_VISIBLE: ibus_property_set_visible (prop, g_value_get_boolean (value)); break; case PROP_PROP_TYPE: prop->priv->type = g_value_get_enum (value); break; case PROP_STATE: ibus_property_set_state (prop, g_value_get_enum (value)); break; case PROP_SUB_PROPS: ibus_property_set_sub_props (prop, (IBusPropList *)g_value_get_object (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (prop, prop_id, pspec); } } static void ibus_property_get_property (IBusProperty *prop, guint prop_id, GValue *value, GParamSpec *pspec) { switch (prop_id) { case PROP_KEY: g_value_set_string (value, ibus_property_get_key (prop)); break; case PROP_ICON: g_value_set_string (value, ibus_property_get_icon (prop)); break; case PROP_LABEL: g_value_set_object (value, ibus_property_get_label (prop)); break; case PROP_SYMBOL: g_value_set_object (value, ibus_property_get_symbol (prop)); break; case PROP_TOOLTIP: g_value_set_object (value, ibus_property_get_tooltip (prop)); break; case PROP_SENSITIVE: g_value_set_boolean (value, ibus_property_get_sensitive (prop)); break; case PROP_VISIBLE: g_value_set_boolean (value, ibus_property_get_visible (prop)); break; case PROP_PROP_TYPE: g_value_set_enum (value, ibus_property_get_prop_type (prop)); break; case PROP_STATE: g_value_set_enum (value, ibus_property_get_state (prop)); break; case PROP_SUB_PROPS: g_value_set_object (value, ibus_property_get_sub_props (prop)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (prop, prop_id, pspec); } } static void ibus_property_destroy (IBusProperty *prop) { g_free (prop->priv->key); prop->priv->key = NULL; g_free (prop->priv->icon); prop->priv->icon = NULL; if (prop->priv->label) { g_object_unref (prop->priv->label); prop->priv->label = NULL; } if (prop->priv->symbol) { g_object_unref (prop->priv->symbol); prop->priv->symbol = NULL; } if (prop->priv->tooltip) { g_object_unref (prop->priv->tooltip); prop->priv->tooltip = NULL; } if (prop->priv->sub_props) { g_object_unref (prop->priv->sub_props); prop->priv->sub_props = NULL; } IBUS_OBJECT_CLASS (ibus_property_parent_class)->destroy ((IBusObject *)prop); } gboolean ibus_property_serialize (IBusProperty *prop, GVariantBuilder *builder) { gboolean retval; retval = IBUS_SERIALIZABLE_CLASS (ibus_property_parent_class)->serialize ((IBusSerializable *) prop, builder); g_return_val_if_fail (retval, FALSE); g_return_val_if_fail (IBUS_IS_PROPERTY (prop), FALSE); g_variant_builder_add (builder, "s", prop->priv->key); g_variant_builder_add (builder, "u", prop->priv->type); g_variant_builder_add (builder, "v", ibus_serializable_serialize ((IBusSerializable *)prop->priv->label)); g_variant_builder_add (builder, "s", prop->priv->icon); g_variant_builder_add (builder, "v", ibus_serializable_serialize ((IBusSerializable *)prop->priv->tooltip)); g_variant_builder_add (builder, "b", prop->priv->sensitive); g_variant_builder_add (builder, "b", prop->priv->visible); g_variant_builder_add (builder, "u", prop->priv->state); g_variant_builder_add (builder, "v", ibus_serializable_serialize ((IBusSerializable *)prop->priv->sub_props)); /* Keep the serialized order for the compatibility when add new members. */ g_variant_builder_add (builder, "v", ibus_serializable_serialize ((IBusSerializable *)prop->priv->symbol)); return TRUE; } static gint ibus_property_deserialize (IBusProperty *prop, GVariant *variant) { gint retval; retval = IBUS_SERIALIZABLE_CLASS (ibus_property_parent_class)->deserialize ((IBusSerializable *) prop, variant); g_return_val_if_fail (retval, 0); ibus_g_variant_get_child_string (variant, retval++, &prop->priv->key); g_variant_get_child (variant, retval++, "u", &prop->priv->type); GVariant *subvar = g_variant_get_child_value (variant, retval++); if (prop->priv->label != NULL) { g_object_unref (prop->priv->label); } prop->priv->label = IBUS_TEXT (ibus_serializable_deserialize (subvar)); g_object_ref_sink (prop->priv->label); g_variant_unref (subvar); ibus_g_variant_get_child_string (variant, retval++, &prop->priv->icon); subvar = g_variant_get_child_value (variant, retval++); if (prop->priv->tooltip != NULL) { g_object_unref (prop->priv->tooltip); } prop->priv->tooltip = IBUS_TEXT (ibus_serializable_deserialize (subvar)); g_object_ref_sink (prop->priv->tooltip); g_variant_unref (subvar); g_variant_get_child (variant, retval++, "b", &prop->priv->sensitive); g_variant_get_child (variant, retval++, "b", &prop->priv->visible); g_variant_get_child (variant, retval++, "u", &prop->priv->state); subvar = g_variant_get_child_value (variant, retval++); if (prop->priv->sub_props != NULL) { g_object_unref (prop->priv->sub_props); } prop->priv->sub_props = IBUS_PROP_LIST (ibus_serializable_deserialize (subvar)); g_object_ref_sink (prop->priv->sub_props); g_variant_unref (subvar); /* Keep the serialized order for the compatibility when add new members. */ subvar = g_variant_get_child_value (variant, retval++); if (prop->priv->symbol != NULL) { g_object_unref (prop->priv->symbol); } prop->priv->symbol = IBUS_TEXT (ibus_serializable_deserialize (subvar)); g_object_ref_sink (prop->priv->symbol); g_variant_unref (subvar); return retval; } static gboolean ibus_property_copy (IBusProperty *dest, const IBusProperty *src) { gboolean retval; retval = IBUS_SERIALIZABLE_CLASS (ibus_property_parent_class)->copy ((IBusSerializable *) dest, (IBusSerializable *) src); g_return_val_if_fail (retval, FALSE); g_return_val_if_fail (IBUS_IS_PROPERTY (dest), FALSE); g_return_val_if_fail (IBUS_IS_PROPERTY (src), FALSE); dest->priv->key = g_strdup (src->priv->key); dest->priv->icon = g_strdup (src->priv->icon); if (src->priv->label) { dest->priv->label = (IBusText *) ibus_serializable_copy ((IBusSerializable *) src->priv->label); } else dest->priv->label = ibus_text_new_from_static_string (""); if (src->priv->symbol) { dest->priv->symbol = (IBusText *) ibus_serializable_copy ((IBusSerializable *) src->priv->symbol); } else dest->priv->symbol = ibus_text_new_from_static_string (""); if (src->priv->tooltip) { dest->priv->tooltip = (IBusText *) ibus_serializable_copy ((IBusSerializable *) src->priv->tooltip); } else dest->priv->tooltip = ibus_text_new_from_static_string (""); dest->priv->sensitive = src->priv->sensitive; dest->priv->visible = src->priv->visible; dest->priv->type = src->priv->type; dest->priv->state = src->priv->state; dest->priv->sub_props = (IBusPropList *) ibus_serializable_copy ((IBusSerializable *) src->priv->sub_props); return TRUE; } IBusProperty * ibus_property_new (const gchar *key, IBusPropType type, IBusText *label, const gchar *icon, IBusText *tooltip, gboolean sensitive, gboolean visible, IBusPropState state, IBusPropList *props) { g_return_val_if_fail (key != NULL, NULL); g_return_val_if_fail (type >= PROP_TYPE_NORMAL && type <= PROP_TYPE_SEPARATOR, NULL); return ibus_property_new_varargs ("key", key, "prop-type", type, "label", label, "icon", icon, "tooltip", tooltip, "sensitive", sensitive, "visible", visible, "state", state, "sub-props", props, NULL); } IBusProperty * ibus_property_new_varargs (const gchar *first_property_name, ...) { va_list var_args; IBusProperty *prop; g_assert (first_property_name); va_start (var_args, first_property_name); prop = (IBusProperty *) g_object_new_valist (IBUS_TYPE_PROPERTY, first_property_name, var_args); va_end (var_args); g_assert (prop->priv->key); g_assert (prop->priv->type >= PROP_TYPE_NORMAL && prop->priv->type <= PROP_TYPE_SEPARATOR); return prop; } #define IBUS_PROPERTY_GET_FIELD(field, return_type) \ return_type \ ibus_property_get_ ## field (IBusProperty *prop) \ { \ return prop->priv->field; \ } IBUS_PROPERTY_GET_FIELD (key, const gchar *) IBUS_PROPERTY_GET_FIELD (icon, const gchar *) IBUS_PROPERTY_GET_FIELD (label, IBusText *) IBUS_PROPERTY_GET_FIELD (symbol, IBusText *) IBUS_PROPERTY_GET_FIELD (tooltip, IBusText *) IBUS_PROPERTY_GET_FIELD (sensitive, gboolean) IBUS_PROPERTY_GET_FIELD (visible, gboolean) IBUS_PROPERTY_GET_FIELD (state, IBusPropState) IBUS_PROPERTY_GET_FIELD (sub_props, IBusPropList *) #undef IBUS_PROPERTY_GET_FIELD /* ibus_property_get_type() exists */ IBusPropType ibus_property_get_prop_type (IBusProperty *prop) { g_assert (IBUS_IS_PROPERTY (prop)); return prop->priv->type; } void ibus_property_set_label (IBusProperty *prop, IBusText *label) { g_assert (IBUS_IS_PROPERTY (prop)); g_return_if_fail (label == NULL || IBUS_IS_TEXT (label)); if (prop->priv->label) { g_object_unref (prop->priv->label); } if (label == NULL) { prop->priv->label = ibus_text_new_from_static_string (""); } else { prop->priv->label = g_object_ref_sink (label); } } void ibus_property_set_symbol (IBusProperty *prop, IBusText *symbol) { g_assert (IBUS_IS_PROPERTY (prop)); g_return_if_fail (symbol == NULL || IBUS_IS_TEXT (symbol)); if (prop->priv->symbol) { g_object_unref (prop->priv->symbol); } if (symbol == NULL) { prop->priv->symbol = ibus_text_new_from_static_string (""); } else { prop->priv->symbol = g_object_ref_sink (symbol); } } void ibus_property_set_icon (IBusProperty *prop, const gchar *icon) { g_assert (IBUS_IS_PROPERTY (prop)); g_free (prop->priv->icon); prop->priv->icon = g_strdup (icon != NULL ? icon : ""); } void ibus_property_set_tooltip (IBusProperty *prop, IBusText *tooltip) { g_assert (IBUS_IS_PROPERTY (prop)); g_assert (tooltip == NULL || IBUS_IS_TEXT (tooltip)); IBusPropertyPrivate *priv = prop->priv; if (priv->tooltip) { g_object_unref (priv->tooltip); } if (tooltip == NULL) { priv->tooltip = ibus_text_new_from_static_string (""); g_object_ref_sink (priv->tooltip); } else { priv->tooltip = tooltip; g_object_ref_sink (priv->tooltip); } } void ibus_property_set_sensitive (IBusProperty *prop, gboolean sensitive) { g_assert (IBUS_IS_PROPERTY (prop)); prop->priv->sensitive = sensitive; } void ibus_property_set_visible (IBusProperty *prop, gboolean visible) { g_assert (IBUS_IS_PROPERTY (prop)); prop->priv->visible = visible; } void ibus_property_set_state (IBusProperty *prop, IBusPropState state) { g_assert (IBUS_IS_PROPERTY (prop)); g_assert (state == PROP_STATE_UNCHECKED || state == PROP_STATE_CHECKED || state == PROP_STATE_INCONSISTENT); prop->priv->state = state; } void ibus_property_set_sub_props (IBusProperty *prop, IBusPropList *prop_list) { g_assert (IBUS_IS_PROPERTY (prop)); g_assert (IBUS_IS_PROP_LIST (prop_list) || prop_list == NULL); IBusPropertyPrivate *priv = prop->priv; if (priv->sub_props) { g_object_unref (priv->sub_props); } if (prop_list) { priv->sub_props = prop_list; g_object_ref_sink (prop_list); } else { priv->sub_props = ibus_prop_list_new (); g_object_ref_sink (priv->sub_props); } } gboolean ibus_property_update (IBusProperty *prop, IBusProperty *prop_update) { g_assert (IBUS_IS_PROPERTY (prop)); g_assert (IBUS_IS_PROPERTY (prop_update)); IBusPropertyPrivate *priv = prop->priv; IBusPropertyPrivate *priv_update = prop_update->priv; if (g_strcmp0 (priv->key, priv_update->key) != 0) { return ibus_prop_list_update_property (priv->sub_props, prop_update); } /* Do not support update prop type */ g_assert (priv->type == priv_update->type); ibus_property_set_icon (prop, ibus_property_get_icon (prop_update)); ibus_property_set_label (prop, ibus_property_get_label (prop_update)); ibus_property_set_symbol (prop, ibus_property_get_symbol (prop_update)); ibus_property_set_tooltip (prop, ibus_property_get_tooltip (prop_update)); ibus_property_set_visible (prop, ibus_property_get_visible (prop_update)); ibus_property_set_state (prop, ibus_property_get_state (prop_update)); ibus_property_set_sensitive (prop, ibus_property_get_sensitive (prop_update)); /* Do not support update sub props */ return TRUE; }