diff options
Diffstat (limited to 'src/corelib/itemmodels/qabstractproxymodel_p.h')
-rw-r--r-- | src/corelib/itemmodels/qabstractproxymodel_p.h | 80 |
1 files changed, 78 insertions, 2 deletions
diff --git a/src/corelib/itemmodels/qabstractproxymodel_p.h b/src/corelib/itemmodels/qabstractproxymodel_p.h index a95687c970..350735afd1 100644 --- a/src/corelib/itemmodels/qabstractproxymodel_p.h +++ b/src/corelib/itemmodels/qabstractproxymodel_p.h @@ -53,22 +53,98 @@ // #include "private/qabstractitemmodel_p.h" +#include "private/qproperty_p.h" QT_REQUIRE_CONFIG(proxymodel); QT_BEGIN_NAMESPACE +class QAbstractProxyModelBindable : public QUntypedBindable +{ +public: + explicit QAbstractProxyModelBindable(QUntypedPropertyData *d, + const QtPrivate::QBindableInterface *i) + : QUntypedBindable(d, i) + { + } +}; + class Q_CORE_EXPORT QAbstractProxyModelPrivate : public QAbstractItemModelPrivate { Q_DECLARE_PUBLIC(QAbstractProxyModel) public: - QAbstractProxyModelPrivate() : QAbstractItemModelPrivate(), model(nullptr) {} - QAbstractItemModel *model; + QAbstractProxyModelPrivate() : QAbstractItemModelPrivate() { } + void setModelForwarder(QAbstractItemModel *sourceModel) + { + q_func()->setSourceModel(sourceModel); + } + void modelChangedForwarder() + { + Q_EMIT q_func()->sourceModelChanged(QAbstractProxyModel::QPrivateSignal()); + } + Q_OBJECT_COMPAT_PROPERTY_WITH_ARGS(QAbstractProxyModelPrivate, QAbstractItemModel *, model, + &QAbstractProxyModelPrivate::setModelForwarder, + &QAbstractProxyModelPrivate::modelChangedForwarder, nullptr) virtual void _q_sourceModelDestroyed(); void mapDropCoordinatesToSource(int row, int column, const QModelIndex &parent, int *source_row, int *source_column, QModelIndex *source_parent) const; + + using ModelPropertyType = decltype(model); }; +namespace QtPrivate { + +/*! + The biggest trick for adding new QProperty binding support here is the + getter for the sourceModel property (QAbstractProxyModel::sourceModel), + which returns nullptr, while internally using a global staticEmptyModel() + instance. + This lead to inconsistency while binding to a proxy model without source + model. The bound object would point to staticEmptyModel() instance, while + sourceModel() getter returns nullptr. + To solve this issue we need to implement a custom QBindableInterface, with + custom getter and makeBinding methods, that would introduce the required + logic. +*/ + +inline QAbstractItemModel *normalizePotentiallyEmptyModel(QAbstractItemModel *model) +{ + if (model == QAbstractItemModelPrivate::staticEmptyModel()) + return nullptr; + return model; +} + +class QBindableInterfaceForSourceModel +{ + using PropertyType = QAbstractProxyModelPrivate::ModelPropertyType; + using Parent = QBindableInterfaceForProperty<PropertyType>; + using T = typename PropertyType::value_type; + +public: + static constexpr QBindableInterface iface = { + [](const QUntypedPropertyData *d, void *value) -> void { + const auto val = static_cast<const PropertyType *>(d)->value(); + *static_cast<T *>(value) = normalizePotentiallyEmptyModel(val); + }, + Parent::iface.setter, + Parent::iface.getBinding, + Parent::iface.setBinding, + [](const QUntypedPropertyData *d, + const QPropertyBindingSourceLocation &location) -> QUntypedPropertyBinding { + return Qt::makePropertyBinding( + [d]() -> T { + return normalizePotentiallyEmptyModel( + static_cast<const PropertyType *>(d)->value()); + }, + location); + }, + Parent::iface.setObserver, + Parent::iface.metaType + }; +}; + +} // namespace QtPrivate + QT_END_NAMESPACE #endif // QABSTRACTPROXYMODEL_P_H |