Skip to content
This repository was archived by the owner on Jun 8, 2021. It is now read-only.

Commit 7cb6ad1

Browse files
authored
Merge pull request #457 from sdroege/set-property-and-signal-return-type-relaxation
For setting properties and the return value of signal handlers relax …
2 parents d6a3b03 + a44b0b0 commit 7cb6ad1

File tree

2 files changed

+39
-6
lines changed

2 files changed

+39
-6
lines changed

src/object.rs

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -947,7 +947,7 @@ impl<T: ObjectType> ObjectExt for T {
947947

948948
fn set_property<'a, N: Into<&'a str>>(&self, property_name: N, value: &ToValue) -> Result<(), BoolError> {
949949
let property_name = property_name.into();
950-
let property_value = value.to_value();
950+
let mut property_value = value.to_value();
951951

952952
let pspec = match self.find_property(property_name) {
953953
Some(pspec) => pspec,
@@ -968,12 +968,28 @@ impl<T: ObjectType> ObjectExt for T {
968968
let valid_type: bool = from_glib(gobject_ffi::g_type_check_value_holds(
969969
mut_override(property_value.to_glib_none().0),
970970
pspec.get_value_type().to_glib()));
971-
if !valid_type {
971+
972+
// If it's not directly a valid type but an object type, we check if the
973+
// actual type of the contained object is compatible and if so create
974+
// a properly type Value. This can happen if the type field in the
975+
// Value is set to a more generic type than the contained value
976+
if !valid_type && property_value.type_().is_a(&Object::static_type()) {
977+
if let Some(obj) = property_value.get::<Object>() {
978+
if obj.get_type().is_a(&pspec.get_value_type()) {
979+
property_value.0.g_type = pspec.get_value_type().to_glib();
980+
} else {
981+
return Err(glib_bool_error!("property can't be set from the given object type"));
982+
}
983+
} else {
984+
// Otherwise if the value is None then the type is compatible too
985+
property_value.0.g_type = pspec.get_value_type().to_glib();
986+
}
987+
} else if !valid_type {
972988
return Err(glib_bool_error!("property can't be set from the given type"));
973989
}
974990

975991
let changed: bool = from_glib(gobject_ffi::g_param_value_validate(
976-
pspec.to_glib_none().0, mut_override(property_value.to_glib_none().0)));
992+
pspec.to_glib_none().0, property_value.to_glib_none_mut().0));
977993
let change_allowed = pspec.get_flags().contains(::ParamFlags::LAX_VALIDATION);
978994
if changed && !change_allowed {
979995
return Err(glib_bool_error!(
@@ -1139,11 +1155,28 @@ impl<T: ObjectType> ObjectExt for T {
11391155
None
11401156
} else {
11411157
match ret {
1142-
Some(ret) => {
1158+
Some(mut ret) => {
11431159
let valid_type: bool = from_glib(gobject_ffi::g_type_check_value_holds(
11441160
mut_override(ret.to_glib_none().0),
11451161
return_type.to_glib()));
1146-
if !valid_type {
1162+
1163+
// If it's not directly a valid type but an object type, we check if the
1164+
// actual typed of the contained object is compatible and if so create
1165+
// a properly typed Value. This can happen if the type field in the
1166+
// Value is set to a more generic type than the contained value
1167+
if !valid_type && ret.type_().is_a(&Object::static_type()) {
1168+
if let Some(obj) = ret.get::<Object>() {
1169+
if obj.get_type().is_a(&return_type) {
1170+
ret.0.g_type = return_type.to_glib();
1171+
} else {
1172+
panic!("Signal required return value of type {} but got {} (actual {})",
1173+
return_type.name(), ret.type_().name(), obj.get_type().name());
1174+
}
1175+
} else {
1176+
// Otherwise if the value is None then the type is compatible too
1177+
ret.0.g_type = return_type.to_glib();
1178+
}
1179+
} else if !valid_type {
11471180
panic!("Signal required return value of type {} but got {}",
11481181
return_type.name(), ret.type_().name());
11491182
}

src/value.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ use gobject_ffi;
103103
/// See the [module documentation](index.html) for more details.
104104
// TODO: Should use impl !Send for Value {} once stable
105105
#[repr(C)]
106-
pub struct Value(gobject_ffi::GValue, PhantomData<*const c_void>);
106+
pub struct Value(pub(crate) gobject_ffi::GValue, PhantomData<*const c_void>);
107107

108108
impl Value {
109109
/// Creates a new `Value` that is initialized with `type_`

0 commit comments

Comments
 (0)