5#ifndef QRANGEMODEL_IMPL_H
6#define QRANGEMODEL_IMPL_H
11#error Do not include qrangemodel_impl.h directly
15#pragma qt_sync_skip_header_check
16#pragma qt_sync_stop_processing
19#include <QtCore/qabstractitemmodel.h>
20#include <QtCore/qquasivirtual_impl.h>
21#include <QtCore/qmetaobject.h>
22#include <QtCore/qvariant.h>
23#include <QtCore/qmap.h>
24#include <QtCore/qscopedvaluerollback.h>
25#include <QtCore/qset.h>
26#include <QtCore/qvarlengtharray.h>
32#include <QtCore/qxptype_traits.h>
34#include <QtCore/q23utility.h>
40 template <
typename T,
template <
typename...>
typename... Templates>
43 template <
template <
typename...>
typename Template,
45 template <
typename...>
typename...
Templates>
49 template <
typename...>
typename Template,
50 template <
typename...>
typename...
Templates>
53 template <
typename T,
template <
typename...>
typename...
Templates>
56 template <
typename T,
typename =
void>
63 template <
typename T,
typename =
void>
80#ifndef QT_NO_SCOPED_POINTER
96 using Type = q20::remove_cvref_t<T>;
97 if constexpr (is_any_of<Type, std::optional>())
98 return t ?
std::addressof(*
std::forward<T>(t)) :
nullptr;
99 else if constexpr (std::is_pointer<Type>())
101 else if constexpr (is_smart_ptr<Type>())
103 else if constexpr (is_any_of<Type, std::reference_wrapper>())
104 return std::addressof(t.get());
106 return std::addressof(
std::forward<T>(t));
109 template <
typename T>
119 template <
typename T>
122 template <
typename T>
127 template <
typename T,
typename =
void>
131 template <
typename T>
134 template <
typename T>
137 template <
typename T,
typename =
void>
143 template <
typename T>
146 template <
typename T,
typename =
void>
148 template <
typename T>
151 template <
typename T>
154 template <
typename T>
155 static constexpr bool isValid(
const T &t)
noexcept
157 if constexpr (
std::is_array_v<T>)
159 else if constexpr (is_validatable<T>())
165 template <
typename T>
166 static decltype(
auto)
refTo(T&& t) {
169 using Type = q20::remove_cvref_t<T>;
170 if constexpr (is_any_of<T, std::optional>())
171 return *
std::forward<T>(t);
172 if constexpr (!is_wrapped<Type>() || is_any_unique_ptr<Type>())
173 return q23::forward_like<T>(*QRangeModelDetails::pointerTo(t));
178 template <
typename It>
179 auto key(It&& it) ->
decltype(it.key()) {
return std::forward<It>(it).key(); }
180 template <
typename It>
181 auto key(It&& it) ->
decltype((it->first)) {
return std::forward<It>(it)->first; }
183 template <
typename It>
184 auto value(It&& it) ->
decltype(it.value()) {
return std::forward<It>(it).value(); }
185 template <
typename It>
186 auto value(It&& it) ->
decltype((it->second)) {
return std::forward<It>(it)->second; }
192 template <
typename C>
195 template <
typename C>
198 template <
typename C>
199 static auto pos(C &&c,
int i)
207 template <
typename C,
typename =
void>
210 template <
typename C>
221 template <
typename C,
typename =
void>
224 template <
typename C>
233 template <
typename C,
typename =
void>
236 template <
typename C>
244 template <
typename C,
typename =
void>
247 template <
typename C>
258 template <
typename It>
260 std::is_swappable<
decltype(*
std::declval<It>())>,
261 std::is_base_of<
std::forward_iterator_tag,
265 template <
typename C,
typename =
void>
268 template <
typename C>
278 template <
typename C>
279 static void rotate(C& c,
int src,
int count,
int dst) {
281 using Container = std::remove_reference_t<
decltype(container)>;
284 const auto srcEnd =
std::next(srcBegin, count);
287 if constexpr (test_splice<Container>::value) {
288 if (dst > src && dst < src + count)
289 container.splice(srcBegin, container, dstBegin, srcEnd);
291 container.splice(dstBegin, container, srcBegin, srcEnd);
294 std::rotate(srcBegin, srcEnd, dstBegin);
296 std::rotate(dstBegin, srcBegin, srcEnd);
309 template <
typename C>
318 template <
typename C>
323 template <
typename C,
typename =
void>
325 template <
typename C>
328 template <
typename C,
typename =
void>
330 template <
typename C>
335 template <
typename C,
typename =
void>
346 template <
typename C>
387 template <
typename C>
389 template <
typename C>
396 template <
typename T,
typename =
void>
402 template <
typename T>
414 template <
typename T,
typename =
void>
417 template <
typename T>
430 "The return type of the ItemAccess::writeRole implementation "
431 "needs to be convertible to a bool!");
434 "The return type of the ItemAccess::readRole implementation "
435 "needs to be convertible to QVariant!");
441 template <
typename T,
typename =
void>
457 template <
typename Row,
typename Fn>
463 int columnIndex = -1;
466 return std::forward<Fn>(fn)(firstIndex.siblingAtColumn(++columnIndex),
474 template <
typename T>
494 template <
typename C,
typename F>
529 template <
typename Row,
typename Fn>
549 template <
typename C,
typename F>
561 template <
typename Row,
typename Fn>
577 template <
typename T>
612 template <
typename Row,
typename Fn>
619 template <
typename T,
typename =
void>
622 template <
typename That>
625 return That::roleNamesForSimpleType();
632 template <
typename That>
639 template <
typename T>
645 template <
typename T>
648 template <
typename That>
655 template <
typename T>
659 template <
typename Range>
665 auto newRow() ->
decltype(R{}) {
return R{}; }
668 template <
typename Range>
696 template <
typename Range,
704 template <
typename Range>
707 template <
typename R >
708 auto parentRow(
const R& row)
const ->
decltype(row.parentRow())
710 return row.parentRow();
713 template <
typename R >
714 auto setParentRow(R &row, R* parent) ->
decltype(row.setParentRow(parent))
716 row.setParentRow(parent);
719 template <
typename R >
720 auto childRows(
const R &row)
const ->
decltype(row.childRows())
722 return row.childRows();
725 template <
typename R >
728 return row.childRows();
732 template <
typename P,
typename R>
735 template <
typename P,
typename R>
738 template <
typename P,
typename R>
741 template <
typename P,
typename R>
744 template <
typename P,
typename R>
748 template <
typename P,
typename R>
751 template <
typename P,
typename R>
754 template <
typename P,
typename R>
757 template <
typename P,
typename =
void>
759 template <
typename P>
763 template <
typename P,
typename R,
typename =
void>
765 template <
typename P,
typename R>
770 template <
typename Range,
782 template <
typename Range>
795 template <
typename Range,
typename Protocol>
814 template <
bool cacheProperties,
bool itemsAreQObjects>
842 return lhs.sender == rhs.sender && lhs
.role == rhs
.role;
846 return qHashMulti(seed, c.sender, c
.role);
862 template <
typename ModelStorage,
typename =
void>
881 template <
typename ModelStorage,
typename ItemType>
893 template <
typename Model = ModelStorage>
912 template <
typename StaticContainer,
typename F>
915 using type = std::remove_cv_t<QRangeModelDetails::wrapped_t<StaticContainer>>;
918 QRangeModelDetails::row_traits<type>::for_element_at(ref, idx, std::forward<F>(function));
932 bool setHeaderData(
int section, Qt::Orientation orientation,
const QVariant &data,
int role);
933 bool setData(
const QModelIndex &index,
const QVariant &data,
int role);
934 bool setItemData(
const QModelIndex &index,
const QMap<
int, QVariant> &data);
938 bool moveColumns(
const QModelIndex &sourceParent,
int sourceColumn,
int count,
const QModelIndex &destParent,
int destColumn);
939 bool insertRows(
int row,
int count,
const QModelIndex &parent);
940 bool removeRows(
int row,
int count,
const QModelIndex &parent);
941 bool moveRows(
const QModelIndex &sourceParent,
int sourceRow,
int count,
const QModelIndex &destParent,
int destRow);
954 void multiData(
const QModelIndex &index, QModelRoleDataSpan roleDataSpan)
const;
986 template <
typename C>
1018 friend class QRangeModelPrivate;
1021 QRangeModel *m_rangeModel;
1025 : m_rangeModel(itemModel)
1030 inline void dataChanged(
const QModelIndex &from,
const QModelIndex &to,
1031 const QList<
int> &roles);
1038 inline bool beginMoveColumns(
const QModelIndex &sourceParent,
int sourceFirst,
int sourceLast,
1039 const QModelIndex &destParent,
int destRow);
1041 inline void beginInsertRows(
const QModelIndex &parent,
int start,
int count);
1043 inline void beginRemoveRows(
const QModelIndex &parent,
int start,
int count);
1045 inline bool beginMoveRows(
const QModelIndex &sourceParent,
int sourceFirst,
int sourceLast,
1046 const QModelIndex &destParent,
int destRow);
1065 int role,
const QMetaProperty &property);
1067 int role,
const QMetaProperty &property);
1069 const QHash<
int, QMetaProperty> &properties);
1071 const QHash<
int, QMetaProperty> &properties);
1074template <
typename Structure,
typename Range,
1075 typename Protocol = QRangeModelDetails::table_protocol_t<Range>>
1104 "Currently, std::optional is not supported for ranges and rows, as "
1105 "it has range semantics in c++26. Once the required behavior is clarified, "
1106 "std::optional for ranges and rows will be supported.");
1113 Structure&
that() {
return static_cast<Structure &>(*
this); }
1114 const Structure&
that()
const {
return static_cast<
const Structure &>(*
this); }
1116 template <
typename C>
1117 static constexpr int size(
const C &c)
1122 if constexpr (QRangeModelDetails::test_size<C>()) {
1124 return int(size(c));
1126#if defined(__cpp_lib_ranges)
1127 using std::ranges::distance;
1129 using std::distance;
1131 using container_type = std::conditional_t<QRangeModelDetails::range_traits<C>::has_cbegin,
1132 const QRangeModelDetails::wrapped_t<C>,
1133 QRangeModelDetails::wrapped_t<C>>;
1134 container_type& container =
const_cast<container_type &>(
QRangeModelDetails::refTo(c));
1152 return this->blockDataChangedDispatch();
1162 template <
typename T>
1182 {
return lhs.n == rhs.n; }
1184 {
return !(lhs == rhs); }
1195 "The range holding a move-only row-type must support insert(pos, start, end)");
1202 return range_features::is_mutable && row_features::is_mutable
1203 && std::is_reference_v<row_reference>
1204 && Structure::is_mutable_impl;
1227 if (row < 0 || column < 0 || column >= columnCount(parent)
1228 || row >= rowCount(parent)) {
1232 return that().indexImpl(row, column, parent);
1237 if (row == index.row() && column == index.column())
1240 if (column < 0 || column >=
this->columnCount({}))
1243 if (row == index.row())
1244 return this->createIndex(row, column, index.constInternalPointer());
1246 const_row_ptr parentRow =
static_cast<const_row_ptr>(index.constInternalPointer());
1247 const auto siblingCount = size(that().childrenOf(parentRow));
1248 if (row < 0 || row >=
int(siblingCount))
1250 return this->createIndex(row, column, parentRow);
1255 if (!index.isValid())
1256 return Qt::NoItemFlags;
1258 Qt::ItemFlags f = Structure::defaultFlags();
1260 if constexpr (isMutable()) {
1261 if constexpr (row_traits::hasMetaObject) {
1262 if (index.column() < row_traits::fixed_size()) {
1263 const QMetaObject mo = wrapped_row_type::staticMetaObject;
1264 const QMetaProperty prop = mo.property(index.column() + mo.propertyOffset());
1265 if (prop.isWritable())
1266 f |= Qt::ItemIsEditable;
1269 f |= Qt::ItemIsEditable;
1270 }
else if constexpr (std::is_reference_v<row_reference> && !std::is_const_v<row_reference>) {
1273 const_row_reference row = rowData(index);
1274 row_reference mutableRow =
const_cast<row_reference>(row);
1277 using target_type =
decltype(ref);
1278 if constexpr (std::is_const_v<std::remove_reference_t<target_type>>)
1279 f &= ~Qt::ItemIsEditable;
1280 else if constexpr (std::is_lvalue_reference_v<target_type>)
1281 f |= Qt::ItemIsEditable;
1286 f &= ~Qt::ItemIsEditable;
1296 if (role != Qt::DisplayRole || orientation != Qt::Horizontal
1297 || section < 0 || section >= columnCount({})) {
1298 return this->itemModel().QAbstractItemModel::headerData(section, orientation, role);
1301 result = row_traits::column_name(section);
1302 if (!result.isValid())
1303 result =
this->itemModel().QAbstractItemModel::headerData(section, orientation, role);
1309 if (!index.isValid())
1312 QModelRoleData result(role);
1313 multiData(index, result);
1314 return std::move(result.data());
1319 return role == Qt::RangeModelDataRole
1320 || role == Qt::RangeModelAdapterRole;
1325 return role == Qt::DisplayRole || role == Qt::EditRole;
1330 QMap<
int, QVariant> result;
1332 if (index.isValid()) {
1336 readAt(index, [&result, &tried](
const auto &value) {
1337 if constexpr (std::is_convertible_v<
decltype(value),
decltype(result)>) {
1343 const auto roles =
this->itemModel().roleNames().keys();
1344 QVarLengthArray<QModelRoleData, 16> roleDataArray;
1345 roleDataArray.reserve(roles.size());
1346 for (
auto role : roles) {
1347 if (isRangeModelRole(role))
1349 roleDataArray.emplace_back(role);
1351 QModelRoleDataSpan roleDataSpan(roleDataArray);
1352 multiData(index, roleDataSpan);
1354 for (
auto &&roleData : std::move(roleDataSpan)) {
1355 QVariant data = roleData.data();
1357 result[roleData.role()] = std::move(data);
1364 void multiData(
const QModelIndex &index, QModelRoleDataSpan roleDataSpan)
const
1367 readAt(index, [
this, &index, roleDataSpan, &tried](
const auto &value) {
1370 using value_type = q20::remove_cvref_t<
decltype(value)>;
1371 using multi_role = QRangeModelDetails::is_multi_role<value_type>;
1372 using wrapped_value_type = QRangeModelDetails::wrapped_t<value_type>;
1374 const auto readModelData = [&value](QModelRoleData &roleData){
1375 const int role = roleData.role();
1376 if (role == Qt::RangeModelDataRole) {
1380 if constexpr (std::is_copy_assignable_v<wrapped_value_type>)
1381 roleData.setData(QVariant::fromValue(QRangeModelDetails::refTo(value)));
1383 roleData.setData(QVariant::fromValue(QRangeModelDetails::pointerTo(value)));
1384 }
else if (role == Qt::RangeModelAdapterRole) {
1386 if constexpr (std::is_copy_assignable_v<value_type>)
1387 roleData.setData(QVariant::fromValue(value));
1389 roleData.setData(QVariant::fromValue(QRangeModelDetails::pointerTo(value)));
1396 if constexpr (QRangeModelDetails::item_access<wrapped_value_type>()) {
1397 using ItemAccess = QRangeModelDetails::QRangeModelItemAccess<wrapped_value_type>;
1399 for (
auto &roleData : roleDataSpan) {
1400 if (!readModelData(roleData))
1401 roleData.setData(ItemAccess::readRole(value, roleData.role()));
1403 }
else if constexpr (multi_role()) {
1405 const auto roleNames = [
this]() -> QHash<
int, QByteArray> {
1407 if constexpr (!multi_role::int_key)
1408 return this->itemModel().roleNames();
1412 using key_type =
typename value_type::key_type;
1413 for (
auto &roleData : roleDataSpan) {
1414 const auto &it = [&roleNames, &value, role = roleData.role()]{
1415 Q_UNUSED(roleNames);
1416 if constexpr (multi_role::int_key)
1417 return value.find(key_type(role));
1419 return value.find(roleNames.value(role));
1421 if (it != QRangeModelDetails::adl_end(value))
1422 roleData.setData(QRangeModelDetails::value(it));
1424 roleData.clearData();
1426 }
else if constexpr (has_metaobject<value_type>) {
1427 if (row_traits::fixed_size() <= 1) {
1429 for (
auto &roleData : roleDataSpan) {
1430 if (!readModelData(roleData)) {
1431 roleData.setData(readRole(index, roleData.role(),
1432 QRangeModelDetails::pointerTo(value)));
1435 }
else if (index.column() <= row_traits::fixed_size()) {
1437 for (
auto &roleData : roleDataSpan) {
1438 const int role = roleData.role();
1439 if (isPrimaryRole(role)) {
1440 roleData.setData(readProperty(index.column(),
1441 QRangeModelDetails::pointerTo(value)));
1443 roleData.clearData();
1449 for (
auto &roleData : roleDataSpan) {
1450 const int role = roleData.role();
1451 if (isPrimaryRole(role) || isRangeModelRole(role))
1452 roleData.setData(read(value));
1454 roleData.clearData();
1462 bool setData(
const QModelIndex &index,
const QVariant &data,
int role)
1464 if (!index.isValid())
1467 bool success =
false;
1468 if constexpr (isMutable()) {
1469 auto emitDataChanged = qScopeGuard([&success,
this, &index, role]{
1471 Q_EMIT
this->dataChanged(index, index,
1472 role == Qt::EditRole || role == Qt::RangeModelDataRole
1473 || role == Qt::RangeModelAdapterRole
1474 ? QList<
int>{} : QList<
int>{role});
1480 const auto writeData = [
this, column = index.column(), &data, role](
auto &&target) ->
bool {
1481 using value_type = q20::remove_cvref_t<
decltype(target)>;
1482 using wrapped_value_type = QRangeModelDetails::wrapped_t<value_type>;
1483 using multi_role = QRangeModelDetails::is_multi_role<value_type>;
1485 auto setRangeModelDataRole = [&target, &data]{
1486 constexpr auto targetMetaType = QMetaType::fromType<value_type>();
1487 const auto dataMetaType = data.metaType();
1488 constexpr bool isWrapped = QRangeModelDetails::is_wrapped<value_type>();
1489 if constexpr (!std::is_copy_assignable_v<wrapped_value_type>) {
1493 if constexpr (isWrapped) {
1494 constexpr bool is_raw_pointer = std::is_pointer_v<value_type>;
1495 if constexpr (!is_raw_pointer && std::is_copy_assignable_v<value_type>) {
1496 if (data.canConvert(targetMetaType)) {
1497 target = data.value<value_type>();
1500 }
else if constexpr (is_raw_pointer) {
1502 target = data.value<value_type>();
1511 }
else if constexpr (isWrapped) {
1516 if (
const auto mt = QMetaType::fromType<wrapped_value_type>();
1517 data.canConvert(mt)) {
1518 targetRef = data.value<wrapped_value_type>();
1520 }
else if (
const auto mtp = QMetaType::fromType<wrapped_value_type *>();
1521 data.canConvert(mtp)) {
1522 targetRef = *data.value<wrapped_value_type *>();
1526 }
else if (targetMetaType == dataMetaType) {
1527 QRangeModelDetails::refTo(target) = data.value<value_type>();
1529 }
else if (dataMetaType.flags() & QMetaType::PointerToGadget) {
1530 QRangeModelDetails::refTo(target) = *data.value<value_type *>();
1534 qCritical(
"Not able to assign %s to %s",
1535 qPrintable(QDebug::toString(data)), targetMetaType.name());
1540 if constexpr (QRangeModelDetails::item_access<wrapped_value_type>()) {
1541 using ItemAccess = QRangeModelDetails::QRangeModelItemAccess<wrapped_value_type>;
1542 if (isRangeModelRole(role))
1543 return setRangeModelDataRole();
1544 return ItemAccess::writeRole(target, data, role);
1545 }
else if constexpr (has_metaobject<value_type>) {
1546 if (row_traits::fixed_size() <= 1) {
1547 if (isRangeModelRole(role))
1548 return setRangeModelDataRole();
1550 }
else if (column <= row_traits::fixed_size()
1551 && (isPrimaryRole(role) || isRangeModelRole(role))) {
1554 }
else if constexpr (multi_role::value) {
1555 Qt::ItemDataRole roleToSet = Qt::ItemDataRole(role);
1558 const auto roleNames = [
this]() -> QHash<
int, QByteArray> {
1560 if constexpr (!multi_role::int_key)
1561 return this->itemModel().roleNames();
1565 if (role == Qt::EditRole) {
1566 if constexpr (multi_role::int_key) {
1567 if (target.find(roleToSet) == target.end())
1568 roleToSet = Qt::DisplayRole;
1570 if (target.find(roleNames.value(roleToSet)) == target.end())
1571 roleToSet = Qt::DisplayRole;
1574 if constexpr (multi_role::int_key)
1575 return write(target[roleToSet], data);
1577 return write(target[roleNames.value(roleToSet)], data);
1578 }
else if (isPrimaryRole(role) || isRangeModelRole(role)) {
1579 return write(target, data);
1584 success = writeAt(index, writeData);
1587 if (success && isRangeModelRole(role) &&
this->autoConnectPolicy() == AutoConnectPolicy::Full) {
1588 if (QObject *item = data.value<QObject *>())
1589 Self::connectProperties(index, item, m_data.context, m_data.properties);
1596 template <
typename LHS,
typename RHS>
1599 if constexpr (
std::is_pointer_v<RHS>) {
1603 if constexpr (
std::is_assignable_v<LHS, RHS>)
1604 org =
std::forward<RHS>(copy);
1609 template <
typename LHS,
typename RHS>
1612 updateTarget(*org,
std::forward<RHS>(copy));
1615 bool setItemData(
const QModelIndex &index,
const QMap<
int, QVariant> &data)
1617 if (!index.isValid() || data.isEmpty())
1620 bool success =
false;
1621 if constexpr (isMutable()) {
1622 auto emitDataChanged = qScopeGuard([&success,
this, &index, &data]{
1624 Q_EMIT
this->dataChanged(index, index, data.keys());
1630 auto writeItemData = [
this, &tried, &data](
auto &target) ->
bool {
1632 using value_type = q20::remove_cvref_t<
decltype(target)>;
1633 using multi_role = QRangeModelDetails::is_multi_role<value_type>;
1634 using wrapped_value_type = QRangeModelDetails::wrapped_t<value_type>;
1638 auto makeCopy = [](
const value_type &original){
1639 if constexpr (!std::is_copy_assignable_v<wrapped_value_type>)
1641 else if constexpr (std::is_pointer_v<
decltype(original)>)
1643 else if constexpr (std::is_copy_assignable_v<value_type>)
1649 const auto roleNames =
this->itemModel().roleNames();
1651 if constexpr (QRangeModelDetails::item_access<wrapped_value_type>()) {
1653 using ItemAccess = QRangeModelDetails::QRangeModelItemAccess<wrapped_value_type>;
1654 const auto roles = roleNames.keys();
1655 auto targetCopy = makeCopy(target);
1656 for (
int role : roles) {
1657 if (!ItemAccess::writeRole(QRangeModelDetails::refTo(targetCopy),
1658 data.value(role), role)) {
1662 updateTarget(target,
std::move(targetCopy));
1664 }
else if constexpr (multi_role()) {
1665 using key_type =
typename value_type::key_type;
1667 const auto roleName = [&roleNames](
int role) {
1668 return roleNames.value(role);
1673 if constexpr (!multi_role::int_key)
1675 auto invalid =
std::find_if(data.keyBegin(), data.keyEnd(),
1676 [&roleName](
int role) {
return roleName(role).isEmpty(); }
1679 if (invalid != data.keyEnd()) {
1681 qWarning(
"No role name set for %d", *invalid);
1687 for (
auto &&[role, value] : data.asKeyValueRange()) {
1688 if constexpr (multi_role::int_key)
1689 target[
static_cast<key_type>(role)] = value;
1691 target[QString::fromUtf8(roleName(role))] = value;
1694 }
else if constexpr (has_metaobject<value_type>) {
1695 if (row_traits::fixed_size() <= 1) {
1697 auto targetCopy = makeCopy(target);
1698 for (
auto &&[role, value] : data.asKeyValueRange()) {
1699 if (isRangeModelRole(role))
1701 if (!writeRole(role, QRangeModelDetails::pointerTo(targetCopy), value)) {
1702 const QByteArray roleName = roleNames.value(role);
1704 qWarning(
"Failed to write value '%s' to role '%s'",
1705 qPrintable(QDebug::toString(value)), roleName.data());
1710 updateTarget(target,
std::move(targetCopy));
1717 success = writeAt(index, writeItemData);
1722 emitDataChanged.dismiss();
1723 success =
this->itemModel().QAbstractItemModel::setItemData(index, data);
1731 if (!index.isValid())
1734 bool success =
false;
1735 if constexpr (isMutable()) {
1736 auto emitDataChanged = qScopeGuard([&success,
this, &index]{
1738 Q_EMIT
this->dataChanged(index, index, {});
1741 auto clearData = [column = index.column()](
auto &&target) {
1742 if constexpr (row_traits::hasMetaObject) {
1743 if (row_traits::fixed_size() <= 1) {
1746 }
else if (column <= row_traits::fixed_size()) {
1756 success = writeAt(index, clearData);
1764 using item_type = QRangeModelDetails::wrapped_t<
typename row_traits::item_type>;
1765 using item_traits =
typename QRangeModelDetails::item_traits<item_type>;
1766 return item_traits::roleNames(
this);
1773 return row_traits::for_each_element(row,
this->itemModel().index(rowIndex, 0, parent),
1774 [
this](
const QModelIndex &index, QObject *item) {
1775 if constexpr (isMutable())
1776 return Self::connectProperties(index, item, m_data.context, m_data.properties);
1778 return Self::connectPropertiesConst(index, item, m_data.context, m_data.properties);
1786 row_traits::for_each_element(row,
this->itemModel().index(rowIndex, 0, parent),
1787 [
this](
const QModelIndex &, QObject *item) {
1788 m_data.connections.removeIf([item](
const auto &connection) {
1789 return connection.sender == item;
1799 using item_type = std::remove_pointer_t<
typename row_traits::item_type>;
1801 delete m_data.context;
1802 m_data.connections = {};
1803 switch (
this->autoConnectPolicy()) {
1804 case AutoConnectPolicy::None:
1805 m_data.context =
nullptr;
1807 case AutoConnectPolicy::Full:
1808 m_data.context =
new QObject(&
this->itemModel());
1809 m_data.properties = QRangeModelImplBase::roleProperties(
this->itemModel(),
1810 item_type::staticMetaObject);
1811 if (!m_data.properties.isEmpty())
1812 that().autoConnectPropertiesImpl();
1814 case AutoConnectPolicy::OnRead:
1815 m_data.context =
new QObject(&
this->itemModel());
1820 qWarning(
"All items in the range must be QObject subclasses");
1825 template <
typename InsertFn>
1830 range_type *
const children = childRange(parent);
1834 this->beginInsertColumns(parent, column, column + count - 1);
1836 for (
auto &child : *children) {
1837 auto it = QRangeModelDetails::pos(child, column);
1838 (
void)insertFn(QRangeModelDetails::refTo(child), it, count);
1841 this->endInsertColumns();
1847 if (m_data.context &&
this->autoConnectPolicy() == AutoConnectPolicy::Full) {
1848 for (
int r = 0; r < that().rowCount(parent); ++r) {
1849 for (
int c = column; c < column + count; ++c) {
1850 const QModelIndex index = that().index(r, c, parent);
1851 writeAt(index, [
this, &index](QObject *item){
1852 return Self::connectProperties(index, item,
1853 m_data.context, m_data.properties);
1865 if constexpr (dynamicColumns() && isMutable() && row_features::has_insert) {
1866 return doInsertColumns(column, count, parent, [](
auto &row,
auto it,
int n){
1867 row.insert(it, n, {});
1877 if constexpr (dynamicColumns() && isMutable() && row_features::has_erase) {
1878 if (column < 0 || column + count > columnCount(parent))
1881 range_type *
const children = childRange(parent);
1886 if (m_data.context &&
this->autoConnectPolicy() == AutoConnectPolicy::OnRead) {
1887 for (
int r = 0; r < that().rowCount(parent); ++r) {
1888 for (
int c = column; c < column + count; ++c) {
1889 const QModelIndex index = that().index(r, c, parent);
1890 writeAt(index, [
this](QObject *item){
1891 m_data.connections.removeIf([item](
const auto &connection) {
1892 return connection.sender == item;
1901 this->beginRemoveColumns(parent, column, column + count - 1);
1902 for (
auto &child : *children) {
1903 const auto start = QRangeModelDetails::pos(child, column);
1904 QRangeModelDetails::refTo(child).erase(start, std::next(start, count));
1906 this->endRemoveColumns();
1912 bool moveColumns(
const QModelIndex &sourceParent,
int sourceColumn,
int count,
1913 const QModelIndex &destParent,
int destColumn)
1916 if (sourceParent != destParent)
1918 if constexpr (isMutable() && (row_features::has_rotate || row_features::has_splice)) {
1919 if (!Structure::canMoveColumns(sourceParent, destParent))
1925 range_type *
const children = childRange(sourceParent);
1929 if (!
this->beginMoveColumns(sourceParent, sourceColumn, sourceColumn + count - 1,
1930 destParent, destColumn)) {
1934 for (
auto &child : *children)
1935 QRangeModelDetails::rotate(child, sourceColumn, count, destColumn);
1937 this->endMoveColumns();
1944 template <
typename InsertFn>
1945 bool doInsertRows(
int row,
int count,
const QModelIndex &parent, InsertFn &&insertFn)
1947 range_type *children = childRange(parent);
1951 this->beginInsertRows(parent, row, row + count - 1);
1953 row_ptr parentRow = parent.isValid()
1956 (
void)
std::forward<InsertFn>(insertFn)(*children, parentRow, row, count);
1960 that().resetParentInChildren(children);
1962 this->endInsertRows();
1968 if (m_data.context &&
this->autoConnectPolicy() == AutoConnectPolicy::Full) {
1970 const auto end =
std::next(begin, count);
1972 for (
auto it = begin; it != end; ++it, ++rowIndex)
1973 autoConnectPropertiesInRow(*it, rowIndex, parent);
1983 return doInsertRows(row, count, parent,
1984 [
this](range_type &children, row_ptr parentRow,
int r,
int n){
1988 if constexpr (range_features::has_insert_range) {
1991 auto start = children.insert(pos, n,
nullptr);
1994 children.insert(pos, n,
std::move(*generator));
2003 bool removeRows(
int row,
int count,
const QModelIndex &parent = {})
2006 const int prevRowCount = rowCount(parent);
2007 if (row < 0 || row + count > prevRowCount)
2010 range_type *children = childRange(parent);
2015 if (m_data.context &&
this->autoConnectPolicy() == AutoConnectPolicy::OnRead) {
2017 const auto end =
std::next(begin, count);
2019 for (
auto it = begin; it != end; ++it, ++rowIndex)
2020 clearConnectionInRow(*it, rowIndex, parent);
2024 this->beginRemoveRows(parent, row, row + count - 1);
2025 [[maybe_unused]]
bool callEndRemoveColumns =
false;
2029 if (prevRowCount == count) {
2030 if (
const int columns = columnCount(parent)) {
2031 callEndRemoveColumns =
true;
2032 this->beginRemoveColumns(parent, 0, columns - 1);
2038 const auto end =
std::next(begin, count);
2039 that().deleteRemovedRows(begin, end);
2040 children->erase(begin, end);
2044 that().resetParentInChildren(children);
2047 if (callEndRemoveColumns) {
2048 Q_ASSERT(columnCount(parent) == 0);
2049 this->endRemoveColumns();
2052 this->endRemoveRows();
2059 bool moveRows(
const QModelIndex &sourceParent,
int sourceRow,
int count,
2060 const QModelIndex &destParent,
int destRow)
2062 if constexpr (isMutable() && (range_features::has_rotate || range_features::has_splice)) {
2063 if (!Structure::canMoveRows(sourceParent, destParent))
2066 if (sourceParent != destParent) {
2067 return that().moveRowsAcross(sourceParent, sourceRow, count,
2068 destParent, destRow);
2071 if (sourceRow == destRow || sourceRow == destRow - 1 || count <= 0
2072 || sourceRow < 0 || sourceRow + count - 1 >=
this->rowCount(sourceParent)
2073 || destRow < 0 || destRow >
this->rowCount(destParent)) {
2077 range_type *source = childRange(sourceParent);
2079 if (!
this->beginMoveRows(sourceParent, sourceRow, sourceRow + count - 1, destParent, destRow))
2084 that().resetParentInChildren(source);
2086 this->endMoveRows();
2098 int rowCount(
const QModelIndex &parent)
const {
return that().rowCountImpl(parent); }
2103 return row_traits::fixed_size();
2107 int columnCount(
const QModelIndex &parent)
const {
return that().columnCountImpl(parent); }
2158 static constexpr bool modelCopied = !QRangeModelDetails::is_wrapped<Range>() &&
2159 (std::is_reference_v<Range> || std::is_const_v<std::remove_reference_t<Range>>);
2161 static constexpr bool modelShared = QRangeModelDetails::is_any_shared_ptr<Range>();
2163 static constexpr bool default_row_deleter = protocol_traits::is_default &&
2164 protocol_traits::has_deleteRow;
2166 static constexpr bool ambiguousRowOwnership = (modelCopied || modelShared) &&
2169 static_assert(!ambiguousRowOwnership,
2170 "Using of copied and shared tree and table models with rows as raw pointers, "
2171 "and the default protocol is not allowed due to ambiguity of rows ownership. "
2172 "Move the model in, use another row type, or implement a custom tree protocol.");
2174 if constexpr (protocol_traits::has_deleteRow && !std::is_pointer_v<Range>
2175 && !QRangeModelDetails::is_any_of<Range, std::reference_wrapper>()) {
2178 that().deleteRemovedRows(begin, end);
2184 if constexpr (dynamicColumns() && !row_features::has_resize) {
2188 }
else if constexpr (!protocol_traits::has_newRow) {
2191 }
else if constexpr (!range_features::has_insert_range
2192 && !std::is_copy_constructible_v<row_type>) {
2198 return Structure::canInsertRowsImpl();
2204 return Structure::canRemoveRowsImpl();
2207 template <
typename F>
2208 bool writeAt(
const QModelIndex &index, F&& writer)
2210 bool result =
false;
2211 row_reference row = rowData(index);
2214 result = writer(row);
2219 QRangeModelImplBase::for_element_at(row, index.column(), [&writer, &result](
auto &&target) {
2220 using target_type =
decltype(target);
2222 if constexpr (std::is_lvalue_reference_v<target_type>
2223 && !std::is_const_v<std::remove_reference_t<target_type>>) {
2224 result = writer(
std::forward<target_type>(target));
2233 template <
typename F>
2234 void readAt(
const QModelIndex &index, F&& reader)
const {
2235 const_row_reference row = rowData(index);
2246 template <
typename Value>
2249 if constexpr (std::is_constructible_v<QVariant, Value>)
2250 return QVariant(value);
2252 return QVariant::fromValue(value);
2254 template <
typename Value>
2258 if constexpr (std::is_constructible_v<QVariant, Value *>)
2259 return QVariant(value);
2261 return read(*value);
2266 template <
typename Target>
2267 static bool write(Target &target,
const QVariant &value)
2269 using Type = std::remove_reference_t<Target>;
2270 if constexpr (std::is_constructible_v<Target, QVariant>) {
2273 }
else if (value.canConvert<Type>()) {
2274 target = value.value<Type>();
2279 template <
typename Target>
2280 static bool write(Target *target,
const QVariant &value)
2283 return write(*target, value);
2287 template <
typename ItemType>
2291 operator QMetaProperty()
const {
2292 const QByteArray roleName = that.itemModel().roleNames().value(role);
2293 const QMetaObject &mo = ItemType::staticMetaObject;
2294 if (
const int index = mo.indexOfProperty(roleName.data());
2296 return mo.property(index);
2300 const QRangeModelImpl &that;
2302 } findProperty{*
this, role};
2304 if constexpr (ModelData::cachesProperties)
2305 return *m_data.properties.tryEmplace(role, findProperty).iterator;
2307 return findProperty;
2310 template <
typename ItemType>
2313 using item_type = std::remove_pointer_t<ItemType>;
2315 QMetaProperty prop = roleProperty<item_type>(role);
2316 if (!prop.isValid() && role == Qt::EditRole) {
2317 role = Qt::DisplayRole;
2318 prop = roleProperty<item_type>(Qt::DisplayRole);
2321 if (prop.isValid()) {
2323 const typename ModelData::Connection connection = {gadget, role};
2324 if (prop.hasNotifySignal() &&
this->autoConnectPolicy() == AutoConnectPolicy::OnRead
2325 && !m_data.connections.contains(connection)) {
2326 if constexpr (isMutable())
2327 Self::connectProperty(index, gadget, m_data.context, role, prop);
2329 Self::connectPropertyConst(index, gadget, m_data.context, role, prop);
2330 m_data.connections.insert(connection);
2333 result = readProperty(prop, gadget);
2338 template <
typename ItemType>
2341 return readRole(index, role, &gadget);
2344 template <
typename ItemType>
2347 if constexpr (std::is_base_of_v<QObject, ItemType>)
2348 return prop.read(gadget);
2350 return prop.readOnGadget(gadget);
2352 template <
typename ItemType>
2355 using item_type = std::remove_pointer_t<ItemType>;
2356 const QMetaObject &mo = item_type::staticMetaObject;
2357 const QMetaProperty prop = mo.property(property + mo.propertyOffset());
2358 return readProperty(prop, gadget);
2361 template <
typename ItemType>
2364 return readProperty(property, &gadget);
2367 template <
typename ItemType>
2368 bool writeRole(
int role, ItemType *gadget,
const QVariant &data)
2370 using item_type = std::remove_pointer_t<ItemType>;
2371 auto prop = roleProperty<item_type>(role);
2372 if (!prop.isValid() && role == Qt::EditRole)
2373 prop = roleProperty<item_type>(Qt::DisplayRole);
2375 return prop.isValid() ? writeProperty(prop, gadget, data) :
false;
2378 template <
typename ItemType>
2379 bool writeRole(
int role, ItemType &&gadget,
const QVariant &data)
2381 return writeRole(role, &gadget, data);
2384 template <
typename ItemType>
2385 static bool writeProperty(
const QMetaProperty &prop, ItemType *gadget,
const QVariant &data)
2387 if constexpr (std::is_base_of_v<QObject, ItemType>)
2388 return prop.write(gadget, data);
2390 return prop.writeOnGadget(gadget, data);
2392 template <
typename ItemType>
2395 using item_type = std::remove_pointer_t<ItemType>;
2396 const QMetaObject &mo = item_type::staticMetaObject;
2397 return writeProperty(mo.property(property + mo.propertyOffset()), gadget, data);
2400 template <
typename ItemType>
2401 static bool writeProperty(
int property, ItemType &&gadget,
const QVariant &data)
2403 return writeProperty(property, &gadget, data);
2406 template <
typename ItemType>
2409 using item_type = std::remove_pointer_t<ItemType>;
2410 const QMetaObject &mo = item_type::staticMetaObject;
2411 bool success =
true;
2412 if (property == -1) {
2414 if constexpr (std::is_base_of_v<QObject, item_type>) {
2415 for (
int p = mo.propertyOffset(); p < mo.propertyCount(); ++p)
2416 success = writeProperty(mo.property(p), object, {}) && success;
2421 success = writeProperty(mo.property(property + mo.propertyOffset()), object, {});
2426 template <
typename ItemType>
2429 return resetProperty(property, &object);
2435 Q_ASSERT(index.isValid());
2436 return that().rowDataImpl(index);
2441 Q_ASSERT(index.isValid());
2442 return that().rowDataImpl(index);
2447 if (!index.isValid())
2448 return m_data.model();
2451 return that().childRangeImpl(index);
2456 if (!index.isValid())
2457 return m_data.model();
2460 return that().childRangeImpl(index);
2471template <
typename Range,
typename Protocol>
2478 using range_type =
typename Base::range_type;
2479 using range_features =
typename Base::range_features;
2480 using row_type =
typename Base::row_type;
2481 using row_ptr =
typename Base::row_ptr;
2482 using const_row_ptr =
typename Base::const_row_ptr;
2484 using tree_traits =
typename Base::protocol_traits;
2485 static constexpr bool is_mutable_impl = tree_traits::has_mutable_childRows;
2487 static constexpr bool rows_are_any_refs_or_pointers = Base::rows_are_raw_pointers ||
2488 QRangeModelDetails::is_smart_ptr<row_type>() ||
2489 QRangeModelDetails::is_any_of<row_type,
std::reference_wrapper>();
2490 static_assert(!Base::dynamicColumns(),
"A tree must have a static number of columns!");
2494 : Base(
std::forward<Range>(model),
std::forward<Protocol>(p), itemModel)
2499 for (
auto &&child : children)
2511 auto *children =
this->childRange(parent);
2514 return autoConnectPropertiesRange(QRangeModelDetails::refTo(children), parent);
2520 if (!parent.isValid())
2521 return this->createIndex(row, column);
2523 if (parent.column())
2524 return QModelIndex();
2526 const_row_ptr grandParent =
static_cast<const_row_ptr>(parent.constInternalPointer());
2527 const auto &parentSiblings = childrenOf(grandParent);
2534 if (!child.isValid())
2538 const_row_ptr parentRow =
static_cast<const_row_ptr>(child.constInternalPointer());
2543 auto &&grandParent =
this->protocol().parentRow(
QRangeModelDetails::refTo(parentRow));
2544 const range_type &parentSiblings = childrenOf(
QRangeModelDetails::pointerTo(grandParent));
2548 const auto it =
std::find_if(begin, end, [parentRow](
auto &&s){
2552 return this->createIndex(
std::distance(begin, it), 0,
2559 return Base::size(
this->childRange(parent));
2566 return Base::fixedColumnCount();
2571 return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
2579 return (rows_are_any_refs_or_pointers || tree_traits::has_setParentRow)
2580 && Base::dynamicRows() && range_features::has_insert;
2588 return (rows_are_any_refs_or_pointers || tree_traits::has_setParentRow)
2589 && Base::dynamicRows() && range_features::has_erase;
2597 static constexpr bool canMoveRows(
const QModelIndex &,
const QModelIndex &)
2603 const QModelIndex &destParent,
int destRow)
2608 if constexpr (!rows_are_any_refs_or_pointers && !tree_traits::has_setParentRow) {
2610 }
else if constexpr (!(range_features::has_insert && range_features::has_erase)) {
2612 }
else if (!
this->beginMoveRows(sourceParent, sourceRow, sourceRow + count - 1,
2613 destParent, destRow)) {
2617 range_type *source =
this->childRange(sourceParent);
2618 range_type *destination =
this->childRange(destParent);
2623 if constexpr (range_features::has_insert_range) {
2625 const auto sourceEnd =
std::next(sourceStart, count);
2627 destination->insert(destStart,
std::move_iterator(sourceStart),
2628 std::move_iterator(sourceEnd));
2629 }
else if constexpr (
std::is_copy_constructible_v<row_type>) {
2631 destination->insert(destStart, count, row_type{});
2634 row_ptr parentRow = destParent.isValid()
2640 if (parentRow ==
static_cast<row_ptr>(sourceParent.internalPointer())) {
2641 if (sourceParent.row() < destRow) {
2642 source =
this->childRange(sourceParent);
2645 source =
this->childRange(
this->createIndex(sourceParent.row() + count, 0,
2646 sourceParent.internalPointer()));
2653 const auto writeEnd =
std::next(writeStart, count);
2655 const auto sourceEnd =
std::next(sourceStart, count);
2657 for (
auto write = writeStart, read = sourceStart; write != writeEnd; ++write, ++read) {
2660 if constexpr (!range_features::has_insert_range)
2661 *write =
std::move(*read);
2665 source->erase(sourceStart, sourceEnd);
2675 this->endMoveRows();
2683 static_assert(tree_traits::has_setParentRow);
2684 row_type empty_row =
this->protocol().newRow();
2690 template <
typename It,
typename Sentinel>
2693 if constexpr (tree_traits::has_deleteRow) {
2694 for (
auto it = begin; it != end; ++it) {
2695 if constexpr (Base::isMutable()) {
2696 decltype(
auto) children =
this->protocol().childRows(
QRangeModelDetails::refTo(*it));
2704 this->protocol().deleteRow(
std::move(*it));
2711 if constexpr (tree_traits::has_setParentRow && !rows_are_any_refs_or_pointers) {
2714 for (
auto it = begin; it != end; ++it) {
2715 decltype(
auto) maybeChildren =
this->protocol().childRows(*it);
2718 QModelIndexList fromIndexes;
2719 QModelIndexList toIndexes;
2720 fromIndexes.reserve(Base::size(childrenRef));
2721 toIndexes.reserve(Base::size(childrenRef));
2725 for (
auto &child : childrenRef) {
2726 const_row_ptr oldParent =
this->protocol().parentRow(child);
2727 if (oldParent != parentRow) {
2728 fromIndexes.append(
this->createIndex(row, 0, oldParent));
2729 toIndexes.append(
this->createIndex(row, 0, parentRow));
2730 this->protocol().setParentRow(child, parentRow);
2734 this->changePersistentIndexList(fromIndexes, toIndexes);
2744 for (
const auto &row : range) {
2745 if (!
this->autoConnectPropertiesInRow(row, rowIndex, parent))
2750 if (!autoConnectPropertiesRange(QRangeModelDetails::refTo(children),
2751 this->itemModel().index(rowIndex, 0, parent))) {
2762 return autoConnectPropertiesRange(*
this->m_data.model(), {});
2767 const_row_ptr parentRow =
static_cast<const_row_ptr>(index.constInternalPointer());
2768 const range_type &siblings = childrenOf(parentRow);
2769 Q_ASSERT(index.row() <
int(Base::size(siblings)));
2775 row_ptr parentRow =
static_cast<row_ptr>(index.internalPointer());
2776 range_type &siblings = childrenOf(parentRow);
2777 Q_ASSERT(index.row() <
int(Base::size(siblings)));
2783 const auto &row =
this->rowData(index);
2785 return static_cast<
const range_type *>(
nullptr);
2787 decltype(
auto) children =
this->protocol().childRows(
QRangeModelDetails::refTo(row));
2793 auto &row =
this->rowData(index);
2795 return static_cast<range_type *>(
nullptr);
2797 decltype(
auto) children =
this->protocol().childRows(
QRangeModelDetails::refTo(row));
2798 using Children = std::remove_reference_t<
decltype(children)>;
2800 if constexpr (QRangeModelDetails::is_any_of<Children, std::optional>())
2801 if constexpr (std::is_default_constructible<
typename Children::value_type>()) {
2803 children.emplace(range_type{});
2812 : *
this->m_data.model();
2816 range_type &childrenOf(row_ptr row)
2819 : *
this->m_data.model();
2824template <
typename Range>
2831 static constexpr bool is_mutable_impl =
true;
2848 if constexpr (Base::dynamicColumns()) {
2849 if (column <
int(Base::size(*QRangeModelDetails::pos(*
this->m_data.model(), row))))
2850 return this->createIndex(row, column);
2853 qCritical(
"QRangeModel: Column-range at row %d is not large enough!", row);
2857 return this->createIndex(row, column);
2868 if (parent.isValid())
2870 return int(Base::size(*
this->m_data.model()));
2875 if (parent.isValid())
2879 if constexpr (Base::dynamicColumns()) {
2880 return int(Base::size(*
this->m_data.model()) == 0
2882 : Base::size(*QRangeModelDetails::adl_begin(*
this->m_data.model())));
2884 return Base::fixedColumnCount();
2890 return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemNeverHasChildren;
2895 return Base::dynamicRows() && range_features::has_insert;
2900 return Base::dynamicRows() && range_features::has_erase;
2903 static constexpr bool canMoveColumns(
const QModelIndex &source,
const QModelIndex &destination)
2905 return !source.isValid() && !destination.isValid();
2908 static constexpr bool canMoveRows(
const QModelIndex &source,
const QModelIndex &destination)
2910 return !source.isValid() && !destination.isValid();
2914 const QModelIndex &,
int)
noexcept
2922 row_type empty_row =
this->protocol().newRow();
2925 if constexpr (Base::dynamicColumns() && row_features::has_resize) {
2933 template <
typename It,
typename Sentinel>
2936 if constexpr (Base::protocol_traits::has_deleteRow) {
2937 for (
auto it = begin; it != end; ++it)
2938 this->protocol().deleteRow(
std::move(*it));
2944 Q_ASSERT(q20::cmp_less(index.row(), Base::size(*
this->m_data.model())));
2950 Q_ASSERT(q20::cmp_less(index.row(), Base::size(*
this->m_data.model())));
2967 return *
this->m_data.model();
2978 for (
const auto &row : *
this->m_data.model()) {
2979 result &=
this->autoConnectPropertiesInRow(row, rowIndex, {});
QModelIndex parentImpl(const QModelIndex &) const
static constexpr bool canMoveRows(const QModelIndex &source, const QModelIndex &destination)
void deleteRemovedRows(It &&begin, Sentinel &&end)
const range_type & childrenOf(const_row_ptr row) const
static constexpr bool canRemoveRowsImpl()
QGenericTableItemModelImpl(Range &&model, QRangeModel *itemModel)
range_type * childRangeImpl(const QModelIndex &)
int columnCountImpl(const QModelIndex &parent) const
constexpr bool moveRowsAcross(const QModelIndex &, int, int, const QModelIndex &, int) noexcept
decltype(auto) rowDataImpl(const QModelIndex &index) const
static constexpr bool canInsertRowsImpl()
const range_type * childRangeImpl(const QModelIndex &) const
int rowCountImpl(const QModelIndex &parent) const
void resetParentInChildren(range_type *)
bool autoConnectPropertiesImpl() const
static constexpr bool canMoveColumns(const QModelIndex &source, const QModelIndex &destination)
decltype(auto) rowDataImpl(const QModelIndex &index)
QModelIndex indexImpl(int row, int column, const QModelIndex &) const
static constexpr Qt::ItemFlags defaultFlags()
auto makeEmptyRow(typename Base::row_ptr)
static constexpr bool canMoveColumns(const QModelIndex &, const QModelIndex &)
auto makeEmptyRow(row_ptr parentRow)
void setParentRow(range_type &children, row_ptr parent)
bool autoConnectPropertiesImpl() const
range_type * childRangeImpl(const QModelIndex &index)
bool moveRowsAcross(const QModelIndex &sourceParent, int sourceRow, int count, const QModelIndex &destParent, int destRow)
void resetParentInChildren(range_type *children)
int rowCountImpl(const QModelIndex &parent) const
static constexpr bool canRemoveRowsImpl()
int columnCountImpl(const QModelIndex &) const
static constexpr bool canMoveRows(const QModelIndex &, const QModelIndex &)
const range_type & childrenOf(const_row_ptr row) const
decltype(auto) rowDataImpl(const QModelIndex &index)
QGenericTreeItemModelImpl(Range &&model, Protocol &&p, QRangeModel *itemModel)
bool autoConnectPropertiesRange(const range_type &range, const QModelIndex &parent) const
QModelIndex indexImpl(int row, int column, const QModelIndex &parent) const
void deleteRemovedRows(It &&begin, Sentinel &&end)
bool autoConnectProperties(const QModelIndex &parent) const
const range_type * childRangeImpl(const QModelIndex &index) const
static constexpr bool canInsertRowsImpl()
decltype(auto) rowDataImpl(const QModelIndex &index) const
void deleteRemovedRows(range_type &range)
static constexpr Qt::ItemFlags defaultFlags()
QModelIndex parentImpl(const QModelIndex &child) const
const QAbstractItemModel & itemModel() const
void beginInsertRows(const QModelIndex &parent, int start, int count)
void multiData(const QModelIndex &index, QModelRoleDataSpan roleDataSpan) const
bool beginMoveColumns(const QModelIndex &sourceParent, int sourceFirst, int sourceLast, const QModelIndex &destParent, int destRow)
bool setItemData(const QModelIndex &index, const QMap< int, QVariant > &data)
QMap< int, QVariant > itemData(const QModelIndex &index) const
bool insertRows(int row, int count, const QModelIndex &parent)
Qt::ItemFlags flags(const QModelIndex &index) const
bool beginMoveRows(const QModelIndex &sourceParent, int sourceFirst, int sourceLast, const QModelIndex &destParent, int destRow)
void beginRemoveRows(const QModelIndex &parent, int start, int count)
bool clearItemData(const QModelIndex &index)
QVariant data(const QModelIndex &index, int role) const
std::tuple< typename C::Destroy, typename C::InvalidateCaches, typename C::SetHeaderData, typename C::SetData, typename C::SetItemData, typename C::ClearItemData, typename C::InsertColumns, typename C::RemoveColumns, typename C::MoveColumns, typename C::InsertRows, typename C::RemoveRows, typename C::MoveRows, typename C::Index, typename C::Parent, typename C::Sibling, typename C::RowCount, typename C::ColumnCount, typename C::Flags, typename C::HeaderData, typename C::Data, typename C::ItemData, typename C::RoleNames, typename C::MultiData, typename C::SetAutoConnectPolicy > MethodTemplates
QRangeModelImplBase(QRangeModel *itemModel)
static auto for_element_at(StaticContainer &&container, std::size_t idx, F &&function)
static Q_CORE_EXPORT bool connectPropertiesConst(const QModelIndex &index, QObject *item, QObject *context, const QHash< int, QMetaProperty > &properties)
void changePersistentIndexList(const QModelIndexList &from, const QModelIndexList &to)
int columnCount(const QModelIndex &parent) const
QModelIndex sibling(int row, int column, const QModelIndex &index) const
void beginInsertColumns(const QModelIndex &parent, int start, int count)
bool insertColumns(int column, int count, const QModelIndex &parent)
static Q_CORE_EXPORT bool connectProperty(const QModelIndex &index, QObject *item, QObject *context, int role, const QMetaProperty &property)
void setAutoConnectPolicy()
static Q_CORE_EXPORT bool connectProperties(const QModelIndex &index, QObject *item, QObject *context, const QHash< int, QMetaProperty > &properties)
bool removeRows(int row, int count, const QModelIndex &parent)
QModelIndex parent(const QModelIndex &child) const
QAbstractItemModel & itemModel()
QModelIndex createIndex(int row, int column, const void *ptr=nullptr) const
QHash< int, QByteArray > roleNames() const
bool moveColumns(const QModelIndex &sourceParent, int sourceColumn, int count, const QModelIndex &destParent, int destColumn)
bool setData(const QModelIndex &index, const QVariant &data, int role)
void dataChanged(const QModelIndex &from, const QModelIndex &to, const QList< int > &roles)
QVariant headerData(int section, Qt::Orientation orientation, int role) const
static Q_CORE_EXPORT bool connectPropertyConst(const QModelIndex &index, QObject *item, QObject *context, int role, const QMetaProperty &property)
AutoConnectPolicy autoConnectPolicy() const
bool removeColumns(int column, int count, const QModelIndex &parent)
QModelIndex index(int row, int column, const QModelIndex &parent) const
bool setHeaderData(int section, Qt::Orientation orientation, const QVariant &data, int role)
int rowCount(const QModelIndex &parent) const
void beginRemoveColumns(const QModelIndex &parent, int start, int count)
bool moveRows(const QModelIndex &sourceParent, int sourceRow, int count, const QModelIndex &destParent, int destRow)
bool removeRows(int row, int count, const QModelIndex &parent={})
static QVariant readProperty(const QMetaProperty &prop, ItemType *gadget)
QHash< int, QByteArray > roleNames() const
row_reference rowData(const QModelIndex &index)
static constexpr bool dynamicRows()
static QVariant read(const Value &value)
const range_type * childRange(const QModelIndex &index) const
bool moveColumns(const QModelIndex &sourceParent, int sourceColumn, int count, const QModelIndex &destParent, int destColumn)
auto maybeBlockDataChangedDispatch()
static constexpr bool has_metaobject
QMetaProperty roleProperty(int role) const
int columnCount(const QModelIndex &parent) const
bool writeRole(int role, ItemType &&gadget, const QVariant &data)
static bool write(Target *target, const QVariant &value)
Qt::ItemFlags flags(const QModelIndex &index) const
void readAt(const QModelIndex &index, F &&reader) const
bool insertColumns(int column, int count, const QModelIndex &parent)
QVariant data(const QModelIndex &index, int role) const
QVariant headerData(int section, Qt::Orientation orientation, int role) const
static constexpr bool isRangeModelRole(int role)
bool clearItemData(const QModelIndex &index)
void multiData(const QModelIndex &index, QModelRoleDataSpan roleDataSpan) const
static constexpr int fixedColumnCount()
const protocol_type & protocol() const
static bool resetProperty(int property, ItemType &&object)
QModelIndex sibling(int row, int column, const QModelIndex &index) const
static bool writeProperty(int property, ItemType &&gadget, const QVariant &data)
bool setItemData(const QModelIndex &index, const QMap< int, QVariant > &data)
bool insertRows(int row, int count, const QModelIndex &parent)
static constexpr bool canInsertRows()
static bool writeProperty(const QMetaProperty &prop, ItemType *gadget, const QVariant &data)
static constexpr int size(const C &c)
const_row_reference rowData(const QModelIndex &index) const
bool writeAt(const QModelIndex &index, F &&writer)
static constexpr bool one_dimensional_range
static constexpr bool rows_are_raw_pointers
bool setHeaderData(int, Qt::Orientation, const QVariant &, int)
bool removeColumns(int column, int count, const QModelIndex &parent)
static constexpr bool isMutable()
bool setData(const QModelIndex &index, const QVariant &data, int role)
QModelIndex parent(const QModelIndex &child) const
static QVariant read(Value *value)
static bool write(Target &target, const QVariant &value)
static QVariant readProperty(int property, const ItemType &gadget)
bool writeRole(int role, ItemType *gadget, const QVariant &data)
QVariant readRole(const QModelIndex &index, int role, const ItemType &gadget) const
QRangeModelImpl< Structure, Range, Protocol > Self
static constexpr bool canRemoveRows()
static constexpr int static_column_count
static QVariant readProperty(int property, ItemType *gadget)
protocol_type & protocol()
int rowCount(const QModelIndex &parent) const
static constexpr bool rows_are_owning_or_raw_pointers
QModelIndex index(int row, int column, const QModelIndex &parent) const
static constexpr int static_row_count
void setAutoConnectPolicy()
static bool writeProperty(int property, ItemType *gadget, const QVariant &data)
QRangeModelImpl(Range &&model, Protocol &&protocol, QRangeModel *itemModel)
const Structure & that() const
static constexpr bool isPrimaryRole(int role)
void updateTarget(LHS *org, RHS &©) noexcept
static constexpr bool itemsAreQObjects
static constexpr bool dynamicColumns()
range_type * childRange(const QModelIndex &index)
bool moveRows(const QModelIndex &sourceParent, int sourceRow, int count, const QModelIndex &destParent, int destRow)
QVariant readRole(const QModelIndex &index, int role, ItemType *gadget) const
static bool resetProperty(int property, ItemType *object)
bool autoConnectPropertiesInRow(const row_type &row, int rowIndex, const QModelIndex &parent) const
bool doInsertColumns(int column, int count, const QModelIndex &parent, InsertFn insertFn)
void updateTarget(LHS &org, RHS &©) noexcept
QMap< int, QVariant > itemData(const QModelIndex &index) const
void clearConnectionInRow(const row_type &row, int rowIndex, const QModelIndex &parent) const
bool doInsertRows(int row, int count, const QModelIndex &parent, InsertFn &&insertFn)
static auto adl_end(C &&c) -> decltype(end(QRangeModelDetails::refTo(std::forward< C >(c))))
static constexpr bool has_metaobject_v
static constexpr bool is_range_v
static constexpr bool array_like_v
static void rotate(C &c, int src, int count, int dst)
static constexpr bool tuple_like_v
typename QRangeModelDetails::wrapped_helper< T >::type wrapped_t
auto value(It &&it) -> decltype(it.value())
std::conjunction< std::is_swappable< decltype(*std::declval< It >())>, std::is_base_of< std::forward_iterator_tag, typename std::iterator_traits< It >::iterator_category > > test_rotate
auto key(It &&it) -> decltype(it.key())
static constexpr int static_size_v
static constexpr bool isValid(const T &t) noexcept
static auto pos(C &&c, int i)
static decltype(auto) refTo(T &&t)
static auto pointerTo(T &&t)
static auto adl_begin(C &&c) -> decltype(begin(QRangeModelDetails::refTo(std::forward< C >(c))))
static constexpr bool is_multi_role_v
auto setParentRow(R &row, R *parent) -> decltype(row.setParentRow(parent))
auto childRows(R &row) -> decltype(row.childRows())
auto childRows(const R &row) const -> decltype(row.childRows())
auto parentRow(const R &row) const -> decltype(row.parentRow())
auto newRow() -> decltype(R{})
static constexpr bool cachesProperties
QHash< int, QMetaProperty > properties
friend bool operator==(const Connection &lhs, const Connection &rhs) noexcept
friend size_t qHash(const Connection &c, size_t seed) noexcept
QSet< Connection > connections
static constexpr bool cachesProperties
std::remove_const_t< ModelStorage > m_model
static constexpr bool int_key
static QHash< int, QByteArray > roleNames(That *)
static constexpr bool has_erase
static constexpr bool has_splice
static constexpr bool has_resize
static constexpr bool is_mutable
static constexpr bool has_rotate
static constexpr bool has_cbegin
static constexpr bool has_insert
static constexpr bool is_default
static constexpr bool has_setParentRow
static constexpr bool is_list
static constexpr bool has_mutable_childRows
static constexpr bool has_deleteRow
static constexpr bool has_newRow
static constexpr bool is_tree
static constexpr bool is_table
static constexpr bool has_insert_range
static constexpr bool is_mutable
static constexpr bool has_rotate
static constexpr bool has_resize
static constexpr bool has_insert
static constexpr bool has_cbegin
static constexpr bool has_splice
static constexpr bool has_erase
static constexpr bool isMultiRole
static constexpr int fixed_size()
static QVariant column_name(int)
static constexpr int static_size
static constexpr bool is_range
static constexpr bool hasMetaObject
static bool for_each_element(const Row &row, const QModelIndex &firstIndex, Fn &&fn)
std::input_iterator_tag iterator_category
friend bool operator==(const EmptyRowGenerator &lhs, const EmptyRowGenerator &rhs) noexcept
friend bool operator!=(const EmptyRowGenerator &lhs, const EmptyRowGenerator &rhs) noexcept
EmptyRowGenerator & operator++()