Extending Qml in python : named signal parameters - qt

According to Qt's doc :
All Qt signals on a registered class become available as special "signal properties" within QML to which the user can assign a single JavaScript expression. The signal property's name is a transformed version of the Qt signal name: "on" is prepended, and the first letter of the signal name upper cased. For example, the signal used in the example above has the following C++ signature:
signals:
void partyStarted(const QTime &time);
Signal parameters become accessible by name to the assigned script. An unnamed parameter cannot be accessed, so care should be taken to name all the signal parameters in the C++ class declaration. The intrinsic types listed in Adding Types, as well registered object types are permitted as signal parameter types. Using other types is not an error, but the parameter value will not be accessible from script.
"so care should be taken to name all the signal parameters in the C++ class declaration" => How do i do that in python ?
I need this in my attempt to translate this custom C++ extension : http://qt-project.org/doc/note_revisions/44/221/view (WheelArea) into some python/PySide or PyQt code :
So far, i'm almost good, but i can't figure how to translate this part (the wheel event signals) :
signals:
void verticalWheel(int delta);
void horizontalWheel(int delta);
in python (the named signal parameters) to access the delta from qml.

Related

To access QML component in C++ backend

I have a qml file with Rectangle. I would like to trigger the onClicked( ) from C++ back-end.
So, How can I get access of QML component reference in C++/Qt backend?
You should use QObject::findChild() to locate the object, and simply invoke the signal as you would a nominal method.
But there is a catch, as QQuickRectangle itself is a private class, so it is not directly available for use in the C++ API. Also, it doesn't really have a clicked() signal, not unless you implemented one yourself. And if you did, it won't be part of the C++ interface.
Also, there is no onClicked() signal, the signal is clicked() and onClicked: is the handler hook.
However, you can still emit it using the Qt meta system, just use:
QObject * object = engine.rootObjects().at(0)->findChild<QObject *>("yourObjectName");
if (object) QMetaObject::invokeMethod(object, "clicked");
It will work even if the signal is implemented on the QML side, it will work even without casting to the concrete C++ type.
Now, if your object is not directly in the root object tree, you will not be able to find it and will have no choice but to pass a reference to it from the QML side to a C++ slot or invokable function.

SIGNAL & SLOT macros in Qt : what do they do?

I'm a beginner in Qt and trying to understand the SIGNAL and SLOT macros. When I'm learning to use the connect method to bind the signal and slot, I found the tutorials on Qt's official reference page uses:
connect(obj1, SIGNAL(signal(int)), obj2, SLOT(slot()))
However, this also works very well:
connect(obj1, &Obj1::signal, obj2, &Obj2::slot)
So what exactly do the macros SIGNAL and SLOT do? Do they just look for the signal in the class the object belongs to and return the address of it?
Then why do most programmers use these macros instead of using &Obj1::signal since the latter appears to be simpler and you don't need to change the code if the parameters of the signal function change?
The use of the SIGNAL and SLOT macros used to be the only way to make connections, before Qt 5. The connection is made at runtime and require signal and slots to be marked in the header. For example:
Class MyClass : public QObject
{
Q_OBJECT
signals:
void Signal();
slots:
void ASlotFunction();
};
To avoid repetition, the way in which it works is described in the QT 4 documentation.
The signal and slot mechanism is part of the C++ extensions that are provided by Qt and make use of the Meta Object Compiler (moc).
This explains why signals and slots use the moc.
The second connect method is much improved as the functions specified can be checked at the time of compilation, not runtime. In addition, by using the address of a function, you can refer to any class function, not just those in the section marked slots:
The documentation was updated for Qt 5.
In addition, there's a good blog post about the Qt 4 connect workings here and Qt 5 here.
Addition to the first answer.
what exactly did the macro SIGNAL and SLOT do
Almost nothing. Look at the qobjectdefs.h:
# define SLOT(a) "1"#a
# define SIGNAL(a) "2"#a
It just adds 1 or 2. It means that next code is valid and works as expected:
QObject *obj = new QObject;
connect(obj,"2objectNameChanged(QString)",this,"1show()");//suppose this is a pointer to a QDialog subclass
obj->setObjectName("newNAme");
why do most programmers use these macros instead of using like
&Obj1::signal
Because these macros work not only in Qt5.
Because with these macros there is no complexity with overloaded
signals (it can make your code very dirty and it is really not a simple thing)
Because with new syntax you sometimes need to use specific
disconnects
More details here.
To complete TheDarkKnight's answer, it is an excellent practice to refactor legacy code that is using the old Qt 4 SIGNAL and SLOT macros to Qt 5's new syntax using function address.
Suddenly, connection error will appear at compile time instead of at runtime! It's very easy to make a Qt 4 connection error as any spelling mistake will result in such an error. Plus, the name of the function must be the fully qualified name, i.e preceded with the full namespace if any.
Another benefit is the ability to use a lambda for the slot function, which can reduce need of a named function if the slot body is trivial.
These macros just convert their parameters to signal/slot-specific strings. The Differences between String-Based and Functor-Based Connections can be found in the docs. In short:
String-based:
Type checking is done at Run-time
Can connect signals to slots which have more arguments than the signal (using default parameters)
Can connect C++ functions to QML functions
Functor-based:
Type checking is done at Compile-time
Can perform implicit type conversions
Can connect signals to lambda expressions

QT - Understanding following lambda expression for a SLOT

I am currently trying to understand the new QT5 signal/slot syntax
connect(sender, &Sender::valueChanged, [=](const QString &newValue) {
receiver->updateValue("senderValue", newValue);
});
Now my question is where is the address of the receiver SLOT in the above expression ? I wanted to know this because what happens if a signal is in threadA and the slot is in thread B and I wanted it to be a queued connection ?
A slot is a piece of code, it doesn't "live" in a thread - a thread might run it or not, but the code itself doesn't belong to any thread. (If the slot is a member function, then the Qt object defined as the receiver belongs to a Qt thread - that's a property of the object, not the function.)
In the code you have above, the compiler generates an object that:
captures receiver by value ([=])
has a function-call operator that can be called with a reference to a const QString.
That object is passed to connect along with the other two arguments. It's not a QObject, so it doesn't have an owning thread in the Qt sense. What you need to make sure of is that:
what receiver points to stays alive for as long as that signal is connected
receiver->updateValue(...) is thread-safe - it will be called in sender's context/thread.
If receiver->updateValue needs to be called in receiver's thread/context, then do not use that syntax for the connect call, use the one where you specify both sender and receiver, and the connection type.

Can I pass an argument to the slot function when using QObject::connect?

Qt4.8.5
QObject::connect(button,SIGNAL(clicked()),label,SLOT(setText("dd"));
The Qt Creator tell me It's wrong . What's the problem ?
That you can't pass arguments in a connect() statement. You need a "trampoline" slot that sets the text of your label (or, in Qt 5, you might choose to use a lambda).
For instance, by using a subclass:
class MyLabel : public QLabel {
Q_OBJECT
public slots:
void setTextToFoo() { setText("foo"); }
};
// ...
connect(button,SIGNAL(clicked()),label,SLOT(setTextToFoo());
It depends what exactly you are trying to achieve, to be honest, the example code you provided is not very functional, is "dd" a particular static value you are using, or potentially some other string? Where does it come from, is it in the scope of the called, or is it sent by the caller, which is the usual practice when sending arguments to slots.
Either way, in order to make a connect statement the first requirement is for the arguments to match, clicked() has no arguments while setText() has one, so there is a mismatch. As of how to resolve that mismatch, the easiest way is to use simple wrappers, although you can use a QSignalMapper and as of Qt5, lambdas and std::bind.
For starters, you cannot specify the actual argument instance in the connect statement, even with arguments on both sides you only need to specify the types to help resolve overloads (it is terrible with the new connection syntax in Qt5), and not any actual identifiers or literals.
In case of the more usual scenario, where the data is send to the slot by the caller, the identifier or literal is specified in the emit signal(value) statement. Since you don't have clicked(const QString &) you need a wrapper slot that you connect to clicked() and emit with the value in that wrapper slot, or subclass the button and add your own overload of clicked(QString).
In case the value is in the scope of the called, then subclassing doesn't make much sense, all you need is the wrapper slot in the scope of the called object.
If you want more, you will have to use Qt 5, whose syntax is significantly more powerful.
If the question is whats wrong, just remember the parameter number must be the same for the Signal and the Slot. Asking a collegue and according the Peppe, setText(QString) wait for One parameter and the Clicked() is empty...A custom slot is to call the setText() method indirectly.
You can look that : http://qt-project.org/doc/qt-4.8/widgets-calculator.html
It uses the QWidget, an important part of Qt interfaces beside QML.

How does Qt implement signals and slots?

Can someone explain to me the basic idea of Qt signals&slots mechanism IMPLEMENTATION?
I want to know what all those Q_OBJECT macros do "in plain C++".
This question is NOT about signals&slots usage.
added:
I know that Qt uses moc compiler to transform Qt-C++ in plain C++.
But what does moc do?
I tried to read "moc_filename.cpp" files but I have no idea what can something like this mean
void *Widget::qt_metacast(const char *_clname)
{
if (!_clname) return 0;
if (!strcmp(_clname, qt_meta_stringdata_Widget))
return static_cast<void*>(const_cast< Widget*>(this));
return QDialog::qt_metacast(_clname);
}
Concerning the signals and slots, the Q_OBJECT macro adds a virtual function qt_metacall() declaration into the class’s declaration which is to be defined later by the the moc. (It also adds some declarations for conversion but that’s not too important here.)
The moc then reads the header file and when it sees the macro, it generates another .cpp file named moc_headerfilename.cpp with the definitions to the virtual functions and – you might have asked yourself why you can get away with mentioning the signals: in your header file without a proper definition – of the signals.
So, when a signal is called, the definition from the mocfile is executed and QMetaObject::activate() is called with the signal’s name and the signal’s arguments.
The activate() function then figures out which connections have been established and fetches the names for the appropriate slots.
Then it calls qt_metacall with the slot names and the arguments given to the signal and the metacall function delegates this with the help of a large switch—case statement to the real slots.
As there is no real runtime information possible in C++ concerning the actual names for the signals and slots, as has already been noticed, these will be encoded by the SIGNAL and SLOT macros to simple const char*s (with either "1" or "2" added to the name to distinguish signals from slots).
As is defined in qobjectdefs.h:
#define SLOT(a) "1"#a
#define SIGNAL(a) "2"#a
—
The other thing the Q_OBJECT macro does is defining the tr() functions inside your object which can be used to translate your application.
Edit
As you asked what the qt_metacast is doing. It checks whether an object belongs to certain class and if it does returns the pointer to it. If it doesn’t, it returns 0.
Widget* w = new Widget();
Q_ASSERT(w->qt_metacast("Widget") != 0);
Q_ASSERT(w->qt_metacast("QWidget") != 0);
Q_ASSERT(w->qt_metacast("QObject") != 0);
Q_ASSERT(w->qt_metacast("UnrelatedClass") == 0);
This is needed to provide some runtime reflection which is not possible otherwise. The function is called in QObject::inherits(const char *) for example and simply checks for inheritance.
Those macros do absolutely nothing "in plain C++", - they expand to empty strings (I think).
QT uses a meta-object compiler, that generates C++ code for Q_OBJECT-enabled classes (implementing the signals/slots you define, among other things).
You can read more about it in the official documentation.
The basic idea is that you can connect your objects allowing them to execute a method (slot) when a signal is done.
connect(pistol,SIGNAL(sigShoot()),runner,SLOT(slotRun()))
Doing the connection above, when the pistol emits the signal, the runner will execute its slot.
To do this, you have to declare your signals and slots in your respective classes.
Is the basic idea.
Good luck!

Resources