Commit cc90f101 authored by Dan Winship's avatar Dan Winship Committed by Dan Williams

libnm-glib: simplify handling of object and object array properties

Add an "object_type" field to NMPropertiesInfo, and use that with
DBUS_TYPE_G_OBJECT_PATH and DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH
properties so that we don't need custom marshallers for each one.

When creating an NMDevice or NMActiveConnection, we need to fetch an
extra property first to figure out the exact subclass to use, so add a
bit of infrastructure for that as well. Also, do that preprocessing
asynchronously when processing a property change notification, so that
it doesn't block the main loop.
parent 5afcee46
......@@ -28,14 +28,24 @@
#include "nm-object-private.h"
#include "nm-types-private.h"
#include "nm-device.h"
#include "nm-device-private.h"
#include "nm-connection.h"
#include "nm-vpn-connection.h"
G_DEFINE_TYPE (NMActiveConnection, nm_active_connection, NM_TYPE_OBJECT)
static GType nm_active_connection_type_for_path (DBusGConnection *connection,
const char *path);
static void nm_active_connection_type_for_path_async (DBusGConnection *connection,
const char *path,
NMObjectTypeCallbackFunc callback,
gpointer user_data);
#define NM_ACTIVE_CONNECTION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_ACTIVE_CONNECTION, NMActiveConnectionPrivate))
static gboolean demarshal_devices (NMObject *object, GParamSpec *pspec, GValue *value, gpointer field);
G_DEFINE_TYPE_WITH_CODE (NMActiveConnection, nm_active_connection, NM_TYPE_OBJECT,
_nm_object_register_type_func (g_define_type_id,
nm_active_connection_type_for_path,
nm_active_connection_type_for_path_async);
)
#define NM_ACTIVE_CONNECTION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_ACTIVE_CONNECTION, NMActiveConnectionPrivate))
typedef struct {
gboolean disposed;
......@@ -95,6 +105,104 @@ nm_active_connection_new (DBusGConnection *connection, const char *path)
NULL);
}
static GType
nm_active_connection_type_for_path (DBusGConnection *connection,
const char *path)
{
DBusGProxy *proxy;
GError *error = NULL;
GValue value = {0,};
GType type;
proxy = dbus_g_proxy_new_for_name (connection,
NM_DBUS_SERVICE,
path,
"org.freedesktop.DBus.Properties");
if (!proxy) {
g_warning ("%s: couldn't create D-Bus object proxy.", __func__);
return G_TYPE_INVALID;
}
/* Have to create an NMVPNConnection if it's a VPN connection, otherwise
* a plain NMActiveConnection.
*/
if (dbus_g_proxy_call (proxy,
"Get", &error,
G_TYPE_STRING, NM_DBUS_INTERFACE_ACTIVE_CONNECTION,
G_TYPE_STRING, "Vpn",
G_TYPE_INVALID,
G_TYPE_VALUE, &value, G_TYPE_INVALID)) {
if (g_value_get_boolean (&value))
type = NM_TYPE_VPN_CONNECTION;
else
type = NM_TYPE_ACTIVE_CONNECTION;
} else {
g_warning ("Error in getting active connection 'Vpn' property: (%d) %s",
error->code, error->message);
g_error_free (error);
type = G_TYPE_INVALID;
}
g_object_unref (proxy);
return type;
}
typedef struct {
DBusGConnection *connection;
NMObjectTypeCallbackFunc callback;
gpointer user_data;
} NMActiveConnectionAsyncData;
static void
async_got_type (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data)
{
NMActiveConnectionAsyncData *async_data = user_data;
GValue value = G_VALUE_INIT;
const char *path = dbus_g_proxy_get_path (proxy);
GError *error = NULL;
GType type;
if (dbus_g_proxy_end_call (proxy, call, &error,
G_TYPE_VALUE, &value,
G_TYPE_INVALID)) {
if (g_value_get_boolean (&value))
type = NM_TYPE_VPN_CONNECTION;
else
type = NM_TYPE_ACTIVE_CONNECTION;
} else {
g_warning ("%s: could not read properties for %s: %s", __func__, path, error->message);
type = G_TYPE_INVALID;
}
async_data->callback (type, async_data->user_data);
g_object_unref (proxy);
g_slice_free (NMActiveConnectionAsyncData, async_data);
}
static void
nm_active_connection_type_for_path_async (DBusGConnection *connection,
const char *path,
NMObjectTypeCallbackFunc callback,
gpointer user_data)
{
NMActiveConnectionAsyncData *async_data;
DBusGProxy *proxy;
async_data = g_slice_new (NMActiveConnectionAsyncData);
async_data->connection = connection;
async_data->callback = callback;
async_data->user_data = user_data;
proxy = dbus_g_proxy_new_for_name (connection, NM_DBUS_SERVICE, path,
"org.freedesktop.DBus.Properties");
dbus_g_proxy_begin_call (proxy, "Get",
async_got_type, async_data, NULL,
G_TYPE_STRING, NM_DBUS_INTERFACE_ACTIVE_CONNECTION,
G_TYPE_STRING, "Vpn",
G_TYPE_INVALID);
}
/**
* nm_active_connection_get_connection:
* @connection: a #NMActiveConnection
......@@ -316,19 +424,6 @@ get_property (GObject *object,
}
}
static gboolean
demarshal_devices (NMObject *object, GParamSpec *pspec, GValue *value, gpointer field)
{
DBusGConnection *connection;
connection = nm_object_get_connection (object);
if (!_nm_object_array_demarshal (value, (GPtrArray **) field, connection, nm_device_new))
return FALSE;
_nm_object_queue_notify (object, NM_ACTIVE_CONNECTION_DEVICES);
return TRUE;
}
static void
register_properties (NMActiveConnection *connection)
{
......@@ -337,7 +432,7 @@ register_properties (NMActiveConnection *connection)
{ NM_ACTIVE_CONNECTION_CONNECTION, &priv->connection },
{ NM_ACTIVE_CONNECTION_UUID, &priv->uuid },
{ NM_ACTIVE_CONNECTION_SPECIFIC_OBJECT, &priv->specific_object },
{ NM_ACTIVE_CONNECTION_DEVICES, &priv->devices, demarshal_devices },
{ NM_ACTIVE_CONNECTION_DEVICES, &priv->devices, NULL, NM_TYPE_DEVICE },
{ NM_ACTIVE_CONNECTION_STATE, &priv->state },
{ NM_ACTIVE_CONNECTION_DEFAULT, &priv->is_default },
{ NM_ACTIVE_CONNECTION_DEFAULT6, &priv->is_default6 },
......
......@@ -235,62 +235,6 @@ update_wimax_status (NMClient *client, gboolean notify)
}
}
static GObject *
new_active_connection (DBusGConnection *connection, const char *path)
{
DBusGProxy *proxy;
GError *error = NULL;
GValue value = {0,};
GObject *object = NULL;
proxy = dbus_g_proxy_new_for_name (connection,
NM_DBUS_SERVICE,
path,
"org.freedesktop.DBus.Properties");
if (!proxy) {
g_warning ("%s: couldn't create D-Bus object proxy.", __func__);
return NULL;
}
/* Have to create an NMVPNConnection if it's a VPN connection, otherwise
* a plain NMActiveConnection.
*/
if (dbus_g_proxy_call (proxy,
"Get", &error,
G_TYPE_STRING, NM_DBUS_INTERFACE_ACTIVE_CONNECTION,
G_TYPE_STRING, "Vpn",
G_TYPE_INVALID,
G_TYPE_VALUE, &value, G_TYPE_INVALID)) {
if (g_value_get_boolean (&value))
object = nm_vpn_connection_new (connection, path);
else
object = nm_active_connection_new (connection, path);
} else {
g_warning ("Error in getting active connection 'Vpn' property: (%d) %s",
error->code, error->message);
g_error_free (error);
}
g_object_unref (proxy);
return object;
}
static gboolean
demarshal_active_connections (NMObject *object,
GParamSpec *pspec,
GValue *value,
gpointer field)
{
DBusGConnection *connection;
connection = nm_object_get_connection (object);
if (!_nm_object_array_demarshal (value, (GPtrArray **) field, connection, new_active_connection))
return FALSE;
_nm_object_queue_notify (object, NM_CLIENT_ACTIVE_CONNECTIONS);
return TRUE;
}
static void
register_properties (NMClient *client)
{
......@@ -305,7 +249,7 @@ register_properties (NMClient *client)
{ NM_CLIENT_WWAN_HARDWARE_ENABLED, &priv->wwan_hw_enabled },
{ NM_CLIENT_WIMAX_ENABLED, &priv->wimax_enabled },
{ NM_CLIENT_WIMAX_HARDWARE_ENABLED, &priv->wimax_hw_enabled },
{ NM_CLIENT_ACTIVE_CONNECTIONS, &priv->active_connections, demarshal_active_connections },
{ NM_CLIENT_ACTIVE_CONNECTIONS, &priv->active_connections, NULL, NM_TYPE_ACTIVE_CONNECTION },
{ NULL },
};
......
......@@ -29,8 +29,4 @@ DBusGConnection *nm_device_get_connection (NMDevice *device);
const char *nm_device_get_path (NMDevice *device);
DBusGProxy *nm_device_get_properties_proxy (NMDevice *device);
/* static methods */
NMDeviceType nm_device_type_for_path (DBusGConnection *connection,
const char *path);
#endif /* NM_DEVICE_PRIVATE_H */
......@@ -40,8 +40,6 @@ G_DEFINE_TYPE (NMDeviceWifi, nm_device_wifi, NM_TYPE_DEVICE)
#define NM_DEVICE_WIFI_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_WIFI, NMDeviceWifiPrivate))
static gboolean demarshal_active_ap (NMObject *object, GParamSpec *pspec, GValue *value, gpointer field);
void _nm_device_wifi_set_wireless_enabled (NMDeviceWifi *device, gboolean enabled);
typedef struct {
......@@ -566,40 +564,6 @@ state_changed_cb (NMDevice *device, GParamSpec *pspec, gpointer user_data)
}
}
static gboolean
demarshal_active_ap (NMObject *object, GParamSpec *pspec, GValue *value, gpointer field)
{
NMDeviceWifiPrivate *priv = NM_DEVICE_WIFI_GET_PRIVATE (object);
const char *path;
NMAccessPoint *ap = NULL;
DBusGConnection *connection;
if (value) {
if (!G_VALUE_HOLDS (value, DBUS_TYPE_G_OBJECT_PATH))
return FALSE;
path = g_value_get_boxed (value);
if (path) {
ap = NM_ACCESS_POINT (_nm_object_cache_get (path));
if (!ap) {
connection = nm_object_get_connection (object);
ap = NM_ACCESS_POINT (nm_access_point_new (connection, path));
}
}
}
if (priv->active_ap) {
g_object_unref (priv->active_ap);
priv->active_ap = NULL;
}
if (ap)
priv->active_ap = ap;
_nm_object_queue_notify (object, NM_DEVICE_WIFI_ACTIVE_ACCESS_POINT);
return TRUE;
}
static void
register_properties (NMDeviceWifi *device)
{
......@@ -609,7 +573,7 @@ register_properties (NMDeviceWifi *device)
{ NM_DEVICE_WIFI_PERMANENT_HW_ADDRESS, &priv->perm_hw_address },
{ NM_DEVICE_WIFI_MODE, &priv->mode },
{ NM_DEVICE_WIFI_BITRATE, &priv->rate },
{ NM_DEVICE_WIFI_ACTIVE_ACCESS_POINT, &priv->active_ap, demarshal_active_ap },
{ NM_DEVICE_WIFI_ACTIVE_ACCESS_POINT, &priv->active_ap, NULL, NM_TYPE_ACCESS_POINT },
{ NM_DEVICE_WIFI_CAPABILITIES, &priv->wireless_caps },
{ NULL },
};
......
......@@ -38,8 +38,6 @@ G_DEFINE_TYPE (NMDeviceWimax, nm_device_wimax, NM_TYPE_DEVICE)
#define NM_DEVICE_WIMAX_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_DEVICE_WIMAX, NMDeviceWimaxPrivate))
static gboolean demarshal_active_nsp (NMObject *object, GParamSpec *pspec, GValue *value, gpointer field);
void _nm_device_wimax_set_wireless_enabled (NMDeviceWimax *wimax, gboolean enabled);
typedef struct {
......@@ -552,47 +550,13 @@ state_changed_cb (NMDevice *device, GParamSpec *pspec, gpointer user_data)
}
}
static gboolean
demarshal_active_nsp (NMObject *object, GParamSpec *pspec, GValue *value, gpointer field)
{
NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (object);
const char *path;
NMWimaxNsp *nsp = NULL;
DBusGConnection *connection;
if (value) {
if (!G_VALUE_HOLDS (value, DBUS_TYPE_G_OBJECT_PATH))
return FALSE;
path = g_value_get_boxed (value);
if (path) {
nsp = NM_WIMAX_NSP (_nm_object_cache_get (path));
if (!nsp) {
connection = nm_object_get_connection (object);
nsp = NM_WIMAX_NSP (nm_wimax_nsp_new (connection, path));
}
}
}
if (priv->active_nsp) {
g_object_unref (priv->active_nsp);
priv->active_nsp = NULL;
}
if (nsp)
priv->active_nsp = nsp;
_nm_object_queue_notify (object, NM_DEVICE_WIMAX_ACTIVE_NSP);
return TRUE;
}
static void
register_properties (NMDeviceWimax *wimax)
{
NMDeviceWimaxPrivate *priv = NM_DEVICE_WIMAX_GET_PRIVATE (wimax);
const NMPropertiesInfo property_info[] = {
{ NM_DEVICE_WIMAX_HW_ADDRESS, &priv->hw_address },
{ NM_DEVICE_WIMAX_ACTIVE_NSP, &priv->active_nsp, demarshal_active_nsp },
{ NM_DEVICE_WIMAX_ACTIVE_NSP, &priv->active_nsp, NULL, NM_TYPE_WIMAX_NSP },
{ NM_DEVICE_WIMAX_CENTER_FREQUENCY, &priv->center_freq },
{ NM_DEVICE_WIMAX_RSSI, &priv->rssi },
{ NM_DEVICE_WIMAX_CINR, &priv->cinr },
......
This diff is collapsed.
......@@ -30,12 +30,14 @@
void _nm_object_ensure_inited (NMObject *object);
typedef gboolean (*PropertyMarshalFunc) (NMObject *, GParamSpec *, GValue *, gpointer);
typedef GObject * (*NMObjectCreatorFunc) (DBusGConnection *, const char *);
typedef struct {
const char *name;
gpointer field;
PropertyMarshalFunc func;
GType object_type;
} NMPropertiesInfo;
......@@ -69,4 +71,12 @@ handle_ptr_array_return (GPtrArray *array)
return array;
}
/* object demarshalling support */
typedef GType (*NMObjectTypeFunc) (DBusGConnection *, const char *);
typedef void (*NMObjectTypeCallbackFunc) (GType, gpointer);
typedef void (*NMObjectTypeAsyncFunc) (DBusGConnection *, const char *, NMObjectTypeCallbackFunc, gpointer);
void _nm_object_register_type_func (GType base_type, NMObjectTypeFunc type_func,
NMObjectTypeAsyncFunc type_async_func);
#endif /* NM_OBJECT_PRIVATE_H */
......@@ -30,6 +30,7 @@
#include "nm-object-private.h"
#include "nm-dbus-glib-types.h"
#include "nm-glib-compat.h"
#include "nm-types.h"
#define DEBUG 0
......@@ -37,8 +38,12 @@ G_DEFINE_ABSTRACT_TYPE (NMObject, nm_object, G_TYPE_OBJECT)
#define NM_OBJECT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_OBJECT, NMObjectPrivate))
static GHashTable *type_funcs, *type_async_funcs;
typedef struct {
PropertyMarshalFunc func;
GType object_type;
gpointer field;
} PropertyInfo;
......@@ -192,6 +197,11 @@ nm_object_class_init (NMObjectClass *nm_object_class)
g_type_class_add_private (nm_object_class, sizeof (NMObjectPrivate));
if (!type_funcs) {
type_funcs = g_hash_table_new (NULL, NULL);
type_async_funcs = g_hash_table_new (NULL, NULL);
}
/* virtual methods */
object_class->constructor = constructor;
object_class->set_property = set_property;
......@@ -311,6 +321,81 @@ _nm_object_queue_notify (NMObject *object, const char *property)
priv->notify_props = g_slist_prepend (priv->notify_props, g_strdup (property));
}
void
_nm_object_register_type_func (GType base_type, NMObjectTypeFunc type_func,
NMObjectTypeAsyncFunc type_async_func)
{
g_hash_table_insert (type_funcs,
GSIZE_TO_POINTER (base_type),
type_func);
g_hash_table_insert (type_async_funcs,
GSIZE_TO_POINTER (base_type),
type_async_func);
}
static GObject *
_nm_object_create (GType type, DBusGConnection *connection, const char *path)
{
NMObjectTypeFunc type_func;
type_func = g_hash_table_lookup (type_funcs, GSIZE_TO_POINTER (type));
if (type_func)
type = type_func (connection, path);
return g_object_new (type,
NM_OBJECT_DBUS_CONNECTION, connection,
NM_OBJECT_DBUS_PATH, path,
NULL);
}
typedef void (*NMObjectCreateCallbackFunc) (GObject *, gpointer);
typedef struct {
DBusGConnection *connection;
char *path;
NMObjectCreateCallbackFunc callback;
gpointer user_data;
} NMObjectTypeAsyncData;
static void
async_got_type (GType type, gpointer user_data)
{
NMObjectTypeAsyncData *async_data = user_data;
GObject *object;
if (type != G_TYPE_INVALID) {
object = g_object_new (type,
NM_OBJECT_DBUS_CONNECTION, async_data->connection,
NM_OBJECT_DBUS_PATH, async_data->path,
NULL);
} else
object = NULL;
async_data->callback (object, async_data->user_data);
g_free (async_data->path);
g_slice_free (NMObjectTypeAsyncData, async_data);
}
static void
_nm_object_create_async (GType type, DBusGConnection *connection, const char *path,
NMObjectCreateCallbackFunc callback, gpointer user_data)
{
NMObjectTypeAsyncFunc type_async_func;
NMObjectTypeAsyncData *async_data;
async_data = g_slice_new (NMObjectTypeAsyncData);
async_data->connection = connection;
async_data->path = g_strdup (path);
async_data->callback = callback;
async_data->user_data = user_data;
type_async_func = g_hash_table_lookup (type_async_funcs, GSIZE_TO_POINTER (type));
if (type_async_func)
type_async_func (connection, path, async_got_type, async_data);
else
async_got_type (type, async_data);
}
/* Stolen from dbus-glib */
static char*
wincaps_to_dash (const char *caps)
......@@ -333,19 +418,155 @@ wincaps_to_dash (const char *caps)
return g_string_free (str, FALSE);
}
typedef struct {
NMObject *self;
PropertyInfo *pi;
GObject **objects;
int length, remaining;
gboolean array;
const char *property_name;
} ObjectCreatedData;
static void
handle_property_changed (gpointer key, gpointer data, gpointer user_data)
object_created (GObject *obj, gpointer user_data)
{
ObjectCreatedData *odata = user_data;
NMObject *self = odata->self;
PropertyInfo *pi = odata->pi;
/* We assume that on error, the creator_func printed something */
odata->objects[--odata->remaining] = obj;
if (odata->remaining)
return;
if (odata->array) {
GPtrArray **array = pi->field;
int i;
if (*array)
g_boxed_free (NM_TYPE_OBJECT_ARRAY, *array);
*array = g_ptr_array_sized_new (odata->length);
for (i = 0; i < odata->length; i++) {
if (odata->objects[i])
g_ptr_array_add (*array, odata->objects[i]);
}
} else {
GObject **obj_p = pi->field;
g_clear_object (obj_p);
*obj_p = odata->objects[0];
}
if (odata->property_name)
_nm_object_queue_notify (self, odata->property_name);
g_object_unref (self);
g_free (odata->objects);
g_slice_free (ObjectCreatedData, odata);
}
static gboolean
handle_object_property (NMObject *self, const char *property_name, GValue *value,
PropertyInfo *pi, gboolean synchronously)
{
NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (self);
GObject *obj;
const char *path;
ObjectCreatedData *odata;
odata = g_slice_new (ObjectCreatedData);
odata->self = g_object_ref (self);
odata->pi = pi;
odata->objects = g_new (GObject *, 1);
odata->length = odata->remaining = 1;
odata->array = FALSE;
odata->property_name = property_name;
path = g_value_get_boxed (value);
if (!strcmp (path, "/")) {
object_created (NULL, odata);
return TRUE;
}
obj = G_OBJECT (_nm_object_cache_get (path));
if (obj) {
object_created (obj, odata);
return TRUE;
} else if (synchronously) {
obj = _nm_object_create (pi->object_type, priv->connection, path);
object_created (obj, odata);
return obj != NULL;
} else {
_nm_object_create_async (pi->object_type, priv->connection, path,
object_created, odata);
/* Assume success */
return TRUE;
}
}
static gboolean
handle_object_array_property (NMObject *self, const char *property_name, GValue *value,
PropertyInfo *pi, gboolean synchronously)
{
NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (self);
GObject *obj;
GPtrArray *paths;
GPtrArray **array = pi->field;
const char *path;
ObjectCreatedData *odata;
int i;
paths = g_value_get_boxed (value);
odata = g_slice_new (ObjectCreatedData);
odata->self = g_object_ref (self);
odata->pi = pi;
odata->objects = g_new0 (GObject *, paths->len);
odata->length = odata->remaining = paths->len;
odata->array = TRUE;
odata->property_name = property_name;
for (i = 0; i < paths->len; i++) {
path = paths->pdata[i];
if (!strcmp (path, "/")) {
/* FIXME: can't happen? */
continue;
}
obj = G_OBJECT (_nm_object_cache_get (path));
if (obj) {
object_created (obj, odata);
} else if (synchronously) {
obj = _nm_object_create (pi->object_type, priv->connection, path);
object_created (obj, odata);
} else {
_nm_object_create_async (pi->object_type, priv->connection, path,
object_created, odata);
}
}
if (!synchronously) {
/* Assume success */
return TRUE;
}
return *array && ((*array)->len == paths->len);
}
static void
handle_property_changed (NMObject *self, const char *dbus_name, GValue *value, gboolean synchronously)
{
NMObject *self = NM_OBJECT (user_data);
NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (self);
char *prop_name;
PropertyInfo *pi;
GParamSpec *pspec;
gboolean success = FALSE, found = FALSE;
GSList *iter;
GValue *value = data;
prop_name = wincaps_to_dash ((char *) key);
prop_name = wincaps_to_dash (dbus_name);
/* Iterate through the object and its parents to find the property */
for (iter = priv->property_tables; iter; iter = g_slist_next (iter)) {
......@@ -377,13 +598,18 @@ handle_property_changed (gpointer key, gpointer data, gpointer user_data)
goto out;
}
/* Handle NULL object paths */
if (G_VALUE_HOLDS (value, DBUS_TYPE_G_OBJECT_PATH)) {
if (g_strcmp0 (g_value_get_boxed (value), "/") == 0)
value = NULL;
}
if (pi->object_type) {
if (G_VALUE_HOLDS (value, DBUS_TYPE_G_OBJECT_PATH))
success = handle_object_property (self, pspec->name, value, pi, synchronously);
else if (G_VALUE_HOLDS (value, DBUS_TYPE_G_ARRAY_OF_OBJECT_PATH))
success = handle_object_array_property (self, pspec->name, value, pi, synchronously);
else {
g_warn_if_reached ();
goto out;
}
} else
success = (*(pi->func)) (self, pspec, value, pi->field);
success = (*(pi->func)) (self, pspec, value, pi->field);
if (!success) {
g_warning ("%s: failed to update property '%s' of object type %s.",
__func__,
......@@ -398,7 +624,12 @@ out:
void
_nm_object_process_properties_changed (NMObject *self, GHashTable *properties)
{
g_hash_table_foreach (properties, handle_property_changed, self);
GHashTableIter iter;
gpointer name, value;
g_hash_table_iter_init (&iter, properties);
while (g_hash_table_iter_next (&iter, &name, &value))
handle_property_changed (self, name, value, FALSE);
}
static void
......@@ -509,6 +740,7 @@ _nm_object_register_properties (NMObject *object,
pi = g_malloc0 (sizeof (PropertyInfo));
pi->func = tmp->func ? tmp->func : demarshal_generic;
pi->object_type = tmp->object_type;
pi->field = tmp->field;
g_hash_table_insert (instance, g_strdup (tmp->name), pi);
}
......@@ -591,7 +823,7 @@ _nm_object_reload_property (NMObject *object,
return;
}
handle_property_changed ((gpointer)prop_name, &value, object);
handle_property_changed (object, prop_name, &value, TRUE);
g_value_unset (&value);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment