0

I'm open to all opinions on the best way to do this, including "something else completely".

I'm trying to create objects to be displayed in QT5 with a base class containing many shared properties and virtual functions. These are graphics objects linked together by the user- I'd like them to function more or less like a linked list during evaluation, containing weak pointers to their neighbors.

QT wasn't able to resolve a std::variant containing pointers to the child objects, and I'm not sure if it's possible to do true polymorphism the way I envisioned it on QGraphicsObjects, since QVariant doesn't take user defined classes.

There's an excellent post here which is semi-related, but not quite how I'd like to handle UI/drawing, C++: How to get decoupled polymorphic behavior I want to keep the information in the QGraphicsObjects, then once the entry is all done, transfer to stl code that does the processing.

I'm also trying to make a distinction between clicks on the object and connector handles on the object, which I intended to use virtual mouseevent functions for.

The problem I have even with doing visitors or even dynamic_cast is with the required functions for QT, like boundingRect();

I've tried declaring it virtual, as below, and I'm still getting "undefined reference"

class BaseObject : public QGraphicsObject
{
    Q_OBJECT

public:
    //QT requirements
    virtual QRectF boundingRect();
    virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *item, QWidget *widget);
    //Input tracking
    void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
    void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override;
    void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override;
public slots:
    virtual void flip();
    virtual void rotate();
    virtual bool checkConstrained();
protected:
    //Constructed only by inherited items
    BaseObject(QPoint* base);
    virtual ~BaseObject(){}

    //Shared properties
    QString name;
    bool constrained;
//etc...
};

Here's one of the classes inheriting it:

class ChildObject : public BaseObject
{
     Q_OBJECT
public:
    ChildObject(QPoint* base, QPointer<BaseObject> linkInit1 = nullptr, QPointer<BaseObject> linkInit2 = nullptr, QPointer<BaseObject> linkInit3 = nullptr);
    QRectF boundingRect() const override;
    bool checkConstrained();
    void flip();
    void rotate();
    void paint(QPainter *painter, const QStyleOptionGraphicsItem *item, QWidget *widget);

Is there a more sensible way to do this? So far I've also thought of letting the "connection handle" objects own pointers to other handles, but that just breaks OOP and you still end up needing code that asks "Which type of object am I owned by?", in addition to "which one of its handles am I?"

MGreene
  • 21
  • 6
  • 1
    "since QVariant doesn't take user defined classes" -> see [`QMetaType`'s documentation](http://doc.qt.io/qt-5/qmetatype.html). User defined classes are not an issue with `QVariant`. `qRegisterMetaType<>()` and `Q_DECLARE_METATYPE()` are what you're looking for. – jonspaceharper Apr 03 '18 at 19:07
  • Also, don't use `dynamic_cast` with `QObject`-derived objects. Use `qobject_cast` instead. – jonspaceharper Apr 03 '18 at 19:08
  • Thank you for the direction, but I must be understanding the documentation incorrectly. It says that classes derived from Q_OBJECT don't have copy constructors (or, more accurately, are copy disabled). The requirements for using those metatype functions say "as long as it provides a public default constructor, a public copy constructor and a public destructor." How do I define these without explicitly defining a public copy constructor? – MGreene Apr 06 '18 at 14:49
  • `QVariant` allows you to use pointers to `QObject`s and derived classes by registering them. No need for a copy constructor. – jonspaceharper Apr 07 '18 at 08:31
  • Am I correct that I have to both declare them as pointer types and register them as pointer types, and not declare/register them in any other way? This doesn't seem to be working and the errors I'm encountering are extremely unclear. Usually I can at least work out what a compiler warning is getting at but I don't have a clue with some of these. – MGreene Apr 10 '18 at 23:03

2 Answers2

0

Maybe you may consider grouping shared properties in another class SharedProperties and inherit from this new class.

class BaseObject : public QGraphicsObject, public SharedProperties

... and I'm not sure if it's possible to do true polymorphism the way I envisioned it on QGraphicsObjects, since QVariant doesn't take user defined classes.

User defined classes can be used with QVariant. Please take a look at Qt Documentation and How to verify QVariant of type QVariant::UserType is expected type?

zapprox
  • 61
  • 3
  • Sorry, I worded that poorly. I should have said "I don't know how to get QVariant to resolve user-defined classes inheriting from Q_Object." I.E., Classes with no public copy constructor (Q_Object) don't meet the requirements for a metatype. – MGreene Apr 06 '18 at 14:57
0

Your override in ChildObject is const

QRectF boundingRect() const override;

while the virtual in BaseObject is not

virtual QRectF boundingRect();

Could this be the issue? I don't see anything obvious wrong with your design. Cameron

Fryz
  • 2,119
  • 2
  • 25
  • 45