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:
Ievgenii Meshcheriakov 2021-09-22 13:40:21 +02:00
parent eb5cae26a4
commit de641fbc14
2 changed files with 5 additions and 68 deletions

View File

@ -161,8 +161,7 @@ QAbstractItemModel *QAbstractProxyModel::sourceModel() const
QBindable<QAbstractItemModel *> QAbstractProxyModel::bindableSourceModel()
{
Q_D(QAbstractProxyModel);
return QBindable<QAbstractItemModel *>(QAbstractProxyModelBindable(
&d->model, &QtPrivate::QBindableInterfaceForSourceModel::iface));
return QBindable<QAbstractItemModel *>(&d->model);
}
/*!

View File

@ -59,16 +59,6 @@ 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)
@ -82,69 +72,17 @@ public:
{
Q_EMIT q_func()->sourceModelChanged(QAbstractProxyModel::QPrivateSignal());
}
QAbstractItemModel *getModelForwarder() const { return q_func()->sourceModel(); }
Q_OBJECT_COMPAT_PROPERTY_WITH_ARGS(QAbstractProxyModelPrivate, QAbstractItemModel *, model,
&QAbstractProxyModelPrivate::setModelForwarder,
&QAbstractProxyModelPrivate::modelChangedForwarder, nullptr)
&QAbstractProxyModelPrivate::modelChangedForwarder,
&QAbstractProxyModelPrivate::getModelForwarder, 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