fix some on properties and signal connection

This commit is contained in:
AndreaRigoni
2026-03-26 09:50:52 +00:00
parent 2c5d6842c3
commit e0ffeff5b7
22 changed files with 578 additions and 62 deletions

View File

@@ -88,6 +88,16 @@ const std::vector<PropertyBase*>& Object::GetProperties() const {
return d->m_Properties;
}
PropertyBase* Object::GetProperty(const std::string& name) const {
for (auto* p : d->m_Properties) {
if (p->GetName() == name) return p;
}
for (auto* p : d->m_DynamicProperties) {
if (p->GetName() == name) return p;
}
return nullptr;
}
// In Object.h, the template serialize needs to be updated to call property serialization.
// However, since Object::serialize is a template in the header, we might need a helper here.

View File

@@ -93,6 +93,7 @@ public:
void RegisterProperty(PropertyBase* prop);
void RegisterDynamicProperty(PropertyBase* prop);
const std::vector<PropertyBase*>& GetProperties() const;
PropertyBase* GetProperty(const std::string& name) const;
////////////////////////////////////////////////////////////////////////////
// PARAMETERS //

View File

@@ -23,6 +23,12 @@ public:
virtual const char* GetTypeName() const = 0;
virtual std::string GetValueAsString() const = 0;
virtual std::type_index GetTypeIndex() const = 0; // Added
virtual const std::string& GetUnits() const = 0;
virtual void SetUnits(const std::string& units) = 0;
virtual const std::vector<std::string>& GetEnumLabels() const {
static std::vector<std::string> empty;
return empty;
}
// Signal support
signals:
@@ -45,16 +51,16 @@ template <typename T>
class Property : public PropertyBase {
public:
// PROXY: Use an existing variable as back-end storage
Property(Object* owner, const std::string& name, T* valuePtr)
: m_owner(owner), m_name(name), m_value(valuePtr), m_own(false) {
Property(Object* owner, const std::string& name, T* valuePtr, const std::string& units = "")
: m_owner(owner), m_name(name), m_units(units), m_value(valuePtr), m_own(false) {
if (m_owner) {
m_owner->RegisterProperty(this);
}
}
// MANAGED: Create and own internal storage
Property(Object* owner, const std::string& name, const T& defaultValue = T())
: m_owner(owner), m_name(name), m_value(new T(defaultValue)), m_own(true) {
Property(Object* owner, const std::string& name, const T& defaultValue = T(), const std::string& units = "")
: m_owner(owner), m_name(name), m_units(units), m_value(new T(defaultValue)), m_own(true) {
if (m_owner) {
m_owner->RegisterProperty(this);
}
@@ -68,6 +74,8 @@ public:
virtual const std::string& GetName() const override { return m_name; }
virtual const char* GetTypeName() const override { return typeid(T).name(); }
virtual std::type_index GetTypeIndex() const override { return std::type_index(typeid(T)); }
virtual const std::string& GetUnits() const override { return m_units; }
virtual void SetUnits(const std::string& units) override { m_units = units; }
std::string GetValueAsString() const override {
@@ -118,6 +126,7 @@ public:
private:
std::string m_name;
std::string m_units;
T* m_value;
bool m_own;
Object* m_owner;
@@ -135,6 +144,22 @@ typedef Property<float> FloatProperty;
typedef Property<double> DoubleProperty;
typedef Property<Bool_t> BoolProperty;
/**
* @brief Property specialized for enumerations, providing labels for GUI representations.
*/
class EnumProperty : public Property<int> {
public:
EnumProperty(Object* owner, const std::string& name, int* valuePtr, const std::vector<std::string>& labels, const std::string& units = "")
: Property<int>(owner, name, valuePtr, units), m_Labels(labels) {}
const std::vector<std::string>& GetEnumLabels() const override { return m_Labels; }
const char* GetTypeName() const override { return "Enum"; }
virtual std::type_index GetTypeIndex() const override { return std::type_index(typeid(EnumProperty)); }
private:
std::vector<std::string> m_Labels;
};
/**
* @brief Macro to simplify property declaration within a class.
* Usage: ULIB_PROPERTY(float, Width, 1.0f)
@@ -188,10 +213,16 @@ public:
template<class T>
void save_override(const boost::serialization::hrp<T> &t) {
if (m_Object) {
// We use const_cast because we are just creating a proxy to the member
m_Object->RegisterDynamicProperty(
new Property<T>(m_Object, t.name(), &const_cast<boost::serialization::hrp<T>&>(t).value())
);
Property<T>* p = new Property<T>(m_Object, t.name(), &const_cast<boost::serialization::hrp<T>&>(t).value(), t.units() ? t.units() : "");
m_Object->RegisterDynamicProperty(p);
}
}
template<class T>
void save_override(const boost::serialization::hrp_enum<T> &t) {
if (m_Object) {
EnumProperty* p = new EnumProperty(m_Object, t.name(), (int*)&const_cast<boost::serialization::hrp_enum<T>&>(t).value(), t.labels(), t.units() ? t.units() : "");
m_Object->RegisterDynamicProperty(p);
}
}

View File

@@ -75,12 +75,14 @@ template <class T> struct access2 {};
template <class T>
class hrp : public boost::serialization::wrapper_traits<hrp<T>> {
const char *m_name;
const char *m_units;
T &m_value;
public:
explicit hrp(const char *name_, T &t) : m_name(name_), m_value(t) {}
explicit hrp(const char *name_, T &t, const char* units_ = nullptr) : m_name(name_), m_units(units_), m_value(t) {}
const char *name() const { return this->m_name; }
const char *units() const { return this->m_units; }
T &value() { return this->m_value; }
const T &const_value() const { return this->m_value; }
@@ -98,11 +100,46 @@ public:
};
template <class T>
inline hrp<T> make_hrp(const char *name, T &t) {
return hrp<T>(name, t);
inline hrp<T> make_hrp(const char *name, T &t, const char* units = nullptr) {
return hrp<T>(name, t, units);
}
template <class T>
class hrp_enum : public boost::serialization::wrapper_traits<hrp_enum<T>> {
const char *m_name;
const char *m_units;
T &m_value;
std::vector<std::string> m_labels;
public:
explicit hrp_enum(const char *name_, T &t, const std::vector<std::string>& labels, const char* units_ = nullptr)
: m_name(name_), m_units(units_), m_value(t), m_labels(labels) {}
const char *name() const { return this->m_name; }
const char *units() const { return this->m_units; }
T &value() { return this->m_value; }
const std::vector<std::string>& labels() const { return m_labels; }
BOOST_SERIALIZATION_SPLIT_MEMBER()
template <class Archivex>
void save(Archivex &ar, const unsigned int /* version */) const {
ar << boost::serialization::make_nvp(m_name, m_value);
}
template <class Archivex>
void load(Archivex &ar, const unsigned int /* version */) {
ar >> boost::serialization::make_nvp(m_name, m_value);
}
};
template <class T>
inline hrp_enum<T> make_hrp_enum(const char *name, T &t, const std::vector<std::string>& labels, const char* units = nullptr) {
return hrp_enum<T>(name, t, labels, units);
}
#define HRP(name) boost::serialization::make_hrp(BOOST_PP_STRINGIZE(name), name)
#define HRPU(name, units) boost::serialization::make_hrp(BOOST_PP_STRINGIZE(name), name, units)
} // namespace serialization
} // namespace boost