Qt : cannot connect signals to slots of promoted QWidget [duplicate] - c++

The documentation states that:
The Q_OBJECT macro must appear in the
private section of a class definition
that declares its own signals and
slots or that uses other services
provided by Qt's meta-object system.
But exactly what does that mean? On which QObject-derived classes can I safely omit it? Will problems arise if you omit Q_OBJECT on a QObject-derived class, and then inherit from that one? Basically I would like a little more information on when I can omit it from my Qt classes.

You should use the Q_OBJECT macro for any non-templated classes that derive from QObject.
Besides signals and slots, the Q_OBJECT macro provides the meta object information that is associated with given class.
As stated in the documentation:
we strongly recommend that all subclasses of QObject use the Q_OBJECT macro regardless of whether or not they actually use signals, slots, and properties.
Suppose we have the following class:
class Class : public QObject {
public:
Class() {}
};
Without Q_OBJECT, the following metaobject system features (among others) will not work for Class:
qobject_cast<Class>() - due to missing metadata
QObject::tr() - due to missing metadata
slots and invokables first declared in Class, when invoked or looked up by name - none of QMetaObject methods will work for these methods, neither will the Qt 4 connect - due to missing metadata
signals - since moc won't generate their implementations and the code won't compile.
You can omit it, of course, but if you ever use these features, you'll need to remember to put the macro into the class's declaration. This is a rather brittle practice and best avoided. The savings are not worth it. So, don't wait - add the Q_OBJECT macro to every class that derives from QObject as a matter of coding policy.
The Q_OBJECT macro should never be used on classes that don't derive from QObject. To add invokables and properties to such classes, use the Q_GADGET macro instead.

If you want to use signals/slots you MUST include the Q_OBJECT macro and derive the class from QObject.
Otherwise you can leave it out, but it doesn't do any harm to include it in all the Qt gui classes

Well the first part is pretty clear as you probably already know.. signals and slots, the rest of the Meta-object system is a little lesser known. Perhaps one of the more useful features is dynamic properties. Although these have many uses, I used them to take advantage of Qt's animation system QPropertyAnimation.
There's a little more info about the meta-object system here: http://doc.qt.io/archives/4.6/metaobjects.html
I think the bottom line is, if you inherit from the QObject hierarchy, throw in the Q_OBJECT macro regardless. It's simple to do and will save you from some potentially baffling problems down the road.

What #liaK said is correct (in short: you should always use the Q_OBJECT macro in any class that derives from QObject).
One thing that I haven't seen highlighted is that if you don't explicitly put the Q_OBJECT macro then using the sometimes very handy qobject_cast won't work!!!

Related

Where do the arguments passed to slots come from? [duplicate]

Is there a way to use any C++ function as a Qt slot, without having its class inheriting from QWidget?
You cannot in Qt versions < Qt 5.
In order to use signals/slots the meta object compiler has to be invoked. To make this happen your class should meet the following requirements:
Inherit from QObject or any other subclass (eg QWidget, QPushButton etc)
The Q_OBJECT macro should be defined in the private section of the class in order to enable meta-object features such as slots
Use the Qt keywords slots and signals in order to declare which functions should be handles by the meta compiler as slots or signals
For more details check the corresponding documentation pages about the meta-object system and the signals & slots
Also check the QObject documentation:
Notice that the Q_OBJECT macro is mandatory for any object that implements signals, slots or properties. You also need to run the
Meta Object Compiler on the source file. We strongly recommend the use
of this macro in all subclasses of QObject regardless of whether or
not they actually use signals, slots and properties, since failure to
do so may lead certain functions to exhibit strange behavior.
Edit: Since Qt 5, functors and lambda expressions can be used as slot. See New Signal Slot Syntax in Qt 5
Since Qt 5, functors and lambda expressions can be used as slot (as previously mentioned, here: http://qt-project.org/wiki/New_Signal_Slot_Syntax).
As I could not find example code, I added the following:
This example uses boost::function for a class member ClassName::classMember() without parameters.
boost::function<void()> f= boost::bind(&ClassName::classMember, classInstance);
connect(QObjectInstance, &QObject::signalName, f);
When the Qt signal and class member have parameters (for instance ClassName::classMember(int)), the boost function should be adapted as follows:
boost::function<void(int)> f= boost::bind(&ClassName::classMember, classInstance, _1);
More information on boost::bind can be found in the documentation: http://www.boost.org/doc/libs/1_55_0/libs/bind/bind.html
In Qt 5, you can. See http://qt-project.org/wiki/New_Signal_Slot_Syntax
In Qt 4, this is not directly supported but there are a couple of libraries which provide this functionality by proxying the signal via a slot in a hidden QObject which then calls your non-slot function. My attempt at this can be found at https://github.com/robertknight/qt-signal-tools . There are links to other implementations on the bottom of the README.
Unlikely. The Qt-meta-object-compiler (moc) wraps the function, are marked as slot-s, in relatively large code-wrapper. Files, created by moc, begin with moc_, look them.
It is enough to inherit QObject: http://qt-project.org/doc/qt-4.8/signalsandslots.html

Qt signals and slots: permissions

There are discrepancies between respected answers here on SO and the actual Qt docs.
I've read this question and I want some further clarification. Can anyone confirm:
A signal is always protected, therefore it can be emitted only by the class or any of its subclasses. I'm not sure this is true; the question above shows answers supporting this statement. But the Qt docs say: Signals are public access functions and can be emitted from anywhere, but we recommend to only emit them from the class that defines the signal and its subclasses. So which is it?
Slots are just functions, and thus may be public, private or protected. Obviously an outside class will have the ability to control if your class connects one of its own signals to one of its own slots if the slot is public. However, again the SO information differs from the docs, which say: a signal emitted from an instance of an arbitrary class can cause a private slot to be invoked in an instance of an unrelated class. This means that private is not honored by the signal/slot mechanism?
The words public, private, protected have no use with working with the signal keyword
The emitted signal is always available to all other classes, that is, any other class may always connect to that signal (regardless of its permission to emit the signal).
Despite that all signals are viewable to by all classes, you could still have two classes with signals of the same name since the connect function takes the class name as a signal prefix (i.e. SomeClass::itsSignal)
Signals are protected in Qt4 but are public in Qt5, thus the contradictory information.
Slots are functions and public/protected/private is honored when calling them as such, when connecting to a signal, the metaobject system ignores it though.
As signals is defined as public:, prepending them with e.g. private leads
to:
private:
public: //signals:
void theSignal();
Thus it's without effect.
All classes can be connected to any signal, correct. Signals are part of the public API in that regard.
Having identical signal signatures is not a problem. The context is defined by the object specified as sender.
Using old-style connect:
Apple *apple ... Orange* orange
connect(apple, SIGNAL(changed()), this, SLOT(appleChanged()));
connect(orange, SIGNAL(changed()), this, SLOT(orangeChanged()));
The signal is specified as string here (without the class name in it), but as apple and orange have only one signal changed() each and the lookup is done in the metaobject of the QObject instance, which exists one per class (not instance), they cannot collide.
Qt 5 version with compile-time checking:
connect(apple, &Apple::changed, this, &MyReceiver::appleChanged);
Here one must specify a function, so depending on the scope, one must specify a class name (and maybe namespaces). As an ambiguous function name wouldn't be valid C++ and thus not compile, so one is safe here.
Take a look at qobjectdefs.h (QT5.0+). In there are defined the moc macros
# define signals public
As you can see the macros used in header files for signals are defined as public. As for the explicit statet public,private,protected directives, these are ignored in the signals section. Prior 5.0 versions of QT have signals defined as protected. Those were still available for connections using the SIGNAL() macro.
The slots macro
# define slots
is defined as an empty macro and therefore can be used with:
public slots:
private slots:
protected slots:
The method visibility is used for direct method calls, so private/protected cannot be called from foreign classes directly.
Using the a connect statement still works independently from the visibility. This is the intended behaviour and is implemented in the moc-generated code.
If i remember correctly in earlier versions of Qt a slot was also public automatically, but i did not find a reference for that now.
Any other class can connect to a signal from a foreign class, as long the Q_OBJECT macro is given in the class and the foreign class is known (header included). Since signals are defined per-class it is perfectly legal to have the same signal in different classes. This is also pretty convenient, for example have a signal sendInfo(QString) in all classes makes it easier to remember. The Q_OBJECT macro makes the moc to create code needed to connect signals to slots independent to visibility.
The emitted signal is always available to all other classes, that is, any other class may always connect to that signal (regardless of its permission to emit the signal).
In Qt5, this isn't necessarily true. A signal can be defined with QPrivateSignal as its final argument, and in that case, only the object which declared the signal would be able to connect to it.

Using any c++ function as a Qt slot

Is there a way to use any C++ function as a Qt slot, without having its class inheriting from QWidget?
You cannot in Qt versions < Qt 5.
In order to use signals/slots the meta object compiler has to be invoked. To make this happen your class should meet the following requirements:
Inherit from QObject or any other subclass (eg QWidget, QPushButton etc)
The Q_OBJECT macro should be defined in the private section of the class in order to enable meta-object features such as slots
Use the Qt keywords slots and signals in order to declare which functions should be handles by the meta compiler as slots or signals
For more details check the corresponding documentation pages about the meta-object system and the signals & slots
Also check the QObject documentation:
Notice that the Q_OBJECT macro is mandatory for any object that implements signals, slots or properties. You also need to run the
Meta Object Compiler on the source file. We strongly recommend the use
of this macro in all subclasses of QObject regardless of whether or
not they actually use signals, slots and properties, since failure to
do so may lead certain functions to exhibit strange behavior.
Edit: Since Qt 5, functors and lambda expressions can be used as slot. See New Signal Slot Syntax in Qt 5
Since Qt 5, functors and lambda expressions can be used as slot (as previously mentioned, here: http://qt-project.org/wiki/New_Signal_Slot_Syntax).
As I could not find example code, I added the following:
This example uses boost::function for a class member ClassName::classMember() without parameters.
boost::function<void()> f= boost::bind(&ClassName::classMember, classInstance);
connect(QObjectInstance, &QObject::signalName, f);
When the Qt signal and class member have parameters (for instance ClassName::classMember(int)), the boost function should be adapted as follows:
boost::function<void(int)> f= boost::bind(&ClassName::classMember, classInstance, _1);
More information on boost::bind can be found in the documentation: http://www.boost.org/doc/libs/1_55_0/libs/bind/bind.html
In Qt 5, you can. See http://qt-project.org/wiki/New_Signal_Slot_Syntax
In Qt 4, this is not directly supported but there are a couple of libraries which provide this functionality by proxying the signal via a slot in a hidden QObject which then calls your non-slot function. My attempt at this can be found at https://github.com/robertknight/qt-signal-tools . There are links to other implementations on the bottom of the README.
Unlikely. The Qt-meta-object-compiler (moc) wraps the function, are marked as slot-s, in relatively large code-wrapper. Files, created by moc, begin with moc_, look them.
It is enough to inherit QObject: http://qt-project.org/doc/qt-4.8/signalsandslots.html

Features that require Q_OBJECT macro in Qt 4 other than signal - slots mechanism

I am using Qt 4.5 in windows XP. I know we have to use Q_OBJECT macro for signal - slot connection mechanism. But besides that, is there are any other reasons to use the Q_OBJECT macro? I recently come to know that for some other meta-object features we require the Q_OBJECT declaration. What are those features beside the Signal-slots? I tried for documentation regarding that but couldn't find anything helpful. Any pointers regarding this are welcome.
You can find all you need to know about when Q_OBJECT macro is needed here:
http://doc.qt.digia.com/4.6/metaobjects.html
In resume you need it for signals and slots, to use tr for translation, to retrieve class name in real time from a QObject, to know if it inherits from other class (instrospection) to set properties and to be able to call newInstance.
Hope it helps.
AFAIK its of use for retreiving meta information (Names of signal slots, vars)
and provides support for the ownership tracking of objects.
(aka. just do new and pass parents to these objects and they will be disposed deterministically as time of the parent passes by.)

Architecture for Qt SIGNAL with subclass-specific, templated argument type

I am developing a scientific data acquisition application using Qt. Since I'm not a deep expert in Qt, I'd like some architecture advise from the community on the following problem:
The application supports several hardware acquisition interfaces but I would like to provide an common API on top of those interfaces. Each interface has a sample data type and a units for its data. So I'm representing a vector of samples from each device as a std::vector of Boost.Units quantities (i.e. std::vector<boost::units::quantity<unit,sample_type> >). I'd like to use a multi-cast style architecture, where each data source broadcasts newly received data to 1 or more interested parties. Qt's Signal/Slot mechanism is an obvious fit for this style. So, I'd like each data source to emit a signal like
typedef std::vector<boost::units::quantity<unit,sample_type> > SampleVector
signals:
void samplesAcquired(SampleVector sampleVector);
for the unit and sample_type appropriate for that device. Since tempalted QObject subclasses aren't supported by the meta-object compiler, there doesn't seem to be a way to have a (tempalted) base class for all data sources which defines the samplesAcquired Signal. In other words, the following won't work:
template<T,U> //sample type and units
class DataSource : public QObject {
Q_OBJECT
...
public:
typedef std::vector<boost::units::quantity<U,T> > SampleVector
signals:
void samplesAcquired(SampleVector sampleVector);
};
The best option I've been able to come up with is a two-layered approach:
template<T,U> //sample type and units
class IAcquiredSamples {
public:
typedef std::vector<boost::units::quantity<U,T> > SampleVector
virtual shared_ptr<SampleVector> acquiredData(TimeStamp ts, unsigned long nsamples);
};
class DataSource : public QObject {
...
signals:
void samplesAcquired(TimeStamp ts, unsigned long nsamples);
};
The samplesAcquired signal now gives a timestamp and number of samples for the acquisition and clients must use the IAcquiredSamples API to retrieve those samples. Obviously data sources must subclass both DataSource and IAcquiredSamples.
The disadvantage of this approach appears to be a loss of simplicity in the API... it would be much nicer if clients could get the acquired samples in the Slot connected. Being able to use Qt's queued connections would also make threading issues easier instead of having to manage them in the acquiredData method within each subclass.
One other possibility, is to use a QVariant argument. This necessarily puts the onus on subclass to register their particular sample vector type with Q_REGISTER_METATYPE/qRegisterMetaType. Not really a big deal. Clients of the base class however, will have no way of knowing what type the QVariant value type is, unless a tag struct is also passed with the signal. I consider this solution at least as convoluted as the one above, as it forces clients of the abstract base class API to deal with some of the gnarlier aspects of type system.
So, is there a way to achieve the templated signal parameter? Is there a better architecture than the one I've proposed?
There is QVariant type -- you can create your custom sub-type on it
and use it as parameter (if I understand your right and that's what you want) in signals
http://doc.trolltech.com/qq/qq14-metatypes.html#customtypesinqvariant
One simplification to your two-layered approach would be to have the QObject class as a non-templated base for the class template i.e. something like
class DataSourceBase : public QObject {
Q_OBJECT
...
signals:
void samplesAcquired(TimeStamp ts, unsigned long nsamples);
};
template<T,U> //sample type and units
class DataSource : public DataSourceBase {
public:
typedef std::vector<boost::units::quantity<U,T> > SampleVector
virtual shared_ptr<SampleVector> acquiredData(TimeStamp ts, unsigned long nsamples);
};
Note that the drawback to this approach is that since you cannot use the Q_OBJECT macro in the class template there is no information about it in Qt's meta-object system.
Qt doesn't like class templates that inherit from QObject. If you don't need the runtime introspection of QObject, you might want to use Boost.Signals instead, which doesn't have this problem.
Introducing the Boost.Signals library in a Qt project can be a bit challenging, though. In Boost.Signals, signals is a namespace while Qt #defines signal to protected. You should make sure your Qt project compiles with QT_NO_KEYWORDS defined (CONFIG += no_keywords in qmake), before introducing Boost.Signals.
You actually can use Qt classes with Templates with little modifications to your code.
The issue with Qt classes and Templates is the moc tool that generates the meta object information, it has no knowledge on templates at all, but the generated code doesn't needs to come from Moc.
you can use Verdigris to create your C++/QObject class that will work with templates without any issues, bypassing the moc step for such code.