Discussion:
Interface with signals and slots
(too old to reply)
Jérôme Godbout
2018-11-30 20:37:53 UTC
Permalink
Hi,
I was wondering if it's even possible to do the following somehow. I'm trying to make an Interface with signals without inheriting the QObject and I have a hard time make this compile properly:

class IMyInterface
{
public:
explicit IMyInterface();
virtual ~IMyInterface();

bool val() const;
void setVal(const bool v);

signals:
virtual void valChanged() = 0;

protected:
bool m_val;
};

Q_DECLARE_INTERFACE(IMyInterface, "IMyInterface")

class MyClass : public QObject, public IMyInterface
{
Q_OBJECT
Q_PROPERTY(bool val READ val WRITE setVal NOTIFY valChanged)
Q_INTERFACES(IMyInterface)

public:
...

signals:
virtual void valChanged() override;
};

Q_DECLARE_METATYPE(MyClass*)

The example is simplified to show my problem, the different class will inherit different QObject type so I cannot inherit 2 different QObject type. It does compile but this fail at link with the moc:

moc_MyClass.obj:moc_MyClass.cpp:vtable for MyClass: error: undefined reference to 'MyClass::dirtyChanged()'
moc_MyClass.obj:moc_MyClass.cpp:vtable for MyClass: error: undefined reference to 'non-virtual thunk to MyClass::valChanged()'
module_demo.obj:module_demo.cpp:vtable for QQmlPrivate::QQmlElement<MyClass>: error: undefined reference to 'MyClass::valChanged()'
module_demo.obj:module_demo.cpp:vtable for QQmlPrivate::QQmlElement<MyClass>: error: undefined reference to 'non-virtual thunk to MyClass::valChanged()'

Is there a way to use the signals/slots into an interface to be declared? That would greatly help me do reusable code part.


[36E56279]
une compagnie [cid:***@01D488C2.A8924C20]
RAPPROCHEZ LA DISTANCE

Jérôme Godbout
Développeur Logiciel Sénior /
Senior Software Developer

p: +1 (418) 800-1073 ext.:109

amotus.ca<http://www.amotus-solutions.com/>
statum-iot.com<http://statum-iot.com/>
[cid:***@01D488C2.A8924C20]<https://www.facebook.com/LesSolutionsAmotus/> [cid:***@01D488C2.A8924C20] <https://www.linkedin.com/company/amotus-solutions/> [cid:***@01D488C2.A8924C20] <https://twitter.com/AmotusSolutions> [cid:***@01D488C2.A8924C20] <https://www.youtube.com/channel/UCoYpQgsmj1iJZyDjTQ3x8Ig>
Konstantin Shegunov
2018-11-30 21:28:57 UTC
Permalink
Hi,
This compiles for me:

class SignalInterface

{

public:

virtual void mysignal() = 0;

};


class SignalImplementer : public QObject, public SignalInterface

{

Q_OBJECT


signals:

void mysignal() override;

};


However putting signals into an interface I think is rather dubious,
because you won't be able to connect through the interface. I.e. this:

SignalImplementer obj;

QObject::connect(this, &Session::opened, &obj, &SignalInterface::mysignal);


Is going to fail the static assertions in QObject::connect.
You could derive from QObject though and have them in an abstract class.
Jérôme Godbout
2018-11-30 21:44:17 UTC
Permalink
For me, under Android target, it does fail for the linking. I was trying to add and interface for injecting property into object expose to Qml. I often want to add a subset of property to a model and I would have want to have to rewrite the same Q_PROPERTY() and changed signal over and over again.

But I guess I will stick with the ugly macro mess for now.

Would be nice to have a way to extend a QObject with defined class of property with get/set and changed signals that is not a QObject to avoid diamond inheritance since it could already inherit another QObject class.

For example I would have love to have interface for the dirty property so I could inject the property on many qobjects types I have without rewriting it every time. I can make the get/set/ protected value, but I still have to create the signals/slots/Q_PROPERTY every time. I use some macro but I find that ugly and error prone to forget one.


From: Konstantin Shegunov <***@gmail.com>
Sent: November 30, 2018 4:29 PM
To: JérÎme Godbout <***@amotus.ca>
Cc: Interests Qt <***@qt-project.org>
Subject: Re: [Interest] Interface with signals and slots

Hi,
This compiles for me:

class SignalInterface

{

public:

virtual void mysignal() = 0;

};



class SignalImplementer : public QObject, public SignalInterface

{

Q_OBJECT



signals:

void mysignal() override;

};

However putting signals into an interface I think is rather dubious, because you won't be able to connect through the interface. I.e. this:

SignalImplementer obj;

QObject::connect(this, &Session::opened, &obj, &SignalInterface::mysignal);


Is going to fail the static assertions in QObject::connect.
You could derive from QObject though and have them in an abstract class.
Konstantin Shegunov
2018-11-30 21:47:12 UTC
Permalink
Post by Jérôme Godbout
For me, under Android target, it does fail for the linking.
Links fine for me (g++8).
Post by Jérôme Godbout
I was trying to add and interface for injecting property into object
expose to Qml. I often want to add a subset of property to a model and I
would have want to have to rewrite the same Q_PROPERTY() and changed signal
over and over again.
Would be nice to have a way to extend a QObject with defined class of
property with get/set and changed signals that is not a QObject to avoid
diamond inheritance since it could already inherit another QObject class.
Q_GADGET supports properties. Maybe you can use that?
Continue reading on narkive:
Loading...