There's a hierarchy of classes describing different properties of some object. The abstract class Property
is a base class, and it has children: IntegerProperty
, BooleanProperty
, and so on. All data is encoded in QString
and derived classes decode it in their own way.
class Property : public QObject
{
Q_OBJECT
public:
// ...
virtual QString value() const = 0;
virtual bool setValue(const QString &value) = 0;
virtual bool validateValue(const QString& value) = 0;
// ...
};
class IntegerProperty : public Property
{
// ...
virtual QString value() const override;
virtual bool setValue(const QString &value) override;
virtual bool validateValue(const QString& value) override;
// ...
};
// ...
Every property class must have an independent editor (GUI widget) - PropertyEditor
(abstract class again), IntegerPropertyEditor
, BooleanPropertyEditor
, and so on.
class PropertyEditor : public QWidget
{
Q_OBJECT
public:
inline Facer::PropertyPointer attachedProperty() { return m_property; }
protected:
PropertyEditor(Facer::PropertyPointer attachedProperty, QWidget* parent = nullptr);
virtual void mousePressEvent(QMouseEvent* event) override;
virtual bool eventFilter(QObject *watched, QEvent *event) override;
// ...
};
class IntegerPropertyEditor : public PropertyEditor
{
// ...
};
// ...
For example, I have a set of different properties. I don't know which exactly properties I have because they are all pointers to Property
class. My task is to create specified editors of these properties, so I need to get IntegerPropertyEditor
if the property object is IntegerProperty
.
for (Property* property : propertySet())
PropertyEditor* editor = createEditor(property);
I made a temporary workaround with macro:
#define IF_TYPE_GET_EDITOR(propertyType, editorType) \
if (std::dynamic_pointer_cast<propertyType>(property)) \
return new editorType(property, this);
// ...
PropertyEditor *PropertySetWidget::create(PropertyPointer property)
{
IF_TYPE_GET_EDITOR(BooleanProperty, BooleanPropertyEditor)
else IF_TYPE_GET_EDITOR(ColorProperty, ColorPropertyEditor)
else IF_TYPE_GET_EDITOR(FloatingPointProperty, FloatingPointPropertyEditor)
else IF_TYPE_GET_EDITOR(FontProperty, FontPropertyEditor)
else IF_TYPE_GET_EDITOR(IntegerProperty, IntegerPropertyEditor)
else IF_TYPE_GET_EDITOR(TextProperty, TextPropertyEditor)
else throw std::runtime_error("This PropertyType is not implemented yet");
}
It doesn't look like a good solution - if I add a new type of property and its editor, I'll have to update this code as well. What is the most convenient and generic way to link an editor class and a property class?
Aucun commentaire:
Enregistrer un commentaire