Hello. My name is Jesper Pedersen. I'm from KDAB, and
let's start out right away. I've got a quiz for you. Please have a look at the screen here. Text, that's
my text element in QML...Text: "Hello World." How does that work? Okay, that's quite a
broad question to ask you. So, text is actually an object that's implemented in C++. It's called QQuickText. I think that's a class name. That class has a method that's called
set text. But the question is whenever my QML parser interpreter, or whatever it is, reads that
QML file, it will see that there is text. It knows, "Okay, that means that I need to instantiate
a QQuickText element on the C++ side," and then it sees that it says Text: "Hello
World." How is that going to get into my set text? "Well, you started a video here called
Properties, so you likely have an idea what's going on here." Well, my text
will be converted into a QVariant We saw that in the previous video, right? So, my text
is going to be converted into QVariant and now it will call some method on that QQuickText
element, actually a method inherited from QObject that is called set property. It will take
the string text and it will take that QVariant. That's exactly what helps. My QObject subclass,
or my QUpdate class offers these two methods: one is called set property (taken in the name
of the property, taking the property as a value, and then it sets that property) and the other is
called property (it is how you read the property; it takes the name of the property you're
interested in and returns that as a QVariant). Okay, so far so good. We got it down there.
But how does that make it into the set text method of my QQuickText element?
Well, that's the next step. So, in my QQuickText class, I'm writing code
that smells awesome, much like this. It's a macro called Q_PROPERTY. First, I need to
specify a type. So, that's likely QString. Then, I need to specify a name. That name text, I read
as written: r-e-a-d, in capital letters...the function that can read that property...write a function
that can write that property...and some other stuff. "I don't get it. How is that going to get
me anywhere closer to what you're asking?" Well, let me show you. See...remember we have
a little friend in Qt land that's called moc. Moc will read this file and when "Mocsie" says
Q_PROPERTY and all of these things, it will set up a table that says, "whenever
you come with a set property method with the text string text,
that means that the write method should be called, namely, the set text and that
method should be given that property." Well, actually we also know that the type is QString. So we
should take that variant that came down to us to the set property method, we should unwrap that, and
convert that into whatever type it would like. And all of that is in your moc_whateverYourClassIs.cpp file.
Go and read that file straight forward for that particular
use case, and that's where it all fits together. Let's see a realistic example of what such
a class could look like. It's semi-realistic because we still don't know how to get objects
from C++ level up to QML. We will see that in the very next video. But for now, we'll just make
the properties system available in a class that we call Customer. It's sub class is QObjects. So, that's
a given. We need it to be a QObject. Otherwise, the super class is not providing us with
the property and set property methods. It needs a Q_OBJECT, and
of course it needs a Q_UPDATE because that is where all the
metaType magic gets into action. And then we have the Q_PROPERTY
for all of the properties we would like to support with this class. So, here I have a Q_PROPERTY. The type name is QString. The name of that property is Name. If I want to get
that property out of my object, then I will call getName. If I want to write it into it, then setName. And this part is super important for our QML use case. It's a signal that will fire whenever
the name is changing on the C++ layer. And you can see getName here is a
method that I must implement myself. setName is a method I must implement
myself. And the QString and the QString there match the QString that we have up
here. The signature for my getName is return that type, getName, and it must be
const. Take no parameters. Similarly, my set name must take exactly one parameter, which
is the const type reference of the type that I specified here in my Q_PROPERTY line. It must return nothing. Here's another version of that QString phone, MEMBER m_phone. That's an addition that came very late. Well, I'm very old.
So, that's why I can say very late. It's like 10 years ago in Qt. The MEMBER m_phone simply sets
up the read and the write for me, so I don't need to do that myself. I can have other types here. It's
a QType, as you can see. I can even have custom types. This has enums here; I
could also have custom types. But here, CustomerType is an enum and I need to mark that with
Q_ENUMS, with the name here. But that we'll talk about that later when we talk about the QML
integration. And these two here are CONSTANT, meaning they will never change. There will not
be set up any signal handlers listening to them. As I said, it's a somewhat weird example that we're
doing here because we do not have the QML layer to connect to yet. But let's simulate what
it would look like from the QML layer when we've implemented this. Well, it would look like this. On
the C++ side, I have my customer object. I set the address with regular C++ method. Now,
the QML level is interested in that. So the QML level would say customer.property("address"). That
of course will map into the getAddress method being called on my object. The result, which is
a QString, will be wrapped into a QVariant. It will be sent up into the QML level again.
Now if the QML level wants to set a property, then on the QML level it will create this
string here. It will convert it into a QVariant. That's all done on the QML level -- of course, not by
you but by the QML engine. And then the QML engine will, on my object, call setProperty with the
string for the name here, and then this QVariant. This QVariant then goes into the C++
level. It's the setName method that will be called. And just before the setName method is called,
the code generated by moc will take my QVariant and call dot to string on it, so that I get a QString. And that's the parameter given to my setName method on the C++ side. Now
you know even how properties, as we know them on the QML level, go down into these QObject
subclasses on the C++ side and get mapped into our property system down on the C++ level.
That is quite a bit of education you got there. That concludes this module here. We have been in
the machine room. I've shown you around. We saw, in the very first section, the Meta
Object System. Then, we saw a number of videos on signal/slot. We saw the QVariant class, and
now finished with how the property system works. Next up is that we'll finally go and look at the
integration from our C++ level up to our QML level. We'll see how we can
take an object down here and export it into QML. We'll see how we can even create
new elements from C++ that you, in QML, can instantiate. We will even go so far as to see
how we can create new elements that are painted on the C++ side, so you can get your own custom
elements. But that is all for the next module. Please do subscribe to our channel. That will make
you the first to know when that module is released. And if it has already been released, you will
know whenever anything else comes out from us. In the meantime, I'm Jesper Pedersen. I'm a proud
member of the KDAB family. Have a great day.