[Solved] Use of Q_PROPERTY's MEMBER keyword outside of QML?
-
Hi!
I've had a look at MEMBER keyword for Q_PROPERTY and was wondering when/how it could be of any use if it could be accessed from C++ code.
With this keyword, it is impossible to link both a getter and a setter to the property, so if I want to get and to set such a property's value in C++ code, it seems that I have to use property() and setProperty() with proper casting. Is there another way?
Does the metasystem considers "implicit/hidden" standard getters and setters (as I suppose it would in QML code)? If so, what is the correct syntax to use? I wanted to use it in order to clear up my classes, and therefore only implement getters or setters that are non-conventional (e.g. setters that process some checking before assigning (or not) or getters that may return a default value in some cases), but I cannot get any compilable code with this way of thinking.
Should I only use it to lighten classes that are only meant to be used in QML code? -
I think MEMBER will automatically create getters and setters for the property. property and setProperty are the typical naming conventions so I suggest you stick to them, although other identifiers can also work through the meta system. If you want to use custom identifiers for the set and get, don't use MEMBER, it was added to simplify and make properties faster to implement and reduce the associated boilerplate code.
-
Hi!
Thanks for your quick reply. I was thinking the same way you are, hence my question, when it doesn't seem to work.I am not using custom naming, though. They really are the same ones QtCreator would generate, but I get compiler errors because these getters and setters are considered non-existant!
I tried with Qt5.1.0 (final) and the stable version pulled from the git repository.
For example, the following code does not compile:
file SH_User.h
@class SH_User : public QObject
{
Q_OBJECT
Q_PROPERTY(QString name MEMBER m_name NOTIFY nameChanged)
...
signals:
nameChanged();
private:
QString m_name;
...
}@file SH_Group.h
@import "SH_User.h"
...
class SH_Group : public QObject
{
Q_OBJECT
...
public:
bool setContact(SH_User* contactUser);
...
private:
QStringList bannedUsers;
}@file SH_Group.cpp
@import "SH_Group.h"
...
bool SH_Group::setContact(SH_User* contactUser) {
if(!bannedUsers.contains(contactUser->name())) { //-----> HERE I get compilation error "class SH_User has no member named 'name'"
...
}
}@ -
According to "link":http://qt-project.org/wiki/New-Features-in-Qt-5.1
the MEMBER property does:- New keyword in Q_PROPERTY: MEMBER let you bind a property to a class member without requiring to have a getter or a setter.
-
Thanks, I have read the documentation first, including "QObject":http://qt-project.org/doc/qt-5.1/qtcore/qobject.html#Q_PROPERTY (which lacks mentioning MEMBER keyword) and "Qt's Property System":http://qt-project.org/doc/qt-5.1/qtcore/properties.html#qt-s-property-system . But explanation on MEMBER keyword purpose are not clear to me... Maybe because English is not my mother language, I don't know... Still, adding the use of this keyword in "A simple example":http://qt-project.org/doc/qt-5.1/qtcore/properties.html#a-simple-example would have been of serious help.
By the way, I also tried to replace contactUser->name() by contactUser->name [exact same error, that is "class SH_User has no member named 'name'"] and by contactUser->m_name ["SH_User member m_name is private"], with no success...
-
Oh I didn't quite read your question correctly.
You want to use the Q_PROPERTY for C++ only.I did a try and the MEMBER keyword works fine from QML. I can set, read and listen to the notify to an Object of your SH_User set as a ContextProperty to QML.
In C++ you cannot access the property via its name (it's a shame), so you need a setter and a getter.
The MEMBER keyword is not creating getters and setters for you. It mearly changes the generated moc file to use the member variable directly instead of via its setters/getters.I looked at the generated code and when using only the MEMBER keyword the moc uses the m_name directly, and in case of setting it, it actually also does the emit if the value changes.
If you specify a setter, it will call that instead and not emit the signal anymore, since that is the job of the setter.So in short using the MEMBER keyword will not help in C++ only.
-
That's indeed what I feared...
My SH_User class is used both in C++ and in QML, so I won't be able to lighten my code today...
Thanks for trying to help :-)
-
The MEMBER keyword does not generate getters and setters.
Like it was already explained by JapieKrekl it generates additional moc code to access the given member variable directly.
This moc code also handles NOTIFY and respects the CONSTANT keyword.But this does not mean that you cannot use it in C++.
1.) You can either make your member public which is not so nice for public APIs.
Or make them protected to access them from subclasses.
2.) You can access the property via the Qt's Property System. See
http://qt-project.org/doc/qt-5.1/qtcore/qmetaproperty.html
With Qt's property system you can enumerate all properties, or
also access them by name.This allows you to program against properties in a generic way without the need to know getter or setter names at compile time.
This was the use case why I added this feature a while ago to the moc.
I needed to serialize all kinds of QObject based classes into SQL Tables in a
generic way. When programming in a generic way getters and setters are not very helpful, but with Qt's property system this can be done.With the MEMBER keyword now the following things are possible:
generic access from C++, QtScript bindings, QML bindings, ActiveQt bindings, and much more...I see that there is also the use case of auto-generating getters and setters.
Indeed this was also my first approach to solve my usecase, but this is not so easy possible. You must get the generated code somehow into your hand written class.
The first idea would be to generate a base class, but this cannot access
members from a subclass. It would need to define also the members which is also not what we want.
Another idea is to generate the getter and setter prototypes via some
preprocesser magic directly inside the Q_PROPERTY keyword and put the
implementation into the moc file. But nobody had a working solution for that so far.But you are welcome to hack the MOC and submit patches to gerrit ;-)
regards,
Gerhard