Signals and Slots - Passing Data - c++

Im trying to connect a signal to a slot and pass through a vector but im not having much luck.
res = QObject::connect(storePayments, SIGNAL(existingPurchasesResponseSuccess(std::vector<QString>)), this, SLOT(RefreshPurchasesSuccess(std::vector<QString>)));
Slot:
void RefreshPurchasesSuccess(std::vector<QString>);
void Store::RefreshPurchasesSuccess(std::vector<QString> previousPurchasesArray)
{
//do something
}
Signal:
void existingPurchasesResponseSuccess(std::vector<QString>);
vector<QString> previousPurchasesArray;
emit existingPurchasesResponseSuccess(previousPurchasesArray);
It says the signal/slot is not defined, but when I take out the vector it works, so it must be something wrong with that. Am I defining it wrong?
Thanks

If you use custom structure like std::vector<QString> you must declare and register metatype
Q_DECLARE_METATYPE(std::vector<QString>)
"Ideally, this macro should be placed below the declaration of the class or struct. If that is not possible, it can be put in a private header file which has to be included every time that type is used in a QVariant." -- Qt documentation on Q_DECLARE_METATYPE
For queued connections you may need qRegisterMetatype
qRegisterMetaType<std::vector<QString> >();
qRegisterMetaType can be called for example in main() even before QApplication::exec().
Also remember that you must use Q_OBJECT macro if your class declares any signals or slots.
"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."
If you have no reason to use std::vector<QString> then it would be much simpler to use QStringList, which is already known to Qt's meta-object system, provides many convenient methods to manipulate its content and as a standard Qt type will fit to non-yours slot definitions.

Related

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

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!!!

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

Passing arguments with signals and slots in qt

I am new to qt and i have got a question.
I wanted to connect signals and slots.
QObject::connect(_Requests, SIGNAL(newJobsAvailable(const MyClass &)), _Object, SLOT(doSend(const MyClass &)));
The qt complains about not being able to queue MyClass and etc.
How do i declare it correctly with
qRegisterMetaType<const MyClass &>("const MyClass&");
If Qt complains about not being able to queue you class this means that, Qt is unable to copy and put inside QVariant object of your class.
This only means that only direct connection will work. What does it mean? If you are using default value of last argument in connect then connection will not work between threads!
Setting last argument of connect to Qt::DirectConnection should silence the warning, and value Qt::QueuedConnection will not work at all.
Another way to fix it is to register your type. But you should do this without any qualifiers!
qRegisterMetaType<MyClass>("MyClass");
If you are using Qt5 then consider use of Q_GADGET macro in MyClass (just put it in beginning of class definition and add header to HEADERS in pro file).
You need to make sure that MyClass has public default and copy constructors. Because the object might be copied, even if you declare signals and slots with const ref.
If for some reason copy is out of the question then pass pointer as suggested by ratchet

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