man nm-settings-nmcli: add "Valid values" field
Show a new field called "Valid values" in those properties that only accept a limited set of values, like enums, ints with a valid range of values, etc. As there is some complex logic behind getting this information, this logic has been put in nm-meta-setting-desc and nm-enum-utils so they can be re-used, avoiding duplicity and errors. Some refactor has been done in nm-meta-setting-desc in this direction, too.
This commit is contained in:
@@ -176,6 +176,11 @@
|
|||||||
Format: <xsl:value-of select="@type"/>
|
Format: <xsl:value-of select="@type"/>
|
||||||
</para>
|
</para>
|
||||||
</xsl:if>
|
</xsl:if>
|
||||||
|
<xsl:if test="@values">
|
||||||
|
<para>
|
||||||
|
Valid values: <xsl:value-of select="@values"/>
|
||||||
|
</para>
|
||||||
|
</xsl:if>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
</xsl:template>
|
</xsl:template>
|
||||||
|
@@ -320,53 +320,117 @@ _nm_utils_enum_from_str_full(GType type,
|
|||||||
const char **
|
const char **
|
||||||
_nm_utils_enum_get_values(GType type, int from, int to)
|
_nm_utils_enum_get_values(GType type, int from, int to)
|
||||||
{
|
{
|
||||||
GTypeClass *klass;
|
int i;
|
||||||
GPtrArray *array;
|
GArray *values_full = _nm_utils_enum_get_values_full(type, from, to, NULL);
|
||||||
int i;
|
GPtrArray *values = g_ptr_array_sized_new(values_full->len + 1);
|
||||||
char sbuf[64];
|
|
||||||
|
|
||||||
klass = g_type_class_ref(type);
|
for (i = 0; i < values_full->len; i++) {
|
||||||
array = g_ptr_array_new();
|
NMUtilsEnumValueInfoFull *v = &g_array_index(values_full, NMUtilsEnumValueInfoFull, i);
|
||||||
|
g_ptr_array_add(values, (gpointer) v->nick);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_ptr_array_add(values, NULL);
|
||||||
|
g_array_unref(values_full);
|
||||||
|
return (const char **) g_ptr_array_free(values, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_free_value_info_full(NMUtilsEnumValueInfoFull *value_info_full)
|
||||||
|
{
|
||||||
|
g_free(value_info_full->aliases);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_init_value_info_full(NMUtilsEnumValueInfoFull *v, bool is_flag, const char *nick, int value)
|
||||||
|
{
|
||||||
|
char sbuf[64];
|
||||||
|
const char *value_str = is_flag ? g_intern_string(nm_sprintf_buf(sbuf, "0x%x", value))
|
||||||
|
: g_intern_string(nm_sprintf_buf(sbuf, "%d", value));
|
||||||
|
|
||||||
|
v->nick = _enum_is_valid_enum_nick(nick) ? nick : value_str;
|
||||||
|
v->aliases = NULL;
|
||||||
|
v->value_str = value_str;
|
||||||
|
v->value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* _nm_utils_enum_get_values_full:
|
||||||
|
* @type: the enum or flags type
|
||||||
|
* @from: lowest value to return
|
||||||
|
* @to: highest value to return
|
||||||
|
* @value_infos: (nullable): additional value aliases
|
||||||
|
*
|
||||||
|
* Get the enum or flags values within the given range, putting together the
|
||||||
|
* value, name and aliases of each of them.
|
||||||
|
*
|
||||||
|
* If @value_infos is NULL, no memory will be allocated and deallocated for the
|
||||||
|
* aliases and #NMUtilsEnumValueInfoFull:aliases will be NULL in the returned
|
||||||
|
* data.
|
||||||
|
*
|
||||||
|
* The caller is responsible of releasing the container, but not the contained
|
||||||
|
* data. Only #NMUtilsEnumValueInfoFull:aliases can be stolen (and set to NULL),
|
||||||
|
* and then the caller becomes the responsible to release it.
|
||||||
|
*
|
||||||
|
* Return: (transfer container): an array of #NMUtilsEnumValueInfoFull.
|
||||||
|
*/
|
||||||
|
GArray *
|
||||||
|
_nm_utils_enum_get_values_full(GType type,
|
||||||
|
int from,
|
||||||
|
int to,
|
||||||
|
const NMUtilsEnumValueInfo *value_infos)
|
||||||
|
{
|
||||||
|
NMUtilsEnumValueInfoFull v;
|
||||||
|
GArray *array;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
nm_auto_unref_gtypeclass GTypeClass *klass = g_type_class_ref(type);
|
||||||
|
g_return_val_if_fail(G_IS_ENUM_CLASS(klass) || G_IS_FLAGS_CLASS(klass), NULL);
|
||||||
|
|
||||||
|
_ASSERT_enum_values_info(type, value_infos);
|
||||||
|
|
||||||
|
array = g_array_new(FALSE, FALSE, sizeof(NMUtilsEnumValueInfoFull));
|
||||||
|
|
||||||
if (G_IS_ENUM_CLASS(klass)) {
|
if (G_IS_ENUM_CLASS(klass)) {
|
||||||
GEnumClass *enum_class = G_ENUM_CLASS(klass);
|
GEnumClass *enum_class = G_ENUM_CLASS(klass);
|
||||||
GEnumValue *enum_value;
|
|
||||||
|
|
||||||
for (i = 0; i < enum_class->n_values; i++) {
|
for (i = 0; i < enum_class->n_values; i++) {
|
||||||
enum_value = &enum_class->values[i];
|
GEnumValue *enum_val = &enum_class->values[i];
|
||||||
if (enum_value->value >= from && enum_value->value <= to) {
|
|
||||||
if (_enum_is_valid_enum_nick(enum_value->value_nick))
|
|
||||||
g_ptr_array_add(array, (gpointer) enum_value->value_nick);
|
|
||||||
else
|
|
||||||
g_ptr_array_add(
|
|
||||||
array,
|
|
||||||
(gpointer) g_intern_string(nm_sprintf_buf(sbuf, "%d", enum_value->value)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (G_IS_FLAGS_CLASS(klass)) {
|
|
||||||
GFlagsClass *flags_class = G_FLAGS_CLASS(klass);
|
|
||||||
GFlagsValue *flags_value;
|
|
||||||
|
|
||||||
for (i = 0; i < flags_class->n_values; i++) {
|
if (enum_val->value >= from && enum_val->value <= to) {
|
||||||
flags_value = &flags_class->values[i];
|
_init_value_info_full(&v, FALSE, enum_val->value_nick, enum_val->value);
|
||||||
if (flags_value->value >= (guint) from && flags_value->value <= (guint) to) {
|
g_array_append_val(array, v);
|
||||||
if (_enum_is_valid_flags_nick(flags_value->value_nick))
|
|
||||||
g_ptr_array_add(array, (gpointer) flags_value->value_nick);
|
|
||||||
else
|
|
||||||
g_ptr_array_add(
|
|
||||||
array,
|
|
||||||
(gpointer) g_intern_string(
|
|
||||||
nm_sprintf_buf(sbuf, "0x%x", (unsigned) flags_value->value)));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
g_type_class_unref(klass);
|
GFlagsClass *flags_class = G_FLAGS_CLASS(klass);
|
||||||
g_ptr_array_free(array, TRUE);
|
|
||||||
g_return_val_if_reached(NULL);
|
for (i = 0; i < flags_class->n_values; i++) {
|
||||||
|
GFlagsValue *flags_val = &flags_class->values[i];
|
||||||
|
|
||||||
|
if (flags_val->value >= (guint) from && flags_val->value <= (guint) to) {
|
||||||
|
_init_value_info_full(&v, TRUE, flags_val->value_nick, flags_val->value);
|
||||||
|
g_array_append_val(array, v);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
g_type_class_unref(klass);
|
if (value_infos) {
|
||||||
g_ptr_array_add(array, NULL);
|
g_array_set_clear_func(array, (GDestroyNotify) _free_value_info_full);
|
||||||
|
|
||||||
return (const char **) g_ptr_array_free(array, FALSE);
|
for (i = 0; i < array->len; i++) {
|
||||||
|
NMUtilsEnumValueInfoFull *vi_full = &g_array_index(array, NMUtilsEnumValueInfoFull, i);
|
||||||
|
GPtrArray *aliases = g_ptr_array_new();
|
||||||
|
|
||||||
|
const NMUtilsEnumValueInfo *vi;
|
||||||
|
for (vi = value_infos; vi && vi->nick; vi++) {
|
||||||
|
if (vi->value == vi_full->value)
|
||||||
|
g_ptr_array_add(aliases, (gpointer) vi->nick);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_ptr_array_add(aliases, NULL);
|
||||||
|
vi_full->aliases = (const char **) g_ptr_array_free(aliases, FALSE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return array;
|
||||||
}
|
}
|
||||||
|
@@ -15,6 +15,13 @@ typedef struct _NMUtilsEnumValueInfo {
|
|||||||
int value;
|
int value;
|
||||||
} NMUtilsEnumValueInfo;
|
} NMUtilsEnumValueInfo;
|
||||||
|
|
||||||
|
typedef struct _NMUtilsEnumValueInfoFull {
|
||||||
|
const char *nick;
|
||||||
|
const char **aliases;
|
||||||
|
const char *value_str;
|
||||||
|
int value;
|
||||||
|
} NMUtilsEnumValueInfoFull;
|
||||||
|
|
||||||
char *_nm_utils_enum_to_str_full(GType type,
|
char *_nm_utils_enum_to_str_full(GType type,
|
||||||
int value,
|
int value,
|
||||||
const char *sep,
|
const char *sep,
|
||||||
@@ -27,6 +34,11 @@ gboolean _nm_utils_enum_from_str_full(GType type,
|
|||||||
|
|
||||||
const char **_nm_utils_enum_get_values(GType type, int from, int to);
|
const char **_nm_utils_enum_get_values(GType type, int from, int to);
|
||||||
|
|
||||||
|
GArray *_nm_utils_enum_get_values_full(GType type,
|
||||||
|
int from,
|
||||||
|
int to,
|
||||||
|
const NMUtilsEnumValueInfo *value_infos);
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
#endif /* __NM_ENUM_UTILS_H__ */
|
#endif /* __NM_ENUM_UTILS_H__ */
|
||||||
|
@@ -46,22 +46,16 @@ _gobject_property_get_gtype(GObject *gobject, const char *property_name)
|
|||||||
g_return_val_if_reached(G_TYPE_INVALID);
|
g_return_val_if_reached(G_TYPE_INVALID);
|
||||||
}
|
}
|
||||||
|
|
||||||
static GType
|
static GParamSpec *
|
||||||
_gtype_property_get_gtype(GType gtype, const char *property_name)
|
_property_get_spec(const NMMetaPropertyInfo *property_info)
|
||||||
{
|
{
|
||||||
/* given @gtype, a type for a GObject, lookup the property @property_name
|
nm_auto_unref_gtypeclass NMSettingClass *setting_class =
|
||||||
* and return its value_type. */
|
g_type_class_ref(property_info->setting_info->general->get_setting_gtype());
|
||||||
if (G_TYPE_IS_CLASSED(gtype)) {
|
GParamSpec *param_spec =
|
||||||
GParamSpec *param_spec;
|
g_object_class_find_property(G_OBJECT_CLASS(setting_class), property_info->property_name);
|
||||||
nm_auto_unref_gtypeclass GTypeClass *gtypeclass = g_type_class_ref(gtype);
|
|
||||||
|
|
||||||
if (G_IS_OBJECT_CLASS(gtypeclass)) {
|
nm_assert(param_spec);
|
||||||
param_spec = g_object_class_find_property(G_OBJECT_CLASS(gtypeclass), property_name);
|
return param_spec;
|
||||||
if (param_spec)
|
|
||||||
return param_spec->value_type;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
g_return_val_if_reached(G_TYPE_INVALID);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
@@ -1225,6 +1219,113 @@ _get_fcn_gobject_enum(ARGS_GET_FCN)
|
|||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nm_meta_property_int_get_range:
|
||||||
|
* @property_info: a #NMMetaProperty info of a int, uint, int64 or uint64 property
|
||||||
|
* @out_min: (out): low value of the property's valid range
|
||||||
|
* @out_max: (out): high value of the property's valid range
|
||||||
|
*
|
||||||
|
* Returns: FALSE if the full range of the type is returned, TRUE if it's smaller
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
nm_meta_property_int_get_range(const NMMetaPropertyInfo *property_info,
|
||||||
|
NMMetaSignUnsignInt64 *out_min,
|
||||||
|
NMMetaSignUnsignInt64 *out_max)
|
||||||
|
{
|
||||||
|
GParamSpec *pspec = _property_get_spec(property_info);
|
||||||
|
|
||||||
|
g_return_val_if_fail(
|
||||||
|
NM_IN_SET(pspec->value_type, G_TYPE_UINT, G_TYPE_UINT64, G_TYPE_INT, G_TYPE_INT64),
|
||||||
|
FALSE);
|
||||||
|
|
||||||
|
if (property_info->property_typ_data
|
||||||
|
&& (property_info->property_typ_data->subtype.gobject_int.min.u64
|
||||||
|
|| property_info->property_typ_data->subtype.gobject_int.max.u64)) {
|
||||||
|
*out_min = property_info->property_typ_data->subtype.gobject_int.min;
|
||||||
|
*out_max = property_info->property_typ_data->subtype.gobject_int.max;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (pspec->value_type) {
|
||||||
|
case G_TYPE_UINT:
|
||||||
|
out_min->u64 = ((GParamSpecUInt *) pspec)->minimum;
|
||||||
|
out_max->u64 = ((GParamSpecUInt *) pspec)->maximum;
|
||||||
|
return out_min->u64 != 0 || out_max->u64 != G_MAXUINT;
|
||||||
|
case G_TYPE_UINT64:
|
||||||
|
out_min->u64 = ((GParamSpecUInt64 *) pspec)->minimum;
|
||||||
|
out_max->u64 = ((GParamSpecUInt64 *) pspec)->maximum;
|
||||||
|
return out_min->u64 != 0 || out_max->u64 != G_MAXUINT64;
|
||||||
|
case G_TYPE_INT:
|
||||||
|
out_min->i64 = ((GParamSpecInt *) pspec)->minimum;
|
||||||
|
out_max->i64 = ((GParamSpecInt *) pspec)->maximum;
|
||||||
|
return out_min->i64 != G_MININT || out_max->i64 != G_MAXINT;
|
||||||
|
case G_TYPE_INT64:
|
||||||
|
out_min->i64 = ((GParamSpecInt64 *) pspec)->minimum;
|
||||||
|
out_max->i64 = ((GParamSpecInt64 *) pspec)->maximum;
|
||||||
|
return out_min->i64 != G_MININT64 || out_max->i64 != G_MAXINT64;
|
||||||
|
default:
|
||||||
|
g_return_val_if_reached(FALSE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nm_meta_property_enum_get_type:
|
||||||
|
* @property_info: a #NMMetaPropertyInfo of an enum or flags type property
|
||||||
|
*
|
||||||
|
* Returns: the #GType of the property, or G_TYPE_INVALID on error
|
||||||
|
*/
|
||||||
|
GType
|
||||||
|
nm_meta_property_enum_get_type(const NMMetaPropertyInfo *property_info)
|
||||||
|
{
|
||||||
|
GType gtype = _property_get_spec(property_info)->value_type;
|
||||||
|
|
||||||
|
if (property_info->property_typ_data
|
||||||
|
&& property_info->property_typ_data->subtype.gobject_enum.get_gtype) {
|
||||||
|
/* if the property is already enum, don't set get_gtype: it's redundant and error prone */
|
||||||
|
g_return_val_if_fail(NM_IN_SET(gtype, G_TYPE_INT, G_TYPE_UINT), G_TYPE_INVALID);
|
||||||
|
return property_info->property_typ_data->subtype.gobject_enum.get_gtype();
|
||||||
|
}
|
||||||
|
|
||||||
|
g_return_val_if_fail(G_TYPE_IS_ENUM(gtype) || G_TYPE_IS_FLAGS(gtype), G_TYPE_INVALID);
|
||||||
|
return gtype;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nm_meta_property_enum_get_range:
|
||||||
|
* @property_info: a #NMMetaProperty info of an enum or flags type property
|
||||||
|
* @out_min: (out): low value of the property's valid range
|
||||||
|
* @out_max: (out): high value of the property's valid range
|
||||||
|
*
|
||||||
|
* Returns: FALSE if the full range of the type is returned, TRUE if it's smaller
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
nm_meta_property_enum_get_range(const NMMetaPropertyInfo *property_info, int *out_min, int *out_max)
|
||||||
|
{
|
||||||
|
GType gtype = nm_meta_property_enum_get_type(property_info);
|
||||||
|
|
||||||
|
if (property_info->property_typ_data
|
||||||
|
&& (property_info->property_typ_data->subtype.gobject_enum.min
|
||||||
|
|| property_info->property_typ_data->subtype.gobject_enum.max)) {
|
||||||
|
*out_min = property_info->property_typ_data->subtype.gobject_enum.min;
|
||||||
|
*out_max = property_info->property_typ_data->subtype.gobject_enum.max;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (G_TYPE_IS_ENUM(gtype)) {
|
||||||
|
*out_min = G_MININT;
|
||||||
|
*out_max = G_MAXINT;
|
||||||
|
} else if (G_TYPE_IS_FLAGS(gtype)) {
|
||||||
|
*out_min = 0;
|
||||||
|
*out_max = (int) G_MAXUINT;
|
||||||
|
} else {
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
_set_fcn_gobject_string(ARGS_SET_FCN)
|
_set_fcn_gobject_string(ARGS_SET_FCN)
|
||||||
{
|
{
|
||||||
@@ -1318,10 +1419,9 @@ _set_fcn_gobject_int(ARGS_SET_FCN)
|
|||||||
nm_auto_unset_gvalue GValue gval = G_VALUE_INIT;
|
nm_auto_unset_gvalue GValue gval = G_VALUE_INIT;
|
||||||
gboolean is_uint64;
|
gboolean is_uint64;
|
||||||
NMMetaSignUnsignInt64 v;
|
NMMetaSignUnsignInt64 v;
|
||||||
gboolean has_minmax = FALSE;
|
NMMetaSignUnsignInt64 min = {0};
|
||||||
NMMetaSignUnsignInt64 min = {0};
|
NMMetaSignUnsignInt64 max = {0};
|
||||||
NMMetaSignUnsignInt64 max = {0};
|
guint base = 10;
|
||||||
guint base = 10;
|
|
||||||
const NMMetaUtilsIntValueInfo *value_infos;
|
const NMMetaUtilsIntValueInfo *value_infos;
|
||||||
|
|
||||||
if (_SET_FCN_DO_RESET_DEFAULT(property_info, modifier, value))
|
if (_SET_FCN_DO_RESET_DEFAULT(property_info, modifier, value))
|
||||||
@@ -1351,53 +1451,9 @@ _set_fcn_gobject_int(ARGS_SET_FCN)
|
|||||||
|
|
||||||
if (property_info->property_typ_data->subtype.gobject_int.base > 0)
|
if (property_info->property_typ_data->subtype.gobject_int.base > 0)
|
||||||
base = property_info->property_typ_data->subtype.gobject_int.base;
|
base = property_info->property_typ_data->subtype.gobject_int.base;
|
||||||
|
|
||||||
if ((is_uint64
|
|
||||||
&& (property_info->property_typ_data->subtype.gobject_int.min.u64
|
|
||||||
|| property_info->property_typ_data->subtype.gobject_int.max.u64))
|
|
||||||
|| (!is_uint64
|
|
||||||
&& (property_info->property_typ_data->subtype.gobject_int.min.i64
|
|
||||||
|| property_info->property_typ_data->subtype.gobject_int.max.i64))) {
|
|
||||||
min = property_info->property_typ_data->subtype.gobject_int.min;
|
|
||||||
max = property_info->property_typ_data->subtype.gobject_int.max;
|
|
||||||
has_minmax = TRUE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!has_minmax) {
|
nm_meta_property_int_get_range(property_info, &min, &max);
|
||||||
switch (pspec->value_type) {
|
|
||||||
case G_TYPE_INT:
|
|
||||||
{
|
|
||||||
const GParamSpecInt *p = (GParamSpecInt *) pspec;
|
|
||||||
|
|
||||||
min.i64 = p->minimum;
|
|
||||||
max.i64 = p->maximum;
|
|
||||||
} break;
|
|
||||||
case G_TYPE_UINT:
|
|
||||||
{
|
|
||||||
const GParamSpecUInt *p = (GParamSpecUInt *) pspec;
|
|
||||||
|
|
||||||
min.u64 = p->minimum;
|
|
||||||
max.u64 = p->maximum;
|
|
||||||
} break;
|
|
||||||
case G_TYPE_INT64:
|
|
||||||
{
|
|
||||||
const GParamSpecInt64 *p = (GParamSpecInt64 *) pspec;
|
|
||||||
|
|
||||||
min.i64 = p->minimum;
|
|
||||||
max.i64 = p->maximum;
|
|
||||||
} break;
|
|
||||||
case G_TYPE_UINT64:
|
|
||||||
{
|
|
||||||
const GParamSpecUInt64 *p = (GParamSpecUInt64 *) pspec;
|
|
||||||
|
|
||||||
min.u64 = p->minimum;
|
|
||||||
max.u64 = p->maximum;
|
|
||||||
} break;
|
|
||||||
default:
|
|
||||||
g_return_val_if_reached(FALSE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_uint64)
|
if (is_uint64)
|
||||||
v.u64 = _nm_utils_ascii_str_to_uint64(value, base, min.u64, max.u64, 0);
|
v.u64 = _nm_utils_ascii_str_to_uint64(value, base, min.u64, max.u64, 0);
|
||||||
@@ -1629,26 +1685,12 @@ _set_fcn_gobject_enum(ARGS_SET_FCN)
|
|||||||
|
|
||||||
fail:
|
fail:
|
||||||
if (error) {
|
if (error) {
|
||||||
gs_free const char **valid_all = NULL;
|
gs_free const char **valid_all = NULL;
|
||||||
gs_free const char *valid_str = NULL;
|
gs_free const char *valid_str = NULL;
|
||||||
gboolean has_minmax = FALSE;
|
int min;
|
||||||
int min = G_MININT;
|
int max;
|
||||||
int max = G_MAXINT;
|
|
||||||
|
|
||||||
if (property_info->property_typ_data) {
|
|
||||||
if (property_info->property_typ_data->subtype.gobject_enum.min
|
|
||||||
|| property_info->property_typ_data->subtype.gobject_enum.max) {
|
|
||||||
min = property_info->property_typ_data->subtype.gobject_enum.min;
|
|
||||||
max = property_info->property_typ_data->subtype.gobject_enum.max;
|
|
||||||
has_minmax = TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!has_minmax && is_flags) {
|
|
||||||
min = 0;
|
|
||||||
max = (int) G_MAXUINT;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
nm_meta_property_enum_get_range(property_info, &min, &max);
|
||||||
valid_all = nm_utils_enum_get_values(gtype, min, max);
|
valid_all = nm_utils_enum_get_values(gtype, min, max);
|
||||||
valid_str = g_strjoinv(",", (char **) valid_all);
|
valid_str = g_strjoinv(",", (char **) valid_all);
|
||||||
if (is_flags) {
|
if (is_flags) {
|
||||||
@@ -1674,40 +1716,13 @@ static const char *const *
|
|||||||
_values_fcn_gobject_enum(ARGS_VALUES_FCN)
|
_values_fcn_gobject_enum(ARGS_VALUES_FCN)
|
||||||
{
|
{
|
||||||
const NMUtilsEnumValueInfo *value_infos = NULL;
|
const NMUtilsEnumValueInfo *value_infos = NULL;
|
||||||
GType gtype = 0;
|
GType gtype;
|
||||||
gboolean has_gtype = FALSE;
|
int min;
|
||||||
gboolean has_minmax = FALSE;
|
int max;
|
||||||
int min = G_MININT;
|
|
||||||
int max = G_MAXINT;
|
|
||||||
char **v;
|
char **v;
|
||||||
|
|
||||||
if (property_info->property_typ_data) {
|
gtype = nm_meta_property_enum_get_type(property_info);
|
||||||
if (property_info->property_typ_data->subtype.gobject_enum.min
|
nm_meta_property_enum_get_range(property_info, &min, &max);
|
||||||
|| property_info->property_typ_data->subtype.gobject_enum.max) {
|
|
||||||
min = property_info->property_typ_data->subtype.gobject_enum.min;
|
|
||||||
max = property_info->property_typ_data->subtype.gobject_enum.max;
|
|
||||||
has_minmax = TRUE;
|
|
||||||
}
|
|
||||||
if (property_info->property_typ_data->subtype.gobject_enum.get_gtype) {
|
|
||||||
gtype = property_info->property_typ_data->subtype.gobject_enum.get_gtype();
|
|
||||||
has_gtype = TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!has_gtype) {
|
|
||||||
gtype = _gtype_property_get_gtype(property_info->setting_info->general->get_setting_gtype(),
|
|
||||||
property_info->property_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!has_minmax && G_TYPE_IS_CLASSED(gtype)) {
|
|
||||||
nm_auto_unref_gtypeclass GTypeClass *class = NULL;
|
|
||||||
|
|
||||||
class = g_type_class_ref(gtype);
|
|
||||||
if (G_IS_FLAGS_CLASS(class)) {
|
|
||||||
min = 0;
|
|
||||||
max = (int) G_MAXUINT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* There is a problem. For flags, we don't expand to all the values that we could
|
/* There is a problem. For flags, we don't expand to all the values that we could
|
||||||
* complete for. We only expand to a single flag "FLAG1", but if the property
|
* complete for. We only expand to a single flag "FLAG1", but if the property
|
||||||
|
@@ -505,6 +505,16 @@ const NMMetaSettingValidPartItem *const *
|
|||||||
nm_meta_setting_info_valid_parts_for_slave_type(const char *slave_type,
|
nm_meta_setting_info_valid_parts_for_slave_type(const char *slave_type,
|
||||||
const char **out_slave_name);
|
const char **out_slave_name);
|
||||||
|
|
||||||
|
gboolean nm_meta_property_int_get_range(const NMMetaPropertyInfo *property_info,
|
||||||
|
NMMetaSignUnsignInt64 *out_min,
|
||||||
|
NMMetaSignUnsignInt64 *out_max);
|
||||||
|
|
||||||
|
gboolean nm_meta_property_enum_get_range(const NMMetaPropertyInfo *property_info,
|
||||||
|
int *out_min,
|
||||||
|
int *out_max);
|
||||||
|
|
||||||
|
GType nm_meta_property_enum_get_type(const NMMetaPropertyInfo *property_info);
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
@@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#include "libnmc-setting/nm-meta-setting-desc.h"
|
#include "libnmc-setting/nm-meta-setting-desc.h"
|
||||||
#include "libnmc-setting/nm-meta-setting-base.h"
|
#include "libnmc-setting/nm-meta-setting-base.h"
|
||||||
|
#include "libnm-glib-aux/nm-enum-utils.h"
|
||||||
#include "nm-core-enum-types.h"
|
#include "nm-core-enum-types.h"
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -70,7 +71,7 @@ _property_get_gtype(const NMMetaPropertyInfo *prop_info)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
_get_enum_format(GType g_type)
|
get_enum_format(GType g_type)
|
||||||
{
|
{
|
||||||
if (G_TYPE_IS_FLAGS(g_type))
|
if (G_TYPE_IS_FLAGS(g_type))
|
||||||
return g_strdup_printf("flags (%s)", g_type_name(g_type));
|
return g_strdup_printf("flags (%s)", g_type_name(g_type));
|
||||||
@@ -78,22 +79,6 @@ _get_enum_format(GType g_type)
|
|||||||
return g_strdup_printf("choice (%s)", g_type_name(g_type));
|
return g_strdup_printf("choice (%s)", g_type_name(g_type));
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *
|
|
||||||
get_enum_format(const NMMetaPropertyInfo *prop_info)
|
|
||||||
{
|
|
||||||
GType gtype = G_TYPE_INVALID;
|
|
||||||
const NMMetaPropertyTypData *prop_typ_data = prop_info->property_typ_data;
|
|
||||||
|
|
||||||
if (prop_typ_data && prop_typ_data->subtype.gobject_enum.get_gtype)
|
|
||||||
gtype = prop_typ_data->subtype.gobject_enum.get_gtype();
|
|
||||||
else
|
|
||||||
gtype = _property_get_gtype(prop_info);
|
|
||||||
|
|
||||||
prop_assert(gtype != G_TYPE_INVALID, prop_info, "unknown property's enum type");
|
|
||||||
|
|
||||||
return _get_enum_format(gtype);
|
|
||||||
}
|
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
get_mac_format(const NMMetaPropertyInfo *prop_info)
|
get_mac_format(const NMMetaPropertyInfo *prop_info)
|
||||||
{
|
{
|
||||||
@@ -185,11 +170,11 @@ get_property_format(const NMMetaPropertyInfo *prop_info)
|
|||||||
case NM_META_PROPERTY_TYPE_FORMAT_STRING:
|
case NM_META_PROPERTY_TYPE_FORMAT_STRING:
|
||||||
return g_strdup("string");
|
return g_strdup("string");
|
||||||
case NM_META_PROPERTY_TYPE_FORMAT_ENUM:
|
case NM_META_PROPERTY_TYPE_FORMAT_ENUM:
|
||||||
return get_enum_format(prop_info);
|
return get_enum_format(nm_meta_property_enum_get_type(prop_info));
|
||||||
case NM_META_PROPERTY_TYPE_FORMAT_SECRET_FLAGS:
|
case NM_META_PROPERTY_TYPE_FORMAT_SECRET_FLAGS:
|
||||||
return _get_enum_format(NM_TYPE_SETTING_SECRET_FLAGS);
|
return get_enum_format(NM_TYPE_SETTING_SECRET_FLAGS);
|
||||||
case NM_META_PROPERTY_TYPE_FORMAT_DCB_FLAGS:
|
case NM_META_PROPERTY_TYPE_FORMAT_DCB_FLAGS:
|
||||||
return _get_enum_format(NM_TYPE_SETTING_DCB_FLAGS);
|
return get_enum_format(NM_TYPE_SETTING_DCB_FLAGS);
|
||||||
case NM_META_PROPERTY_TYPE_FORMAT_BOOL:
|
case NM_META_PROPERTY_TYPE_FORMAT_BOOL:
|
||||||
return g_strdup("boolean");
|
return g_strdup("boolean");
|
||||||
case NM_META_PROPERTY_TYPE_FORMAT_TERNARY:
|
case NM_META_PROPERTY_TYPE_FORMAT_TERNARY:
|
||||||
@@ -224,6 +209,199 @@ get_property_format(const NMMetaPropertyInfo *prop_info)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define append_vals(to, ...) \
|
||||||
|
G_STMT_START \
|
||||||
|
{ \
|
||||||
|
size_t i; \
|
||||||
|
const char *from[] = {__VA_ARGS__}; \
|
||||||
|
for (i = 0; i < NM_N_ELEMENTS(from); i++) \
|
||||||
|
g_ptr_array_add((to), g_strdup(from[i])); \
|
||||||
|
} \
|
||||||
|
G_STMT_END
|
||||||
|
|
||||||
|
static void
|
||||||
|
append_connection_types(GPtrArray *valid_values)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
for (i = 0; i < _NM_META_SETTING_TYPE_NUM; i++) {
|
||||||
|
/* If the setting has a priority of a base-type, it's a valid value for connection.type */
|
||||||
|
NMSettingPriority pri =
|
||||||
|
_nm_setting_type_get_base_type_priority(nm_meta_setting_infos[i].get_setting_gtype());
|
||||||
|
if (pri != NM_SETTING_PRIORITY_INVALID)
|
||||||
|
g_ptr_array_add(valid_values, g_strdup(nm_meta_setting_infos[i].setting_name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
append_int_valid_range(const NMMetaPropertyInfo *prop_info, GPtrArray *valid_values)
|
||||||
|
{
|
||||||
|
NMMetaSignUnsignInt64 min;
|
||||||
|
NMMetaSignUnsignInt64 max;
|
||||||
|
|
||||||
|
nm_meta_property_int_get_range(prop_info, &min, &max);
|
||||||
|
if (NM_IN_SET(_property_get_gtype(prop_info), G_TYPE_UINT, G_TYPE_UINT64))
|
||||||
|
g_ptr_array_add(valid_values, g_strdup_printf("%lu - %lu", min.u64, max.u64));
|
||||||
|
else
|
||||||
|
g_ptr_array_add(valid_values, g_strdup_printf("%ld - %ld", min.i64, max.i64));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_append_enum_valid_values(GType g_type,
|
||||||
|
int min,
|
||||||
|
int max,
|
||||||
|
const NMUtilsEnumValueInfo *value_infos,
|
||||||
|
GPtrArray *valid_values)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
const char **alias;
|
||||||
|
GString *names = g_string_sized_new(64);
|
||||||
|
GArray *values = _nm_utils_enum_get_values_full(g_type, min, max, value_infos);
|
||||||
|
|
||||||
|
for (i = 0; i < values->len; i++) {
|
||||||
|
NMUtilsEnumValueInfoFull *val = &g_array_index(values, NMUtilsEnumValueInfoFull, i);
|
||||||
|
|
||||||
|
g_string_assign(names, val->nick);
|
||||||
|
|
||||||
|
if (val->aliases) {
|
||||||
|
for (alias = val->aliases; *alias; alias++) {
|
||||||
|
g_string_append_c(names, '/');
|
||||||
|
g_string_append(names, *alias);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
g_ptr_array_add(valid_values, g_strdup_printf("%s (%s)", names->str, val->value_str));
|
||||||
|
}
|
||||||
|
|
||||||
|
g_string_free(names, TRUE);
|
||||||
|
g_array_unref(values);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
append_enum_valid_values(const NMMetaPropertyInfo *prop_info, GPtrArray *valid_values)
|
||||||
|
{
|
||||||
|
const NMMetaPropertyTypData *prop_typ_data = prop_info->property_typ_data;
|
||||||
|
const NMUtilsEnumValueInfo *value_infos;
|
||||||
|
GType gtype;
|
||||||
|
int min;
|
||||||
|
int max;
|
||||||
|
|
||||||
|
gtype = nm_meta_property_enum_get_type(prop_info);
|
||||||
|
nm_meta_property_enum_get_range(prop_info, &min, &max);
|
||||||
|
value_infos = prop_typ_data ? prop_typ_data->subtype.gobject_enum.value_infos : NULL;
|
||||||
|
|
||||||
|
_append_enum_valid_values(gtype, min, max, value_infos, valid_values);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
append_ethtool_valid_values(const NMMetaPropertyInfo *prop_info, GPtrArray *valid_values)
|
||||||
|
{
|
||||||
|
NMEthtoolID ethtool_id;
|
||||||
|
|
||||||
|
prop_assert(prop_info->property_typ_data, prop_info, "missing .property_typ_data");
|
||||||
|
|
||||||
|
ethtool_id = prop_info->property_typ_data->subtype.ethtool.ethtool_id;
|
||||||
|
|
||||||
|
if (nm_ethtool_id_is_coalesce(ethtool_id) || nm_ethtool_id_is_ring(ethtool_id))
|
||||||
|
g_ptr_array_add(valid_values, g_strdup_printf("0 - %u", G_MAXUINT32));
|
||||||
|
else if (nm_ethtool_id_is_feature(ethtool_id) || nm_ethtool_id_is_pause(ethtool_id))
|
||||||
|
append_vals(valid_values, "on", "off", "ignore");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
append_dcb_valid_values(const NMMetaPropertyInfo *prop_info, GPtrArray *valid_values)
|
||||||
|
{
|
||||||
|
guint max;
|
||||||
|
guint other;
|
||||||
|
|
||||||
|
prop_assert(prop_info->property_typ_data, prop_info, "missing .property_typ_data");
|
||||||
|
|
||||||
|
max = prop_info->property_typ_data->subtype.dcb.max;
|
||||||
|
other = prop_info->property_typ_data->subtype.dcb.other;
|
||||||
|
|
||||||
|
if (max != 0)
|
||||||
|
g_ptr_array_add(valid_values, g_strdup_printf("0 - %u", max));
|
||||||
|
if (other != 0 && (!max || other > max))
|
||||||
|
g_ptr_array_add(valid_values, g_strdup_printf("%u", other));
|
||||||
|
}
|
||||||
|
|
||||||
|
static GPtrArray *
|
||||||
|
get_property_valid_values(const NMMetaPropertyInfo *prop_info)
|
||||||
|
{
|
||||||
|
const NMMetaPropertyType *prop_type = prop_info->property_type;
|
||||||
|
const NMMetaPropertyTypData *prop_typ_data = prop_info->property_typ_data;
|
||||||
|
NMMetaPropertyTypeFormat fmt = prop_type->doc_format;
|
||||||
|
GPtrArray *valid_values = g_ptr_array_new_full(16, g_free);
|
||||||
|
|
||||||
|
/* connection.type is generated differently */
|
||||||
|
if (prop_info->setting_info->general->meta_type == NM_META_SETTING_TYPE_CONNECTION
|
||||||
|
&& !nm_strcmp0(prop_info->property_name, "type")) {
|
||||||
|
append_connection_types(valid_values);
|
||||||
|
return valid_values;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If it's a list, get the format of the items, but only if we can process it
|
||||||
|
* (prop_typ_data->subtype is of type multilist, so we can't process ints or enums) */
|
||||||
|
if (fmt == NM_META_PROPERTY_TYPE_FORMAT_MULTILIST && prop_typ_data) {
|
||||||
|
switch (prop_typ_data->list_items_doc_format) {
|
||||||
|
case NM_META_PROPERTY_TYPE_FORMAT_SECRET_FLAGS:
|
||||||
|
case NM_META_PROPERTY_TYPE_FORMAT_DCB_FLAGS:
|
||||||
|
case NM_META_PROPERTY_TYPE_FORMAT_BOOL:
|
||||||
|
case NM_META_PROPERTY_TYPE_FORMAT_DCB_BOOL:
|
||||||
|
case NM_META_PROPERTY_TYPE_FORMAT_TERNARY:
|
||||||
|
case NM_META_PROPERTY_TYPE_FORMAT_ETHTOOL:
|
||||||
|
fmt = prop_typ_data->list_items_doc_format;
|
||||||
|
break;
|
||||||
|
case NM_META_PROPERTY_TYPE_FORMAT_ENUM:
|
||||||
|
prop_warn(prop_info, "unknown enum type, can't get valid values");
|
||||||
|
break;
|
||||||
|
case NM_META_PROPERTY_TYPE_FORMAT_INT:
|
||||||
|
prop_warn(prop_info, "can't check for valid range in multilists");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* Other types probably don't need to show "Valid values" */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (fmt) {
|
||||||
|
case NM_META_PROPERTY_TYPE_FORMAT_INT:
|
||||||
|
append_int_valid_range(prop_info, valid_values);
|
||||||
|
break;
|
||||||
|
case NM_META_PROPERTY_TYPE_FORMAT_ENUM:
|
||||||
|
append_enum_valid_values(prop_info, valid_values);
|
||||||
|
break;
|
||||||
|
case NM_META_PROPERTY_TYPE_FORMAT_SECRET_FLAGS:
|
||||||
|
_append_enum_valid_values(NM_TYPE_SETTING_SECRET_FLAGS, 0, G_MAXUINT, NULL, valid_values);
|
||||||
|
break;
|
||||||
|
case NM_META_PROPERTY_TYPE_FORMAT_DCB_FLAGS:
|
||||||
|
_append_enum_valid_values(NM_TYPE_SETTING_DCB_FLAGS, 0, G_MAXUINT, NULL, valid_values);
|
||||||
|
break;
|
||||||
|
case NM_META_PROPERTY_TYPE_FORMAT_BOOL:
|
||||||
|
case NM_META_PROPERTY_TYPE_FORMAT_DCB_BOOL:
|
||||||
|
append_vals(valid_values, "true/yes/on", "false/no/off");
|
||||||
|
break;
|
||||||
|
case NM_META_PROPERTY_TYPE_FORMAT_TERNARY:
|
||||||
|
append_vals(valid_values, "true/yes/on", "false/no/off", "default/unknown");
|
||||||
|
break;
|
||||||
|
case NM_META_PROPERTY_TYPE_FORMAT_ETHTOOL:
|
||||||
|
append_ethtool_valid_values(prop_info, valid_values);
|
||||||
|
break;
|
||||||
|
case NM_META_PROPERTY_TYPE_FORMAT_DCB:
|
||||||
|
append_dcb_valid_values(prop_info, valid_values);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prop_typ_data && prop_typ_data->values_static) {
|
||||||
|
const char *const *v;
|
||||||
|
for (v = prop_typ_data->values_static; *v; v++)
|
||||||
|
g_ptr_array_add(valid_values, g_strdup(*v));
|
||||||
|
}
|
||||||
|
|
||||||
|
return valid_values;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char *argv[])
|
main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
@@ -246,11 +424,13 @@ main(int argc, char *argv[])
|
|||||||
g_print(" >\n");
|
g_print(" >\n");
|
||||||
|
|
||||||
for (i_property = 0; i_property < sett_info->properties_num; i_property++) {
|
for (i_property = 0; i_property < sett_info->properties_num; i_property++) {
|
||||||
const NMMetaPropertyInfo *prop_info = sett_info->properties[i_property];
|
const NMMetaPropertyInfo *prop_info = sett_info->properties[i_property];
|
||||||
gs_free char *name = NULL;
|
gs_free char *name = NULL;
|
||||||
gs_free char *alias = NULL;
|
gs_free char *alias = NULL;
|
||||||
gs_free char *descr = NULL;
|
gs_free char *descr = NULL;
|
||||||
gs_free char *fmt = NULL;
|
gs_free char *fmt = NULL;
|
||||||
|
gs_unref_ptrarray GPtrArray *vals_arr = NULL;
|
||||||
|
gs_free char *vals_str = NULL;
|
||||||
|
|
||||||
g_print("%s<property", _indent_level(2 * INDENT));
|
g_print("%s<property", _indent_level(2 * INDENT));
|
||||||
g_print(" name=%s", name = _xml_escape_attribute(prop_info->property_name));
|
g_print(" name=%s", name = _xml_escape_attribute(prop_info->property_name));
|
||||||
@@ -281,6 +461,15 @@ main(int argc, char *argv[])
|
|||||||
_indent_level(2 * INDENT + 10),
|
_indent_level(2 * INDENT + 10),
|
||||||
_xml_escape_attribute(fmt));
|
_xml_escape_attribute(fmt));
|
||||||
|
|
||||||
|
vals_arr = get_property_valid_values(prop_info);
|
||||||
|
if (vals_arr->len) {
|
||||||
|
g_ptr_array_add(vals_arr, NULL);
|
||||||
|
vals_str = g_strjoinv(", ", (char **) vals_arr->pdata);
|
||||||
|
g_print("\n%svalues=%s",
|
||||||
|
_indent_level(2 * INDENT + 10),
|
||||||
|
_xml_escape_attribute(vals_str));
|
||||||
|
}
|
||||||
|
|
||||||
g_print(" />\n");
|
g_print(" />\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -296,6 +296,7 @@ for setting_name in iter_keys_of_dicts(settings_roots, key_fcn_setting_name):
|
|||||||
else:
|
else:
|
||||||
node_set_attr(property_node, "type", properties_attrs)
|
node_set_attr(property_node, "type", properties_attrs)
|
||||||
|
|
||||||
|
node_set_attr(property_node, "values", properties_attrs)
|
||||||
node_set_attr(property_node, "default", properties_attrs)
|
node_set_attr(property_node, "default", properties_attrs)
|
||||||
node_set_attr(property_node, "alias", properties_attrs)
|
node_set_attr(property_node, "alias", properties_attrs)
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user