Reputation: 718
In the code I'm working on I need to expose Q_PROPERTY
from private member(s) through one integrating QWidget
. Something like this would be nice:
class MyWidget: public QWidget{
Q_OBJECT
Q_PROPERTY(QString headerText MEMBER myLabel.text NOTIFY QLabel::notify)
private:
QLabel myLabel
}
Is it possible to do so and how? Or do I have to write all the get/set methods manually?
Upvotes: 5
Views: 1986
Reputation: 4233
The OP wants to avoid the manual boilerplate of getter/setter pairs that would not need to be written if we didn't want to expose a Q_PROPERTY.
I don't have a solution for that, but I am still interested in the "private members" aspect of the question.
In my case, I arrived here because I wanted to hide these required setters from all other code EXCEPT for Qt binding code.
Empirically, using Qt 5.12, the following does work for me:
class HolderOfSomeInteger : public QObject {
Q_OBJECT
Q_PROPERTY(int someInt
READ GetInt
NOTIFY someIntChanged)
signals:
void someIntChanged();
private: // <--- private section
// My own other classes cannot access this, but
// the QML binding works as expected anyhow.
int GetInt() const { return some_integer; }
int some_integer = 0;
};
So, in addition to keeping the int
data-member some_integer
private, I apparently can simply put the GetInt()
getter in the private
section as well.
However, as @adrian-maire said in https://stackoverflow.com/a/42348046/10278, "for some versions of Qt, you may find some tricks working, but they may stop working in a following version."
As this Qt Property System documentation looks today, it only says
"A READ accessor function is required if no MEMBER variable was specified. It is for reading the property value. Ideally, a const function is used for this purpose, and it must return either the property's type or a const reference to that type."
It says nothing about whether the accessor function must be public or private.
I dug some more, and I think I found out why the property binding still works with a private getter.
The Q_OBJECT
macro declares that your class has methods qt_metacall
and qt_static_metacall
. Qt's MOC
then generates the bodies of these methods.
The property binding is accomplished using those methods. Since those methods are members of your class, they (of course) can call even the private
member functions that your class provides.
Upvotes: 1
Reputation: 14845
You have to write your own getter/setter:
QString getText()const{ return myLabel.text();}
void setText( const QString& s){ myLabel.setText(s);}
And after you may define a Q_PROPERTY for it:
Q_PROPERTY( QString headerText READ getText WRITE setText)
Note: for some versions of Qt, you may found some tricks working, but they may stop working in a following version. For this reason, it is probably better to stick to common/standard behavior.
EDITED:
To add a bit of formalism to this answer, here is a related bug:
https://bugreports.qt.io/browse/QTBUG-47695?jql=text%20~%20%22Q_PROPERTY%20member%22
Summarizing: In Qt<=5.4 it was possible to use structure members in the Q_PROPERTY MEMBER parameter. This feature "Worked by chance" and is not supported from now.
Upvotes: 2