I just found multiple examples showing the usage of Q_ENUM and Q_ENUMS and looking into the definition of Q_ENUM showed me that it includes Q_ENUMS and other definitions.
I am not sure which one to write when using the enum in Q_PROPERTY, Qml/QtQuick, in signals/slots, QVariants and qDebug() output.
It seems like the Q_ENUM is the better one as it is defined using Q_ENUMS, but I'm just guessing here.
What exactly are the differences, why are there two at all and which one should be prefered?
The What's New in Qt 5.5 says:
Added Q_ENUM to replace Q_ENUMS, which allows to get a QMetaEnum at compile time using QMetaEnum::fromType. Such enums are now automatically registered as metatypes, and can be converted to strings within QVariant, or printed as string by qDebug().
Since Qt 5.5 Q_ENUMS is deprecated, replaced with the better Q_ENUM.
There is an example showing its use in the Qt documentation:
class MyClass : public QObject
{
Q_OBJECT
Q_PROPERTY(Priority priority READ priority WRITE setPriority NOTIFY priorityChanged)
public:
MyClass(QObject *parent = 0);
~MyClass();
enum Priority { High, Low, VeryHigh, VeryLow };
Q_ENUM(Priority)
void setPriority(Priority priority)
{
m_priority = priority;
emit priorityChanged(priority);
}
Priority priority() const
{
return m_priority;
}
signals:
void priorityChanged(Priority);
private:
Priority m_priority;
};
For further details on the reasons behind the move from Q_ENUMS to Q_ENUM, read this blog entry
Related
I have created:
class A : public QObject
{
Q_OBJECT
public signals:
Q_SIGNAL void mySignal();
};
And I would like to derive:
class B : public A
{
//Some added functionality
};
And still be able to connect mySignal() emitted by B (which it inherited from A) to a slot in my QMainWindow:
B b;
connect(&b, SIGNAL(mySignal()), this, SLOT(aSlot()));
Currently this method results in "multiple definition of "A::disconnected()" and the compiler points me to the moc file here:
void A::disconnected()
{
QMetaObject::activate(this, &staticMetaObject, 0, nullptr);
}
What is the problem here?
I have done my research but what I found seems to be on different types of inheritance patterns and I don't understand Qt enough to port conclusions here.
Edit: I had stupidly forgotten the & in my original post, thanks Scheff's cat - I've updated my problem.
For those of you who have the same problem as this one, check your source file for a potential definition of A::mySignal()... I had created an empty definition of the function, as usual, whereas apparently MOC creates one for us. Resulting in multiple definitions.
Can I use a template type in any way as a slot or signal argument? As an example, I'm trying to define the following:
void exampleSignal(std::map<non_template_type_1,non_template_type_2> arg);
void exampleSlot(std::map<non_template_type_1,non_template_type_2> arg);
This results in the following during runtime:
QObject::connect: Cannot queue arguments of type
'std::map<non_template_type_1,non_template_type_2>'
(Make sure 'std::map<non_template_type_1,non_template_type_2>'
is registered using qRegisterMetaType().)
Trying to register std::map<non_template_type_1,non_template_type_2> with Q_DECLARE_METATYPE() results in compilation failure and apparently is not supported.
As a workaround, I'm using QVariantMap instead of std::map. But I really would like to know the correct way to solve this problem; one where it is not possible to modify the template classes.
Edit: I forgot to mention that the signal and slot are emitted and received in different threads. Apparently the runtime error doesn't occur in single-thread scenarios.
This works for me:
qRegisterMetaType< std::vector<float> >( "std::vector<float>" );
qRegisterMetaType< std::vector<int> >( "std::vector<int>" );
qRegisterMetaType< std::map<std::string,int64_t> >( "std::map<std::string,int64_t>" );
As explained in this thread you can try using a typedef, including the QMetaType header and then using both Q_DECLARE_METATYPE macro and the qRegisterMetaType function (as implied by this thread on a similar issue).
There is no problem if you created the class like this and used the Qt moc compiler to create those QMetaObject's automatically:
class MyClass : public QObject
{
Q_OBJECT
public:
explicit MyClass(QObject *parent = 0)
: QObject(parent)
{
}
public slots:
void exampleSlot(std::map<non_template_type_1,non_template_type_2> arg);
signals:
void exampleSignal(std::map<non_template_type_1,non_template_type_2> arg);
};
Of course you need to include QObject and wherever std::map is located at.
I am not able to understand the usage of Q_PROPERTY. How th Q_PROPERTY helps in making a program defensive? What is it used for? I have seen the forum, but really not able to make its applicaton. I have understood the example, but not it's usage.
Here is the example, what do I gain with it. I understand that read will give a privilege of reading only.
The write property will give the privilege to write only. But what is the need of it? Can someone exemplify it?
class MyClass : public QObject
{
Q_OBJECT
Q_PROPERTY(Priority priority READ priority WRITE setPriority NOTIFY priorityChanged)
Q_ENUMS(Priority)
public:
MyClass(QObject *parent = 0);
~MyClass();
enum Priority { High, Low, VeryHigh, VeryLow };
void setPriority(Priority priority)
{
m_priority = priority;
emit priorityChanged(priority);
}
Priority priority() const
{ return m_priority; }
signals:
void priorityChanged(Priority);
private:
Priority m_priority;
};
It has the following advantages:
It is available for the meta object system, so it can be introspected, used from QML etc.
It has further options than just read and write. Look at notify, reset, etc. It is also easier to integrate them into QtCreator (designer).
You do not need to write the boilerplate with Qt 5.1 onwards in common read and write cases because they will be generated for you.
Boost.Signals allows various strategies of using the return values of slots to form the return value of the signal. E.g. adding them, forming a vector out of them, or returning the last one.
The common wisdom (expressed in the Qt documentation [EDIT: as well as some answers to this question ]) is that no such thing is possible with Qt signals.
However, when I run the moc on the following class definition:
class Object : public QObject {
Q_OBJECT
public:
explicit Object( QObject * parent=0 )
: QObject( parent ) {}
public Q_SLOTS:
void voidSlot();
int intSlot();
Q_SIGNALS:
void voidSignal();
int intSignal();
};
Not only doesn't moc complain about the signal with the non-void return type, it seems to actively implement it in such a way as to allow a return value to pass:
// SIGNAL 1
int Object::intSignal()
{
int _t0;
void *_a[] = { const_cast<void*>(reinterpret_cast<const void*>(&_t0)) };
QMetaObject::activate(this, &staticMetaObject, 1, _a);
return _t0;
}
So: according to the docs, this thing isn't possible. Then what is moc doing here?
Slots can have return values, so can we connect a slot with a return value to a signal with a return value now? May that be possible, after all? If so, is it useful?
EDIT: I'm not asking for workarounds, so please don't provide any.
EDIT: It obviously isn't useful in Qt::QueuedConnection mode (neither is the QPrintPreviewWidget API, though, and still it exists and is useful). But what about Qt::DirectConnection and Qt::BlockingQueuedConnection (or Qt::AutoConnection, when it resolves to Qt::DirectConnection).
OK. So, I did a little more investigating. Seems this is possible. I was able to emit a signal, and receive value from the slot the signal was connected to. But, the problem was that it only returned the last return value from the multiple connected slots:
Here's a simple class definition (main.cpp):
#include <QObject>
#include <QDebug>
class TestClass : public QObject
{
Q_OBJECT
public:
TestClass();
Q_SIGNALS:
QString testSignal();
public Q_SLOTS:
QString testSlot1() {
return QLatin1String("testSlot1");
}
QString testSlot2() {
return QLatin1String("testSlot2");
}
};
TestClass::TestClass() {
connect(this, SIGNAL(testSignal()), this, SLOT(testSlot1()));
connect(this, SIGNAL(testSignal()), this, SLOT(testSlot2()));
QString a = emit testSignal();
qDebug() << a;
}
int main() {
TestClass a;
}
#include "main.moc"
When main runs, it constructs one of the test classes. The constructor wires up two slots to the testSignal signal, and then emits the signal. It captures the return value from the slot(s) invoked.
Unfortunately, you only get the last return value. If you evaluate the code above, you'll get: "testSlot2", the last return value from the connected slots of the signal.
Here's why. Qt Signals are a syntax sugared interface to the signaling pattern. Slots are the recipients of a signal. In a direct connected signal-slot relationship, you could think of it similar to (pseudo-code):
foreach slot in connectedSlotsForSignal(signal):
value = invoke slot with parameters from signal
return value
Obviously the moc does a little more to help in this process (rudimentary type checking, etc), but this helps paint the picture.
No, they can't.
Boost::signals are quite different from those in Qt. The former provide an advanced callback mechanism, whereas the latter implement the signaling idiom. In the context of multithreading, Qt's (cross-threaded) signals depend on message queues, so they are called asynchronously at some (unknown to the emitter's thread) point in time.
Qt's qt_metacall function returns an integer status code. Because of this, I believe this makes an actual return value impossible (unless you fudge around with the meta object system and moc files after precompilation).
You do, however, have normal function parameters at your disposal. It should be possible to modify your code in such a way to use "out" parameters that act as your "return".
void ClassObj::method(return_type * return_)
{
...
if(return_) *return_ = ...;
}
// somewhere else in the code...
return_type ret;
emit this->method(&ret);
You may get a return value from Qt signal with the following code:
My example shows how to use a Qt signal to read the text of a QLineEdit.
I'm just extending what #jordan has proposed:
It should be possible to modify your code in such a way to use "out" parameters that act as your "return".
#include <QtCore>
#include <QtGui>
class SignalsRet : public QObject
{
Q_OBJECT
public:
SignalsRet()
{
connect(this, SIGNAL(Get(QString*)), SLOT(GetCurrentThread(QString*)), Qt::DirectConnection);
connect(this, SIGNAL(GetFromAnotherThread(QString*)), SLOT(ReadObject(QString*)), Qt::BlockingQueuedConnection);
edit.setText("This is a test");
}
public slots:
QString call()
{
QString text;
emit Get(&text);
return text;
}
signals:
void Get(QString *value);
void GetFromAnotherThread(QString *value);
private slots:
void GetCurrentThread(QString *value)
{
QThread *thread = QThread::currentThread();
QThread *mainthread = this->thread();
if(thread == mainthread) //Signal called from the same thread that SignalsRet class was living
ReadObject(value);
else //Signal called from another thread
emit GetFromAnotherThread(value);
}
void ReadObject(QString *value)
{
QString text = edit.text();
*value = text;
}
private:
QLineEdit edit;
};
To use this, just request call();.
You can try to workaround this with following:
All your connected slots must save their results in some place (container) accessible from signaling object
The last connected slot should somehow (select max or last value) process collected values and expose the only one
The emitting object can try to access this result
Just as an idea.
Automatic indentation in VS editor obviously does not know about Qt. And declarations of signals and slots are auto-formatted like this:
class MyClass : public QObject
{
Q_OBJECT
public:
MyClass();
signals: // <-- Broken indentation
void someSignal();
public slots: // <-- Also broken
void someSlot();
};
I want "signals:" and "slots:" automatically formatted just like access specifiers. What are the options? (I'm using VS2010)
In short answer seems to be NO. Maybe not what you are looking for but maybe you can live with this:
class MyClass : public QObject
{
Q_OBJECT
public:
MyClass();
private:
Q_SIGNAL void someSignal();
public:
Q_SLOT void someSlot();
};
(It's ugly but it seems you can't have your cake and eat it too ;)
Just something I'm wondering about: Is it worth the effort to build a plugin for automatic formatting? Do we really use CTRL-A CTRL-F so much? If so, then yes it could be a pain. But normally if you are working on header files declaring a new method (signal or slot) should not mess up the previous corrected indentation. Perhaps you have some reasons that justifies this?