QGIM: standardise detection of metaobject, also for smart pointers
Change-Id: I01acbfecfad582dd663c9ae2540be277414935db Reviewed-by: Artem Dyomin <artem.dyomin@qt.io>
This commit is contained in:
parent
91ec68313a
commit
3c46f2ef96
@ -249,9 +249,8 @@ protected:
|
|||||||
using const_row_ptr = const wrapped_row_type *;
|
using const_row_ptr = const wrapped_row_type *;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static constexpr bool has_metaobject =
|
static constexpr bool has_metaobject = QGenericItemModelDetails::has_metaobject_v<
|
||||||
(QtPrivate::QMetaTypeForType<std::remove_pointer_t<T>>::flags() & QMetaType::IsGadget)
|
std::remove_pointer_t<std::remove_reference_t<T>>>;
|
||||||
|| (QtPrivate::QMetaTypeForType<T>::flags() & QMetaType::PointerToQObject);
|
|
||||||
|
|
||||||
using ModelData = QGenericItemModelDetails::ModelData<std::conditional_t<
|
using ModelData = QGenericItemModelDetails::ModelData<std::conditional_t<
|
||||||
std::is_pointer_v<Range>,
|
std::is_pointer_v<Range>,
|
||||||
@ -384,9 +383,9 @@ public:
|
|||||||
|
|
||||||
Qt::ItemFlags f = Structure::defaultFlags();
|
Qt::ItemFlags f = Structure::defaultFlags();
|
||||||
|
|
||||||
if constexpr (has_metaobject<row_type>) {
|
if constexpr (has_metaobject<wrapped_row_type>) {
|
||||||
if (index.column() < row_traits::fixed_size()) {
|
if (index.column() < row_traits::fixed_size()) {
|
||||||
const QMetaObject mo = std::remove_pointer_t<row_type>::staticMetaObject;
|
const QMetaObject mo = wrapped_row_type::staticMetaObject;
|
||||||
const QMetaProperty prop = mo.property(index.column() + mo.propertyOffset());
|
const QMetaProperty prop = mo.property(index.column() + mo.propertyOffset());
|
||||||
if (prop.isWritable())
|
if (prop.isWritable())
|
||||||
f |= Qt::ItemIsEditable;
|
f |= Qt::ItemIsEditable;
|
||||||
@ -424,14 +423,13 @@ public:
|
|||||||
return m_itemModel->QAbstractItemModel::headerData(section, orientation, role);
|
return m_itemModel->QAbstractItemModel::headerData(section, orientation, role);
|
||||||
}
|
}
|
||||||
|
|
||||||
if constexpr (has_metaobject<row_type>) {
|
if constexpr (has_metaobject<wrapped_row_type>) {
|
||||||
using meta_type = std::remove_pointer_t<row_type>;
|
|
||||||
if (row_traits::fixed_size() == 1) {
|
if (row_traits::fixed_size() == 1) {
|
||||||
const QMetaType metaType = QMetaType::fromType<meta_type>();
|
const QMetaType metaType = QMetaType::fromType<wrapped_row_type>();
|
||||||
result = QString::fromUtf8(metaType.name());
|
result = QString::fromUtf8(metaType.name());
|
||||||
} else if (section <= row_traits::fixed_size()) {
|
} else if (section <= row_traits::fixed_size()) {
|
||||||
const QMetaProperty prop = meta_type::staticMetaObject.property(
|
const QMetaProperty prop = wrapped_row_type::staticMetaObject.property(
|
||||||
section + meta_type::staticMetaObject.propertyOffset());
|
section + wrapped_row_type::staticMetaObject.propertyOffset());
|
||||||
result = QString::fromUtf8(prop.name());
|
result = QString::fromUtf8(prop.name());
|
||||||
}
|
}
|
||||||
} else if constexpr (static_column_count >= 1) {
|
} else if constexpr (static_column_count >= 1) {
|
||||||
@ -453,10 +451,10 @@ public:
|
|||||||
using multi_role = QGenericItemModelDetails::is_multi_role<value_type>;
|
using multi_role = QGenericItemModelDetails::is_multi_role<value_type>;
|
||||||
if constexpr (has_metaobject<value_type>) {
|
if constexpr (has_metaobject<value_type>) {
|
||||||
if (row_traits::fixed_size() <= 1) {
|
if (row_traits::fixed_size() <= 1) {
|
||||||
result = readRole(role, value);
|
result = readRole(role, QGenericItemModelDetails::pointerTo(value));
|
||||||
} else if (column <= row_traits::fixed_size()
|
} else if (column <= row_traits::fixed_size()
|
||||||
&& (role == Qt::DisplayRole || role == Qt::EditRole)) {
|
&& (role == Qt::DisplayRole || role == Qt::EditRole)) {
|
||||||
result = readProperty(column, value);
|
result = readProperty(column, QGenericItemModelDetails::pointerTo(value));
|
||||||
}
|
}
|
||||||
} else if constexpr (multi_role::value) {
|
} else if constexpr (multi_role::value) {
|
||||||
const auto it = [this, &value, role]{
|
const auto it = [this, &value, role]{
|
||||||
@ -509,7 +507,7 @@ public:
|
|||||||
} else if constexpr (has_metaobject<value_type>) {
|
} else if constexpr (has_metaobject<value_type>) {
|
||||||
if (row_traits::fixed_size() <= 1) {
|
if (row_traits::fixed_size() <= 1) {
|
||||||
tried = true;
|
tried = true;
|
||||||
using meta_type = std::remove_pointer_t<value_type>;
|
using meta_type = QGenericItemModelDetails::wrapped_t<value_type>;
|
||||||
const QMetaObject &mo = meta_type::staticMetaObject;
|
const QMetaObject &mo = meta_type::staticMetaObject;
|
||||||
for (auto &&[role, roleName] : roleNames().asKeyValueRange()) {
|
for (auto &&[role, roleName] : roleNames().asKeyValueRange()) {
|
||||||
QVariant data;
|
QVariant data;
|
||||||
@ -567,10 +565,10 @@ public:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else if (row_traits::fixed_size() <= 1) {
|
} else if (row_traits::fixed_size() <= 1) {
|
||||||
return writeRole(role, target, data);
|
return writeRole(role, QGenericItemModelDetails::pointerTo(target), data);
|
||||||
} else if (column <= row_traits::fixed_size()
|
} else if (column <= row_traits::fixed_size()
|
||||||
&& (role == Qt::DisplayRole || role == Qt::EditRole)) {
|
&& (role == Qt::DisplayRole || role == Qt::EditRole)) {
|
||||||
return writeProperty(column, target, data);
|
return writeProperty(column, QGenericItemModelDetails::pointerTo(target), data);
|
||||||
}
|
}
|
||||||
} else if constexpr (multi_role::value) {
|
} else if constexpr (multi_role::value) {
|
||||||
Qt::ItemDataRole roleToSet = Qt::ItemDataRole(role);
|
Qt::ItemDataRole roleToSet = Qt::ItemDataRole(role);
|
||||||
@ -646,7 +644,7 @@ public:
|
|||||||
} else if constexpr (has_metaobject<value_type>) {
|
} else if constexpr (has_metaobject<value_type>) {
|
||||||
if (row_traits::fixed_size() <= 1) {
|
if (row_traits::fixed_size() <= 1) {
|
||||||
tried = true;
|
tried = true;
|
||||||
using meta_type = std::remove_pointer_t<value_type>;
|
using meta_type = QGenericItemModelDetails::wrapped_t<value_type>;
|
||||||
const QMetaObject &mo = meta_type::staticMetaObject;
|
const QMetaObject &mo = meta_type::staticMetaObject;
|
||||||
// transactional: if possible, modify a copy and only
|
// transactional: if possible, modify a copy and only
|
||||||
// update target if all values from data could be stored.
|
// update target if all values from data could be stored.
|
||||||
@ -721,9 +719,9 @@ public:
|
|||||||
if constexpr (has_metaobject<row_type>) {
|
if constexpr (has_metaobject<row_type>) {
|
||||||
if (row_traits::fixed_size() <= 1) {
|
if (row_traits::fixed_size() <= 1) {
|
||||||
// multi-role object/gadget: reset all properties
|
// multi-role object/gadget: reset all properties
|
||||||
return resetProperty(-1, target);
|
return resetProperty(-1, QGenericItemModelDetails::pointerTo(target));
|
||||||
} else if (column <= row_traits::fixed_size()) {
|
} else if (column <= row_traits::fixed_size()) {
|
||||||
return resetProperty(column, target);
|
return resetProperty(column, QGenericItemModelDetails::pointerTo(target));
|
||||||
}
|
}
|
||||||
} else { // normal structs, values, associative containers
|
} else { // normal structs, values, associative containers
|
||||||
target = {};
|
target = {};
|
||||||
|
@ -328,6 +328,17 @@ namespace QGenericItemModelDetails
|
|||||||
[[maybe_unused]] static constexpr int static_size_v =
|
[[maybe_unused]] static constexpr int static_size_v =
|
||||||
row_traits<std::remove_cv_t<wrapped_t<T>>>::static_size;
|
row_traits<std::remove_cv_t<wrapped_t<T>>>::static_size;
|
||||||
|
|
||||||
|
// we can't add this as a member to row_traits, as we'd end up with
|
||||||
|
// ambiguous specializations for gadgets implementing tuple protocol.
|
||||||
|
template <typename T, typename = void>
|
||||||
|
struct has_metaobject : std::false_type {};
|
||||||
|
template <typename T>
|
||||||
|
struct has_metaobject<T, std::void_t<decltype(wrapped_t<T>::staticMetaObject)>>
|
||||||
|
: std::true_type {};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
[[maybe_unused]] static constexpr bool has_metaobject_v = has_metaobject<T>::value;
|
||||||
|
|
||||||
template <typename Range>
|
template <typename Range>
|
||||||
struct ListProtocol
|
struct ListProtocol
|
||||||
{
|
{
|
||||||
@ -364,7 +375,7 @@ namespace QGenericItemModelDetails
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <typename Range, typename R = typename range_traits<wrapped_t<Range>>::value_type>
|
template <typename Range, typename R = typename range_traits<wrapped_t<Range>>::value_type>
|
||||||
using table_protocol_t = std::conditional_t<static_size_v<R> == 0,
|
using table_protocol_t = std::conditional_t<static_size_v<R> == 0 && !has_metaobject_v<R>,
|
||||||
ListProtocol<Range>, TableProtocol<Range>>;
|
ListProtocol<Range>, TableProtocol<Range>>;
|
||||||
|
|
||||||
// Default tree traversal protocol implementation for row types that have
|
// Default tree traversal protocol implementation for row types that have
|
||||||
|
@ -1235,10 +1235,8 @@ void tst_QGenericItemModel::insertRows()
|
|||||||
|
|
||||||
QEXPECT_FAIL("tableOfPointersPointer", "No item created", Continue);
|
QEXPECT_FAIL("tableOfPointersPointer", "No item created", Continue);
|
||||||
QEXPECT_FAIL("tableOfPointersRef", "No item created", Continue);
|
QEXPECT_FAIL("tableOfPointersRef", "No item created", Continue);
|
||||||
QEXPECT_FAIL("listOfObjectsCopy", "No object created", Continue);
|
|
||||||
QEXPECT_FAIL("listOfMetaObjectTupleCopy", "No object created", Continue);
|
QEXPECT_FAIL("listOfMetaObjectTupleCopy", "No object created", Continue);
|
||||||
QEXPECT_FAIL("tableOfMetaObjectTupleCopy", "No object created", Continue);
|
QEXPECT_FAIL("tableOfMetaObjectTupleCopy", "No object created", Continue);
|
||||||
QEXPECT_FAIL("movedListOfObjects", "No object created", Continue);
|
|
||||||
|
|
||||||
QVERIFY(firstValue.isValid() && lastValue.isValid());
|
QVERIFY(firstValue.isValid() && lastValue.isValid());
|
||||||
QCOMPARE(model->setData(firstItem, lastValue), canSetData && lastValue.isValid());
|
QCOMPARE(model->setData(firstItem, lastValue), canSetData && lastValue.isValid());
|
||||||
|
Loading…
x
Reference in New Issue
Block a user