summaryrefslogtreecommitdiffstats
path: root/src/corelib/itemmodels/qabstractproxymodel_p.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/itemmodels/qabstractproxymodel_p.h')
-rw-r--r--src/corelib/itemmodels/qabstractproxymodel_p.h80
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