QAbstractProxyModel: Use QCompatProperty with custom getter
Use new API for QCompatProperty with custom getter instead of ad-hoc solution. Task-number: QTBUG-89655 Change-Id: I06481ad4d360b178be001ceb9c6c8460b73391f6 Reviewed-by: Ivan Solovev <ivan.solovev@qt.io>
This commit is contained in:
parent
eb5cae26a4
commit
de641fbc14
@ -161,8 +161,7 @@ QAbstractItemModel *QAbstractProxyModel::sourceModel() const
|
|||||||
QBindable<QAbstractItemModel *> QAbstractProxyModel::bindableSourceModel()
|
QBindable<QAbstractItemModel *> QAbstractProxyModel::bindableSourceModel()
|
||||||
{
|
{
|
||||||
Q_D(QAbstractProxyModel);
|
Q_D(QAbstractProxyModel);
|
||||||
return QBindable<QAbstractItemModel *>(QAbstractProxyModelBindable(
|
return QBindable<QAbstractItemModel *>(&d->model);
|
||||||
&d->model, &QtPrivate::QBindableInterfaceForSourceModel::iface));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -59,16 +59,6 @@ QT_REQUIRE_CONFIG(proxymodel);
|
|||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
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
|
class Q_CORE_EXPORT QAbstractProxyModelPrivate : public QAbstractItemModelPrivate
|
||||||
{
|
{
|
||||||
Q_DECLARE_PUBLIC(QAbstractProxyModel)
|
Q_DECLARE_PUBLIC(QAbstractProxyModel)
|
||||||
@ -82,69 +72,17 @@ public:
|
|||||||
{
|
{
|
||||||
Q_EMIT q_func()->sourceModelChanged(QAbstractProxyModel::QPrivateSignal());
|
Q_EMIT q_func()->sourceModelChanged(QAbstractProxyModel::QPrivateSignal());
|
||||||
}
|
}
|
||||||
|
QAbstractItemModel *getModelForwarder() const { return q_func()->sourceModel(); }
|
||||||
|
|
||||||
Q_OBJECT_COMPAT_PROPERTY_WITH_ARGS(QAbstractProxyModelPrivate, QAbstractItemModel *, model,
|
Q_OBJECT_COMPAT_PROPERTY_WITH_ARGS(QAbstractProxyModelPrivate, QAbstractItemModel *, model,
|
||||||
&QAbstractProxyModelPrivate::setModelForwarder,
|
&QAbstractProxyModelPrivate::setModelForwarder,
|
||||||
&QAbstractProxyModelPrivate::modelChangedForwarder, nullptr)
|
&QAbstractProxyModelPrivate::modelChangedForwarder,
|
||||||
|
&QAbstractProxyModelPrivate::getModelForwarder, nullptr)
|
||||||
virtual void _q_sourceModelDestroyed();
|
virtual void _q_sourceModelDestroyed();
|
||||||
void mapDropCoordinatesToSource(int row, int column, const QModelIndex &parent,
|
void mapDropCoordinatesToSource(int row, int column, const QModelIndex &parent,
|
||||||
int *source_row, int *source_column, QModelIndex *source_parent) const;
|
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
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
#endif // QABSTRACTPROXYMODEL_P_H
|
#endif // QABSTRACTPROXYMODEL_P_H
|
||||||
|
Loading…
x
Reference in New Issue
Block a user