Skip to content

Commit

Permalink
Provide a way of exposing private QProperties with a fake API
Browse files Browse the repository at this point in the history
The API reduces the amount of manual plumbing required to offer a
conceptual property through the traditional setter/getter API as well as
through QProperty<T> API. Since the latter would require inlining the
type and thus making it impossible to add new properties without
breaking binary compatibility, this patch introduces a fake API that
behaves similar but does not contain the property by value.

Change-Id: Ib9bccd867f0e4e36a520e5583ba348e728284253
Reviewed-by: Fabian Kosmale <[email protected]>
  • Loading branch information
tronical committed Apr 30, 2020
1 parent b480acb commit 3d7265d
Show file tree
Hide file tree
Showing 9 changed files with 315 additions and 36 deletions.
32 changes: 32 additions & 0 deletions src/corelib/kernel/qtmetamacros.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,34 @@ QT_BEGIN_NAMESPACE
#define Q_INTERFACES(x) QT_ANNOTATE_CLASS(qt_interfaces, x)
#define Q_PROPERTY(...) QT_ANNOTATE_CLASS(qt_property, __VA_ARGS__)
#define Q_PRIVATE_PROPERTY(d, text) QT_ANNOTATE_CLASS2(qt_private_property, d, text)
#define Q_PRIVATE_QPROPERTY(accessor, type, name, setter, ...) \
struct _qt_property_api_##name { \
type value() const; \
type operator()() const { return value(); } \
void setValue(type &&); \
void setValue(const type &); \
void operator=(const type &v) { setValue(v); } \
void operator=(type &&v) { setValue(std::move(v)); } \
QPropertyBinding<type> setBinding(const QPropertyBinding<type> &); \
QPropertyBinding<type> setBinding(QPropertyBinding<type> &&); \
QPropertyBinding<type> operator=(const QPropertyBinding<type> &b) { return setBinding(b); } \
QPropertyBinding<type> operator=(QPropertyBinding<type> &&b) { return setBinding(std::move(b)); } \
bool setBinding(const QUntypedPropertyBinding &); \
template <typename Functor> \
QPropertyBinding<type> setBinding(Functor f, \
const QPropertyBindingSourceLocation &location = QT_PROPERTY_DEFAULT_BINDING_LOCATION) \
{ \
return setBinding(Qt::makePropertyBinding(f, location)); \
} \
bool hasBinding() const; \
QPropertyBinding<type> binding() const; \
QPropertyBinding<type> takeBinding(); \
}; \
void setter(const type &value);
#define Q_PRIVATE_QPROPERTIES_BEGIN union {
#define Q_PRIVATE_QPROPERTY_IMPL(name) \
_qt_property_api_##name name;
#define Q_PRIVATE_QPROPERTIES_END };
#ifndef Q_REVISION
# define Q_REVISION(...)
#endif
Expand Down Expand Up @@ -211,6 +239,10 @@ private: \
#define Q_INTERFACES(x) Q_INTERFACES(x)
#define Q_PROPERTY(text) Q_PROPERTY(text)
#define Q_PRIVATE_PROPERTY(d, text) Q_PRIVATE_PROPERTY(d, text)
#define Q_PRIVATE_QPROPERTY(accessor, type, name, setter, ...) Q_PRIVATE_QPROPERTY(accessor, type, name, setter, __VA_ARGS__)
#define Q_PRIVATE_QPROPERTIES_BEGIN
#define Q_PRIVATE_QPROPERTY_IMPL(name)
#define Q_PRIVATE_QPROPERTIES_END
#define Q_REVISION(...) Q_REVISION(__VA_ARGS__)
#define Q_OVERRIDE(text) Q_OVERRIDE(text)
#define Q_ENUMS(x) Q_ENUMS(x)
Expand Down
105 changes: 105 additions & 0 deletions src/tools/moc/generator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -615,6 +615,11 @@ void Generator::generateCode()
for (int signalindex = 0; signalindex < cdef->signalList.size(); ++signalindex)
generateSignal(&cdef->signalList[signalindex], signalindex);

//
// Generate QProperty forwarding API
//
generateQPropertyApi();

//
// Generate plugin meta data
//
Expand Down Expand Up @@ -1621,6 +1626,106 @@ void Generator::generateSignal(FunctionDef *def,int index)
fprintf(out, "}\n");
}

void Generator::generateQPropertyApi()
{
for (const PrivateQPropertyDef &property: cdef->privateQProperties) {
auto printAccessor = [this, property](bool constAccessor = false) {
const char *constOrNot = constAccessor ? "const " : " ";
fprintf(out, " const size_t propertyMemberOffset = reinterpret_cast<size_t>(&(static_cast<%s *>(nullptr)->%s));\n", cdef->qualified.constData(), property.name.constData());
fprintf(out, " %sauto *thisPtr = reinterpret_cast<%s%s *>(reinterpret_cast<%schar *>(this) - propertyMemberOffset);\n", constOrNot, constOrNot, cdef->qualified.constData(), constOrNot);
};

// property accessor
fprintf(out, "\n%s %s::_qt_property_api_%s::value() const\n{\n",
property.type.name.constData(),
cdef->qualified.constData(),
property.name.constData());
printAccessor(/*const*/true);
fprintf(out, " return thisPtr->%s->%s.value();\n", property.accessor.constData(), property.name.constData());
fprintf(out, "}\n");

// property value setter
fprintf(out, "\nvoid %s::_qt_property_api_%s::setValue(const %s &value)\n{\n",
cdef->qualified.constData(),
property.name.constData(),
property.type.name.constData());
printAccessor();
fprintf(out, " return thisPtr->%s->%s.setValue(value);\n", property.accessor.constData(), property.name.constData());
fprintf(out, "}\n");

// property value move setter
fprintf(out, "\nvoid %s::_qt_property_api_%s::setValue(%s &&value)\n{\n",
cdef->qualified.constData(),
property.name.constData(),
property.type.name.constData());
printAccessor();
fprintf(out, " return thisPtr->%s->%s.setValue(std::move(value));\n", property.accessor.constData(), property.name.constData());
fprintf(out, "}\n");

// binding setter
fprintf(out, "\nQPropertyBinding<%s> %s::_qt_property_api_%s::setBinding(const QPropertyBinding<%s> &binding)\n{\n",
property.type.name.constData(),
cdef->qualified.constData(),
property.name.constData(),
property.type.name.constData());
printAccessor();
fprintf(out, " return thisPtr->%s->%s.setBinding(binding);\n", property.accessor.constData(), property.name.constData());
fprintf(out, "}\n");

// binding move setter
fprintf(out, "\nQPropertyBinding<%s> %s::_qt_property_api_%s::setBinding(QPropertyBinding<%s> &&binding)\n{\n",
property.type.name.constData(),
cdef->qualified.constData(),
property.name.constData(),
property.type.name.constData());
printAccessor();
fprintf(out, " return thisPtr->%s->%s.setBinding(std::move(binding));\n", property.accessor.constData(), property.name.constData());
fprintf(out, "}\n");

// untyped binding setter
fprintf(out, "\nbool %s::_qt_property_api_%s::setBinding(const QUntypedPropertyBinding &binding)\n{\n",
cdef->qualified.constData(),
property.name.constData());
printAccessor();
fprintf(out, " return thisPtr->%s->%s.setBinding(binding);\n", property.accessor.constData(), property.name.constData());
fprintf(out, "}\n");

// binding bool getter
fprintf(out, "\nbool %s::_qt_property_api_%s::hasBinding() const\n{\n",
cdef->qualified.constData(),
property.name.constData());
printAccessor(/*const*/true);
fprintf(out, " return thisPtr->%s->%s.hasBinding();\n", property.accessor.constData(), property.name.constData());
fprintf(out, "}\n");

// binding getter
fprintf(out, "\nQPropertyBinding<%s> %s::_qt_property_api_%s::binding() const\n{\n",
property.type.name.constData(),
cdef->qualified.constData(),
property.name.constData());
printAccessor(/*const*/true);
fprintf(out, " return thisPtr->%s->%s.binding();\n", property.accessor.constData(), property.name.constData());
fprintf(out, "}\n");

// binding taker
fprintf(out, "\nQPropertyBinding<%s> %s::_qt_property_api_%s::takeBinding()\n{\n",
property.type.name.constData(),
cdef->qualified.constData(),
property.name.constData());
printAccessor();
fprintf(out, " return thisPtr->%s->%s.takeBinding();\n", property.accessor.constData(), property.name.constData());
fprintf(out, "}\n");

// property setter function
fprintf(out, "\nvoid %s::%s(const %s &value)\n{\n",
cdef->qualified.constData(),
property.setter.constData(),
property.type.name.constData());
fprintf(out, " %s->%s.setValue(value);\n", property.accessor.constData(), property.name.constData());
fprintf(out, "}\n\n");
}
}

static CborError jsonValueToCbor(CborEncoder *parent, const QJsonValue &v);
static CborError jsonObjectToCbor(CborEncoder *parent, const QJsonObject &o)
{
Expand Down
1 change: 1 addition & 0 deletions src/tools/moc/generator.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ class Generator
void generateMetacall();
void generateStaticMetacall();
void generateSignal(FunctionDef *def, int index);
void generateQPropertyApi();
void generatePluginMetaData();
QMultiMap<QByteArray, int> automaticPropertyMetaTypesHelper();
QMap<int, QMultiMap<QByteArray, int> > methodsWithAutomaticTypesHelper(const QVector<FunctionDef> &methodList);
Expand Down
61 changes: 35 additions & 26 deletions src/tools/moc/keywords.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,12 @@
// DO NOT EDIT.

static const short keyword_trans[][128] = {
{0,0,0,0,0,0,0,0,0,579,576,0,0,0,0,0,
{0,0,0,0,0,0,0,0,0,588,585,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
579,252,577,580,8,38,239,578,25,26,236,234,30,235,27,237,
588,252,586,589,8,38,239,587,25,26,236,234,30,235,27,237,
22,22,22,22,22,22,22,22,22,22,34,41,23,39,24,43,
0,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
8,21,8,8,8,8,8,8,8,8,8,31,582,32,238,8,
8,21,8,8,8,8,8,8,8,8,8,31,591,32,238,8,
0,1,2,3,4,5,6,7,8,9,8,8,10,11,12,13,
14,8,15,16,17,18,19,20,8,8,8,36,245,37,248,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
Expand Down Expand Up @@ -177,7 +177,7 @@ static const short keyword_trans[][128] = {
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,42,0,0,0,28,0,
585,585,585,585,585,585,585,585,585,585,0,0,0,0,0,0,
594,594,594,594,594,594,594,594,594,594,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
Expand Down Expand Up @@ -336,7 +336,7 @@ static const short keyword_trans[][128] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,584,0,0,0,0,583,
0,0,0,0,0,0,0,0,0,0,593,0,0,0,0,592,
0,0,0,0,0,0,0,0,0,0,0,0,0,258,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
Expand Down Expand Up @@ -378,8 +378,8 @@ static const short keyword_trans[][128] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,475,424,408,416,380,0,484,0,0,0,565,364,358,
386,0,557,472,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,475,424,408,416,380,0,484,0,0,0,574,364,358,
386,0,566,472,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
Expand Down Expand Up @@ -443,7 +443,7 @@ static const short keyword_trans[][128] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
549,0,0,517,0,0,0,0,0,0,0,0,0,0,0,0,
549,557,0,517,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
};
Expand Down Expand Up @@ -1013,30 +1013,39 @@ static const struct
{CHARACTER, 0, 84, 555, CHARACTER},
{CHARACTER, 0, 89, 556, CHARACTER},
{Q_PRIVATE_PROPERTY_TOKEN, 0, 0, 0, CHARACTER},
{CHARACTER, 0, 69, 558, CHARACTER},
{CHARACTER, 0, 86, 559, CHARACTER},
{CHARACTER, 0, 73, 560, CHARACTER},
{CHARACTER, 0, 83, 561, CHARACTER},
{CHARACTER, 0, 73, 562, CHARACTER},
{CHARACTER, 0, 79, 563, CHARACTER},
{CHARACTER, 0, 78, 564, CHARACTER},
{Q_REVISION_TOKEN, 0, 0, 0, CHARACTER},
{CHARACTER, 0, 79, 566, CHARACTER},
{CHARACTER, 0, 67, 567, CHARACTER},
{CHARACTER, 0, 95, 568, CHARACTER},
{CHARACTER, 0, 80, 558, CHARACTER},
{CHARACTER, 0, 82, 559, CHARACTER},
{CHARACTER, 0, 79, 560, CHARACTER},
{CHARACTER, 0, 80, 561, CHARACTER},
{CHARACTER, 0, 69, 562, CHARACTER},
{CHARACTER, 0, 82, 563, CHARACTER},
{CHARACTER, 0, 84, 564, CHARACTER},
{CHARACTER, 0, 89, 565, CHARACTER},
{Q_PRIVATE_QPROPERTY_TOKEN, 0, 0, 0, CHARACTER},
{CHARACTER, 0, 69, 567, CHARACTER},
{CHARACTER, 0, 86, 568, CHARACTER},
{CHARACTER, 0, 73, 569, CHARACTER},
{CHARACTER, 0, 78, 570, CHARACTER},
{CHARACTER, 0, 67, 571, CHARACTER},
{CHARACTER, 0, 76, 572, CHARACTER},
{CHARACTER, 0, 85, 573, CHARACTER},
{CHARACTER, 0, 68, 574, CHARACTER},
{CHARACTER, 0, 69, 575, CHARACTER},
{CHARACTER, 0, 83, 570, CHARACTER},
{CHARACTER, 0, 73, 571, CHARACTER},
{CHARACTER, 0, 79, 572, CHARACTER},
{CHARACTER, 0, 78, 573, CHARACTER},
{Q_REVISION_TOKEN, 0, 0, 0, CHARACTER},
{CHARACTER, 0, 79, 575, CHARACTER},
{CHARACTER, 0, 67, 576, CHARACTER},
{CHARACTER, 0, 95, 577, CHARACTER},
{CHARACTER, 0, 73, 578, CHARACTER},
{CHARACTER, 0, 78, 579, CHARACTER},
{CHARACTER, 0, 67, 580, CHARACTER},
{CHARACTER, 0, 76, 581, CHARACTER},
{CHARACTER, 0, 85, 582, CHARACTER},
{CHARACTER, 0, 68, 583, CHARACTER},
{CHARACTER, 0, 69, 584, CHARACTER},
{Q_MOC_INCLUDE_TOKEN, 0, 0, 0, CHARACTER},
{NEWLINE, 0, 0, 0, NOTOKEN},
{QUOTE, 0, 0, 0, NOTOKEN},
{SINGLEQUOTE, 0, 0, 0, NOTOKEN},
{WHITESPACE, 0, 0, 0, NOTOKEN},
{HASH, 0, 35, 581, HASH},
{HASH, 0, 35, 590, HASH},
{PP_HASHHASH, 0, 0, 0, NOTOKEN},
{BACKSLASH, 0, 0, 0, NOTOKEN},
{CPP_COMMENT, 0, 0, 0, NOTOKEN},
Expand Down
Loading

0 comments on commit 3d7265d

Please sign in to comment.