diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/corelib/itemmodels/qsortfilterproxymodel.cpp | 89 | ||||
-rw-r--r-- | src/corelib/itemmodels/qsortfilterproxymodel.h | 2 | ||||
-rw-r--r-- | src/corelib/kernel/qmetaobject.cpp | 15 | ||||
-rw-r--r-- | src/corelib/kernel/qmetaobject.h | 1 | ||||
-rw-r--r-- | src/corelib/kernel/qmetaobject_p.h | 1 | ||||
-rw-r--r-- | src/corelib/kernel/qobjectdefs.h | 4 | ||||
-rw-r--r-- | src/tools/moc/generator.cpp | 72 | ||||
-rw-r--r-- | src/tools/moc/moc.cpp | 69 | ||||
-rw-r--r-- | src/tools/moc/moc.h | 5 |
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 ®Exp) 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); |