summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/corelib/itemmodels/qsortfilterproxymodel.cpp89
-rw-r--r--src/corelib/itemmodels/qsortfilterproxymodel.h2
-rw-r--r--src/corelib/kernel/qmetaobject.cpp15
-rw-r--r--src/corelib/kernel/qmetaobject.h1
-rw-r--r--src/corelib/kernel/qmetaobject_p.h1
-rw-r--r--src/corelib/kernel/qobjectdefs.h4
-rw-r--r--src/tools/moc/generator.cpp72
-rw-r--r--src/tools/moc/moc.cpp69
-rw-r--r--src/tools/moc/moc.h5
9 files changed, 215 insertions, 43 deletions
diff --git a/src/corelib/itemmodels/qsortfilterproxymodel.cpp b/src/corelib/itemmodels/qsortfilterproxymodel.cpp
index 9a4e9d57ed..a620e25f13 100644
--- a/src/corelib/itemmodels/qsortfilterproxymodel.cpp
+++ b/src/corelib/itemmodels/qsortfilterproxymodel.cpp
@@ -274,6 +274,12 @@ class QSortFilterProxyModelPrivate : public QAbstractProxyModelPrivate
Q_DECLARE_PUBLIC(QSortFilterProxyModel)
public:
+ enum class Direction {
+ Rows = 1,
+ Columns = 2,
+ All = Rows | Columns
+ };
+
struct Mapping {
QVector<int> source_rows;
QVector<int> source_columns;
@@ -413,7 +419,7 @@ public:
void update_persistent_indexes(const QModelIndexPairList &source_indexes);
void filter_about_to_be_changed(const QModelIndex &source_parent = QModelIndex());
- void filter_changed(const QModelIndex &source_parent = QModelIndex());
+ void filter_changed(Direction dir, const QModelIndex &source_parent = QModelIndex());
QSet<int> handle_filter_changed(
QVector<int> &source_to_proxy, QVector<int> &proxy_to_source,
const QModelIndex &source_parent, Qt::Orientation orient);
@@ -431,6 +437,11 @@ public:
typedef QHash<QModelIndex, QSortFilterProxyModelPrivate::Mapping *> IndexMap;
+static bool operator&(QSortFilterProxyModelPrivate::Direction a, QSortFilterProxyModelPrivate::Direction b)
+{
+ return int(a) & int(b);
+}
+
void QSortFilterProxyModelPrivate::_q_sourceModelDestroyed()
{
QAbstractProxyModelPrivate::_q_sourceModelDestroyed();
@@ -1269,14 +1280,14 @@ void QSortFilterProxyModelPrivate::filter_about_to_be_changed(const QModelIndex
Updates the proxy model (adds/removes rows) based on the
new filter.
*/
-void QSortFilterProxyModelPrivate::filter_changed(const QModelIndex &source_parent)
+void QSortFilterProxyModelPrivate::filter_changed(Direction dir, const QModelIndex &source_parent)
{
IndexMap::const_iterator it = source_index_mapping.constFind(source_parent);
if (it == source_index_mapping.constEnd())
return;
Mapping *m = it.value();
- QSet<int> rows_removed = handle_filter_changed(m->proxy_rows, m->source_rows, source_parent, Qt::Vertical);
- QSet<int> columns_removed = handle_filter_changed(m->proxy_columns, m->source_columns, source_parent, Qt::Horizontal);
+ const QSet<int> rows_removed = (dir & Direction::Rows) ? handle_filter_changed(m->proxy_rows, m->source_rows, source_parent, Qt::Vertical) : QSet<int>();
+ const QSet<int> columns_removed = (dir & Direction::Columns) ? handle_filter_changed(m->proxy_columns, m->source_columns, source_parent, Qt::Horizontal) : QSet<int>();
// We need to iterate over a copy of m->mapped_children because otherwise it may be changed by other code, invalidating
// the iterator it2.
@@ -1290,7 +1301,7 @@ void QSortFilterProxyModelPrivate::filter_changed(const QModelIndex &source_pare
indexesToRemove.push_back(i);
remove_from_mapping(source_child_index);
} else {
- filter_changed(source_child_index);
+ filter_changed(dir, source_child_index);
}
}
QVector<int>::const_iterator removeIt = indexesToRemove.constEnd();
@@ -2605,7 +2616,7 @@ void QSortFilterProxyModel::setFilterRegExp(const QRegExp &regExp)
Q_D(QSortFilterProxyModel);
d->filter_about_to_be_changed();
d->filter_data.setRegExp(regExp);
- d->filter_changed();
+ d->filter_changed(QSortFilterProxyModelPrivate::Direction::Rows);
}
#if QT_CONFIG(regularexpression)
@@ -2634,7 +2645,7 @@ void QSortFilterProxyModel::setFilterRegularExpression(const QRegularExpression
Q_D(QSortFilterProxyModel);
d->filter_about_to_be_changed();
d->filter_data.setRegularExpression(regularExpression);
- d->filter_changed();
+ d->filter_changed(QSortFilterProxyModelPrivate::Direction::Rows);
}
#endif
@@ -2657,7 +2668,7 @@ void QSortFilterProxyModel::setFilterKeyColumn(int column)
Q_D(QSortFilterProxyModel);
d->filter_about_to_be_changed();
d->filter_column = column;
- d->filter_changed();
+ d->filter_changed(QSortFilterProxyModelPrivate::Direction::Rows);
}
/*!
@@ -2683,7 +2694,7 @@ void QSortFilterProxyModel::setFilterCaseSensitivity(Qt::CaseSensitivity cs)
return;
d->filter_about_to_be_changed();
d->filter_data.setCaseSensitivity(cs);
- d->filter_changed();
+ d->filter_changed(QSortFilterProxyModelPrivate::Direction::Rows);
emit filterCaseSensitivityChanged(cs);
}
@@ -2754,7 +2765,7 @@ void QSortFilterProxyModel::setFilterRegExp(const QString &pattern)
QRegExp rx(pattern);
rx.setCaseSensitivity(d->filter_data.caseSensitivity());
d->filter_data.setRegExp(rx);
- d->filter_changed();
+ d->filter_changed(QSortFilterProxyModelPrivate::Direction::Rows);
}
#if QT_CONFIG(regularexpression)
@@ -2775,7 +2786,7 @@ void QSortFilterProxyModel::setFilterRegularExpression(const QString &pattern)
d->filter_about_to_be_changed();
QRegularExpression rx(pattern);
d->filter_data.setRegularExpression(rx);
- d->filter_changed();
+ d->filter_changed(QSortFilterProxyModelPrivate::Direction::Rows);
}
#endif
@@ -2791,7 +2802,7 @@ void QSortFilterProxyModel::setFilterWildcard(const QString &pattern)
d->filter_about_to_be_changed();
QRegExp rx(pattern, d->filter_data.caseSensitivity(), QRegExp::Wildcard);
d->filter_data.setRegExp(rx);
- d->filter_changed();
+ d->filter_changed(QSortFilterProxyModelPrivate::Direction::Rows);
}
/*!
@@ -2806,7 +2817,7 @@ void QSortFilterProxyModel::setFilterFixedString(const QString &pattern)
d->filter_about_to_be_changed();
QRegExp rx(pattern, d->filter_data.caseSensitivity(), QRegExp::FixedString);
d->filter_data.setRegExp(rx);
- d->filter_changed();
+ d->filter_changed(QSortFilterProxyModelPrivate::Direction::Rows);
}
/*!
@@ -2886,7 +2897,7 @@ void QSortFilterProxyModel::setFilterRole(int role)
return;
d->filter_about_to_be_changed();
d->filter_role = role;
- d->filter_changed();
+ d->filter_changed(QSortFilterProxyModelPrivate::Direction::Rows);
emit filterRoleChanged(role);
}
@@ -2913,7 +2924,7 @@ void QSortFilterProxyModel::setRecursiveFilteringEnabled(bool recursive)
return;
d->filter_about_to_be_changed();
d->filter_recursive = recursive;
- d->filter_changed();
+ d->filter_changed(QSortFilterProxyModelPrivate::Direction::Rows);
emit recursiveFilteringEnabledChanged(recursive);
}
@@ -2964,11 +2975,57 @@ void QSortFilterProxyModel::filterChanged()
(e.g. filterAcceptsRow()), and your filter parameters have changed.
\sa invalidate()
+ \sa invalidateColumnsFilter()
+ \sa invalidateRowsFilter()
*/
void QSortFilterProxyModel::invalidateFilter()
{
Q_D(QSortFilterProxyModel);
- d->filter_changed();
+ d->filter_changed(QSortFilterProxyModelPrivate::Direction::All);
+}
+
+/*!
+ \since 6.0
+
+ Invalidates the current filtering for the columns.
+
+ This function should be called if you are implementing custom filtering
+ (by filterAcceptsColumn()), and your filter parameters have changed.
+ This differs from invalidateFilter() in that it will not invoke
+ filterAcceptsRow(), but only filterAcceptsColumn(). You can use this
+ instead of invalidateFilter() if you want to hide or show a column where
+ the rows don't change.
+
+ \sa invalidate()
+ \sa invalidateFilter()
+ \sa invalidateRowsFilter()
+*/
+void QSortFilterProxyModel::invalidateColumnsFilter()
+{
+ Q_D(QSortFilterProxyModel);
+ d->filter_changed(QSortFilterProxyModelPrivate::Direction::Columns);
+}
+
+/*!
+ \since 6.0
+
+ Invalidates the current filtering for the rows.
+
+ This function should be called if you are implementing custom filtering
+ (by filterAcceptsRow()), and your filter parameters have changed.
+ This differs from invalidateFilter() in that it will not invoke
+ filterAcceptsColumn(), but only filterAcceptsRow(). You can use this
+ instead of invalidateFilter() if you want to hide or show a row where
+ the columns don't change.
+
+ \sa invalidate()
+ \sa invalidateFilter()
+ \sa invalidateColumnsFilter()
+*/
+void QSortFilterProxyModel::invalidateRowsFilter()
+{
+ Q_D(QSortFilterProxyModel);
+ d->filter_changed(QSortFilterProxyModelPrivate::Direction::Rows);
}
/*!
diff --git a/src/corelib/itemmodels/qsortfilterproxymodel.h b/src/corelib/itemmodels/qsortfilterproxymodel.h
index 91253dd601..fb26da39ba 100644
--- a/src/corelib/itemmodels/qsortfilterproxymodel.h
+++ b/src/corelib/itemmodels/qsortfilterproxymodel.h
@@ -143,6 +143,8 @@ protected:
QT_DEPRECATED_X("Use QSortFilterProxyModel::invalidateFilter") void filterChanged();
#endif
void invalidateFilter();
+ void invalidateRowsFilter();
+ void invalidateColumnsFilter();
public:
using QObject::parent;
diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp
index 9be99d8c6a..e715093127 100644
--- a/src/corelib/kernel/qmetaobject.cpp
+++ b/src/corelib/kernel/qmetaobject.cpp
@@ -3506,6 +3506,21 @@ bool QMetaProperty::isRequired() const
}
/*!
+ \since 6.0
+ Returns \c true if the property is implemented using a QProperty member; otherwise returns \c false.
+
+ This can be used to detect the availability of QProperty related meta-call types ahead of
+ performing the call itself.
+*/
+bool QMetaProperty::isQProperty() const
+{
+ if (!mobj)
+ return false;
+ int flags = mobj->d.data[handle + 2];
+ return flags & IsQProperty;
+}
+
+/*!
\obsolete
Returns \c true if the property is editable for the given \a object;
diff --git a/src/corelib/kernel/qmetaobject.h b/src/corelib/kernel/qmetaobject.h
index 08adc495e0..96f851a0e1 100644
--- a/src/corelib/kernel/qmetaobject.h
+++ b/src/corelib/kernel/qmetaobject.h
@@ -265,6 +265,7 @@ public:
bool isConstant() const;
bool isFinal() const;
bool isRequired() const;
+ bool isQProperty() const;
bool isFlagType() const;
bool isEnumType() const;
diff --git a/src/corelib/kernel/qmetaobject_p.h b/src/corelib/kernel/qmetaobject_p.h
index 277109dac4..49c43e3d79 100644
--- a/src/corelib/kernel/qmetaobject_p.h
+++ b/src/corelib/kernel/qmetaobject_p.h
@@ -87,6 +87,7 @@ enum PropertyFlags {
Notify = 0x00400000,
Revisioned = 0x00800000,
Required = 0x01000000,
+ IsQProperty = 0x02000000
};
enum MethodFlags {
diff --git a/src/corelib/kernel/qobjectdefs.h b/src/corelib/kernel/qobjectdefs.h
index fd7c081e88..5ae4c47259 100644
--- a/src/corelib/kernel/qobjectdefs.h
+++ b/src/corelib/kernel/qobjectdefs.h
@@ -390,7 +390,9 @@ struct Q_CORE_EXPORT QMetaObject
CreateInstance,
IndexOfMethod,
RegisterPropertyMetaType,
- RegisterMethodArgumentMetaType
+ RegisterMethodArgumentMetaType,
+ RegisterQPropertyObserver,
+ SetQPropertyBinding
};
int static_metacall(Call, int, void **) const;
diff --git a/src/tools/moc/generator.cpp b/src/tools/moc/generator.cpp
index 078eea257d..c0e1dca748 100644
--- a/src/tools/moc/generator.cpp
+++ b/src/tools/moc/generator.cpp
@@ -869,6 +869,9 @@ void Generator::generateProperties()
if (p.required)
flags |= Required;
+ if (p.isQProperty)
+ flags |= IsQProperty;
+
fprintf(out, " %4d, ", stridx(p.name));
generateTypeInfo(p.type);
fprintf(out, ", 0x%.8x,\n", flags);
@@ -1017,7 +1020,9 @@ void Generator::generateMetacall()
fprintf(out, "else ");
fprintf(out,
"if (_c == QMetaObject::ReadProperty || _c == QMetaObject::WriteProperty\n"
- " || _c == QMetaObject::ResetProperty || _c == QMetaObject::RegisterPropertyMetaType) {\n"
+ " || _c == QMetaObject::ResetProperty || _c == QMetaObject::RegisterPropertyMetaType\n"
+ " || _c == QMetaObject::RegisterQPropertyObserver\n"
+ " || _c == QMetaObject::SetQPropertyBinding) {\n"
" qt_static_metacall(this, _c, _id, _a);\n"
" _id -= %d;\n }", cdef->propertyList.count());
@@ -1354,6 +1359,7 @@ void Generator::generateStaticMetacall()
bool needTempVarForGet = false;
bool needSet = false;
bool needReset = false;
+ bool haveQProperties = false;
for (int i = 0; i < cdef->propertyList.size(); ++i) {
const PropertyDef &p = cdef->propertyList.at(i);
needGet |= !p.read.isEmpty() || !p.member.isEmpty();
@@ -1363,13 +1369,15 @@ void Generator::generateStaticMetacall()
needSet |= !p.write.isEmpty() || (!p.member.isEmpty() && !p.constant);
needReset |= !p.reset.isEmpty();
+ haveQProperties |= p.isQProperty;
}
fprintf(out, "\n#ifndef QT_NO_PROPERTIES\n ");
if (needElse)
fprintf(out, "else ");
fprintf(out, "if (_c == QMetaObject::ReadProperty) {\n");
- if (needGet) {
+
+ auto setupMemberAccess = [this]() {
if (cdef->hasQObject) {
#ifndef QT_NO_DEBUG
fprintf(out, " Q_ASSERT(staticMetaObject.cast(_o));\n");
@@ -1379,6 +1387,10 @@ void Generator::generateStaticMetacall()
fprintf(out, " auto *_t = reinterpret_cast<%s *>(_o);\n", cdef->classname.constData());
}
fprintf(out, " Q_UNUSED(_t)\n");
+ };
+
+ if (needGet) {
+ setupMemberAccess();
if (needTempVarForGet)
fprintf(out, " void *_v = _a[0];\n");
fprintf(out, " switch (_id) {\n");
@@ -1416,15 +1428,7 @@ void Generator::generateStaticMetacall()
fprintf(out, "if (_c == QMetaObject::WriteProperty) {\n");
if (needSet) {
- if (cdef->hasQObject) {
-#ifndef QT_NO_DEBUG
- fprintf(out, " Q_ASSERT(staticMetaObject.cast(_o));\n");
-#endif
- fprintf(out, " auto *_t = static_cast<%s *>(_o);\n", cdef->classname.constData());
- } else {
- fprintf(out, " auto *_t = reinterpret_cast<%s *>(_o);\n", cdef->classname.constData());
- }
- fprintf(out, " Q_UNUSED(_t)\n");
+ setupMemberAccess();
fprintf(out, " void *_v = _a[0];\n");
fprintf(out, " switch (_id) {\n");
for (int propindex = 0; propindex < cdef->propertyList.size(); ++propindex) {
@@ -1472,15 +1476,7 @@ void Generator::generateStaticMetacall()
fprintf(out, " else ");
fprintf(out, "if (_c == QMetaObject::ResetProperty) {\n");
if (needReset) {
- if (cdef->hasQObject) {
-#ifndef QT_NO_DEBUG
- fprintf(out, " Q_ASSERT(staticMetaObject.cast(_o));\n");
-#endif
- fprintf(out, " %s *_t = static_cast<%s *>(_o);\n", cdef->classname.constData(), cdef->classname.constData());
- } else {
- fprintf(out, " %s *_t = reinterpret_cast<%s *>(_o);\n", cdef->classname.constData(), cdef->classname.constData());
- }
- fprintf(out, " Q_UNUSED(_t)\n");
+ setupMemberAccess();
fprintf(out, " switch (_id) {\n");
for (int propindex = 0; propindex < cdef->propertyList.size(); ++propindex) {
const PropertyDef &p = cdef->propertyList.at(propindex);
@@ -1497,6 +1493,42 @@ void Generator::generateStaticMetacall()
fprintf(out, " }\n");
}
fprintf(out, " }");
+
+ fprintf(out, " else ");
+ fprintf(out, "if (_c == QMetaObject::RegisterQPropertyObserver) {\n");
+ if (haveQProperties) {
+ setupMemberAccess();
+ fprintf(out, " QPropertyObserver *observer = reinterpret_cast<QPropertyObserver *>(_a[0]);\n");
+ fprintf(out, " switch (_id) {\n");
+ for (int propindex = 0; propindex < cdef->propertyList.size(); ++propindex) {
+ const PropertyDef &p = cdef->propertyList.at(propindex);
+ if (!p.isQProperty)
+ continue;
+ fprintf(out, " case %d: observer->setSource(_t->%s); break;\n",
+ propindex, p.name.constData());
+ }
+ fprintf(out, " default: break;\n");
+ fprintf(out, " }\n");
+ }
+ fprintf(out, " }");
+
+ fprintf(out, " else ");
+ fprintf(out, "if (_c == QMetaObject::SetQPropertyBinding) {\n");
+ if (haveQProperties) {
+ setupMemberAccess();
+ fprintf(out, " switch (_id) {\n");
+ for (int propindex = 0; propindex < cdef->propertyList.size(); ++propindex) {
+ const PropertyDef &p = cdef->propertyList.at(propindex);
+ if (!p.isQProperty)
+ continue;
+ fprintf(out, " case %d: _t->%s.setBinding(*reinterpret_cast<QPropertyBinding<%s> *>(_a[0])); break;\n",
+ propindex, p.name.constData(), p.type.constData());
+ }
+ fprintf(out, " default: break;\n");
+ fprintf(out, " }\n");
+ }
+ fprintf(out, " }");
+
fprintf(out, "\n#endif // QT_NO_PROPERTIES");
needElse = true;
}
diff --git a/src/tools/moc/moc.cpp b/src/tools/moc/moc.cpp
index 03976771e5..56db54b457 100644
--- a/src/tools/moc/moc.cpp
+++ b/src/tools/moc/moc.cpp
@@ -564,6 +564,32 @@ bool Moc::parseMaybeFunction(const ClassDef *cdef, FunctionDef *def)
return true;
}
+
+// Try to parse QProperty<MyType> propertName; members
+bool Moc::parseMaybeQProperty(ClassDef *def)
+{
+ if (!test(IDENTIFIER))
+ return false;
+
+ if (lexem() != "QProperty")
+ return false;
+
+ if (!test(LANGLE))
+ return false;
+
+ until(RANGLE);
+
+ next();
+ const auto propName = lexem();
+
+ if (!test(SEMIC))
+ return false;
+
+ def->qPropertyMembers.insert(propName);
+
+ return true;
+}
+
void Moc::parse()
{
QVector<NamespaceDef> namespaceList;
@@ -909,7 +935,9 @@ void Moc::parse()
}
}
} else {
- index = rewind;
+ index = rewind - 1;
+ if (!parseMaybeQProperty(&def))
+ index = rewind;
}
}
}
@@ -1198,11 +1226,14 @@ void Moc::parseSignals(ClassDef *def)
void Moc::createPropertyDef(PropertyDef &propDef)
{
+ propDef.location = index;
+
QByteArray type = parseType().name;
if (type.isEmpty())
error();
propDef.designable = propDef.scriptable = propDef.stored = "true";
propDef.user = "false";
+
/*
The Q_PROPERTY construct cannot contain any commas, since
commas separate macro arguments. We therefore expect users
@@ -1234,6 +1265,17 @@ void Moc::createPropertyDef(PropertyDef &propDef)
next();
propDef.name = lexem();
+
+ // Could be Q_PROPERTY(type field) and later QProperty<int> field; -- to be resolved later.
+ if (lookup() == RPAREN) {
+ propDef.isQProperty = true;
+ propDef.designable = propDef.scriptable = propDef.stored = "true";
+ propDef.user = "false";
+ propDef.read = propDef.name + ".value";
+ propDef.write = propDef.name + ".setValue";
+ return;
+ }
+
while (test(IDENTIFIER)) {
const QByteArray l = lexem();
if (l[0] == 'C' && l == "CONSTANT") {
@@ -1320,11 +1362,6 @@ void Moc::createPropertyDef(PropertyDef &propDef)
error(2);
}
}
- if (propDef.read.isNull() && propDef.member.isNull()) {
- const QByteArray msg = "Property declaration " + propDef.name
- + " has no READ accessor function or associated MEMBER variable. The property will be invalid.";
- warning(msg.constData());
- }
if (propDef.constant && !propDef.write.isNull()) {
const QByteArray msg = "Property declaration " + propDef.name
+ " is both WRITEable and CONSTANT. CONSTANT will be ignored.";
@@ -1777,6 +1814,25 @@ void Moc::checkProperties(ClassDef *cdef)
}
definedProperties.insert(p.name);
+ const auto skipProperty = [&](const QByteArray &msg) {
+ const int rewind = index;
+ if (p.location >= 0)
+ index = p.location;
+ warning(msg.constData());
+ index = rewind;
+ cdef->propertyList.removeAt(i);
+ --i;
+ };
+
+ if (p.isQProperty) {
+ if (!cdef->qPropertyMembers.contains(p.name)) {
+ QByteArray msg = "Property declaration " + p.name + " has neither an associated QProperty<> member"
+ ", nor a READ accessor function nor an associated MEMBER variable. The property will be invalid.";
+ skipProperty(msg);
+ break;
+ }
+ }
+
for (int j = 0; j < cdef->publicList.count(); ++j) {
const FunctionDef &f = cdef->publicList.at(j);
if (f.name != p.read)
@@ -1989,6 +2045,7 @@ QJsonObject PropertyDef::toJson() const
prop[QLatin1String("constant")] = constant;
prop[QLatin1String("final")] = final;
prop[QLatin1String("required")] = required;
+ prop[QLatin1String("isQProperty")] = isQProperty;
if (revision > 0)
prop[QLatin1String("revision")] = revision;
diff --git a/src/tools/moc/moc.h b/src/tools/moc/moc.h
index 743749433f..210b6c7c2a 100644
--- a/src/tools/moc/moc.h
+++ b/src/tools/moc/moc.h
@@ -140,6 +140,9 @@ struct PropertyDef
bool constant = false;
bool final = false;
bool required = false;
+ bool isQProperty = false;
+
+ int location = -1; // token index, used for error reporting
QJsonObject toJson() const;
};
@@ -188,6 +191,7 @@ struct ClassDef : BaseDef {
QVector<FunctionDef> signalList, slotList, methodList, publicList;
QVector<QByteArray> nonClassSignalList;
QVector<PropertyDef> propertyList;
+ QSet<QByteArray> qPropertyMembers;
int notifyableProperties = 0;
int revisionedMethods = 0;
int revisionedProperties = 0;
@@ -247,6 +251,7 @@ public:
bool parseFunction(FunctionDef *def, bool inMacro = false);
bool parseMaybeFunction(const ClassDef *cdef, FunctionDef *def);
+ bool parseMaybeQProperty(ClassDef *def);
void parseSlots(ClassDef *def, FunctionDef::Access access);
void parseSignals(ClassDef *def);