13class QT_TECH_PREVIEW_API QRangeModelAdapter
15 using Impl = QRangeModelDetails::RangeImplementation<Range, Protocol>;
16 using Storage = QRangeModelDetails::AdapterStorage<Model, Impl>;
21 using range_type = Range;
23 using range_type = QRangeModelDetails::wrapped_t<Range>;
25 using const_row_reference =
typename Impl::const_row_reference;
26 using row_reference =
typename Impl::row_reference;
27 using range_features =
typename QRangeModelDetails::range_traits<range_type>;
28 using row_type = std::remove_reference_t<row_reference>;
29 using row_features = QRangeModelDetails::range_traits<
typename Impl::wrapped_row_type>;
30 using row_ptr =
typename Impl::wrapped_row_type *;
31 using row_traits =
typename Impl::row_traits;
32 using item_type = std::remove_reference_t<
typename row_traits::item_type>;
33 using data_type =
typename QRangeModelDetails::data_type<item_type>::type;
34 using const_data_type = QRangeModelDetails::asConst_t<data_type>;
35 using protocol_traits =
typename Impl::protocol_traits;
37 template <
typename I>
static constexpr bool is_list = I::protocol_traits::is_list;
38 template <
typename I>
static constexpr bool is_table = I::protocol_traits::is_table;
39 template <
typename I>
static constexpr bool is_tree = I::protocol_traits::is_tree;
40 template <
typename I>
static constexpr bool canInsertColumns = I::dynamicColumns()
42 && row_features::has_insert;
43 template <
typename I>
static constexpr bool canRemoveColumns = I::dynamicColumns()
45 && row_features::has_erase;
47 template <
typename I>
using if_writable = std::enable_if_t<I::isMutable(),
bool>;
48 template <
typename I>
using if_list = std::enable_if_t<is_list<I>,
bool>;
49 template <
typename I>
using unless_list = std::enable_if_t<!is_list<I>,
bool>;
50 template <
typename I>
using if_table = std::enable_if_t<is_table<I>,
bool>;
51 template <
typename I>
using if_tree = std::enable_if_t<is_tree<I>,
bool>;
52 template <
typename I>
using unless_tree = std::enable_if_t<!is_tree<I>,
bool>;
53 template <
typename I>
using if_flat = std::enable_if_t<is_list<I> || is_table<I>,
bool>;
56 using if_canInsertRows = std::enable_if_t<I::canInsertRows(),
bool>;
58 using if_canRemoveRows = std::enable_if_t<I::canRemoveRows(),
bool>;
60 using if_canMoveItems = std::enable_if_t<F::has_rotate || F::has_splice,
bool>;
63 using if_canInsertColumns = std::enable_if_t<canInsertColumns<I>,
bool>;
65 using if_canRemoveColumns = std::enable_if_t<canRemoveColumns<I>,
bool>;
67 template <
typename Row>
68 static constexpr bool is_compatible_row = std::is_convertible_v<Row, const_row_reference>;
69 template <
typename Row>
70 using if_compatible_row = std::enable_if_t<is_compatible_row<Row>,
bool>;
73 static constexpr bool is_compatible_row_range = is_compatible_row<
74 decltype(*std::begin(std::declval<C&>()))
77 using if_compatible_row_range = std::enable_if_t<is_compatible_row_range<C>,
bool>;
78 template <
typename Data>
79 static constexpr bool is_compatible_data = std::is_convertible_v<Data, data_type>;
80 template <
typename Data>
81 using if_compatible_data = std::enable_if_t<is_compatible_data<Data>,
bool>;
83 static constexpr bool is_compatible_data_range = is_compatible_data<
84 typename QRangeModelDetails::data_type<
85 typename QRangeModelDetails::row_traits<
86 decltype(*std::begin(std::declval<C&>()))
91 using if_compatible_column_data = std::enable_if_t<is_compatible_data<C>
92 || is_compatible_data_range<C>,
bool>;
94 using if_compatible_column_range = std::enable_if_t<is_compatible_data_range<C>,
bool>;
97 using if_assignable_range = std::enable_if_t<std::is_assignable_v<range_type, R>,
bool>;
99 friend class QRangeModel;
100 template <
typename T>
101 static constexpr bool is_adapter = QRangeModelDetails::is_any_of<q20::remove_cvref_t<T>,
102 QRangeModelAdapter>::value;
103 template <
typename T>
104 using unless_adapter = std::enable_if_t<!is_adapter<T>,
bool>;
106 template <
typename R,
typename P>
107 using if_compatible_model_params =
111 std::is_convertible<R &&, Range>,
112 std::is_convertible<R &&, Range &&>
114 std::is_convertible<P, Protocol>
117#if !defined(Q_OS_VXWORKS) && !defined(Q_OS_INTEGRITY)
123 template <
typename T>
static constexpr T asMutable(
const T &);
124 template <
typename T>
static constexpr T *asMutable(
const T *);
125 template <
template <
typename,
typename...>
typename U,
typename T,
typename ...Args>
126 static constexpr U<T, Args...> asMutable(
const U<
const T, Args...> &);
128 template <
typename T>
129 using asMutable_t =
decltype(asMutable(std::declval<T>()));
130 friend class QRangeModelAdapter<asMutable_t<Range>, Protocol, Model>;
132 template <
typename R,
typename P,
typename M>
133 friend class QRangeModelAdapter;
136 explicit QRangeModelAdapter(
const std::shared_ptr<QRangeModel> &model,
const QModelIndex &root,
138 : storage{model, root}
141 explicit QRangeModelAdapter(QRangeModel *model)
148 using value_type = data_type;
149 using const_value_type = const_data_type;
150 using pointer = QRangeModelDetails::data_pointer_t<const_value_type>;
152 explicit DataReference(
const QModelIndex &index)
noexcept
155 Q_ASSERT_X(m_index.isValid(),
"QRangeModelAdapter::at",
"Index at position is invalid");
158 DataReference(
const DataReference &other) =
default;
159 DataReference(DataReference &&other) =
default;
162 DataReference &operator=(
const DataReference &other)
168 DataReference &operator=(DataReference &&other)
174 ~DataReference() =
default;
176 DataReference &operator=(
const value_type &value)
182 DataReference &operator=(value_type &&value)
184 assign(std::move(value));
188 const_value_type get()
const
190 Q_ASSERT_X(m_index.isValid(),
"QRangeModelAdapter::at",
"Index at position is invalid");
191 return QRangeModelDetails::dataAtIndex<q20::remove_cvref_t<value_type>>(m_index);
194 operator const_value_type()
const
199 pointer operator->()
const
204 bool isValid()
const {
return m_index.isValid(); }
209 template <
typename Value>
210 void assign(Value &&value)
212 constexpr Qt::ItemDataRole dataRole = Qt::RangeModelAdapterRole;
214 if (m_index.isValid()) {
215 auto model =
const_cast<QAbstractItemModel *>(m_index.model());
216 [[maybe_unused]]
bool couldWrite =
false;
217 if constexpr (std::is_same_v<q20::remove_cvref_t<Value>, QVariant>) {
218 couldWrite = model->setData(m_index, value, dataRole);
220 couldWrite = model->setData(m_index,
221 QVariant::fromValue(std::forward<Value>(value)),
226 qWarning() <<
"Writing value of type"
227 << QMetaType::fromType<q20::remove_cvref_t<Value>>().name()
228 <<
"to role" << dataRole <<
"at index" << m_index <<
"failed";
231 qCritical(
"Data reference for invalid index, can't write to model");
236 friend inline bool comparesEqual(
const DataReference &lhs,
const DataReference &rhs)
238 return lhs.m_index == rhs.m_index
239 || lhs.get() == rhs.get();
241 Q_DECLARE_EQUALITY_COMPARABLE_NON_NOEXCEPT(DataReference);
243 friend inline bool comparesEqual(
const DataReference &lhs,
const value_type &rhs)
245 return lhs.get() == rhs;
247 Q_DECLARE_EQUALITY_COMPARABLE_NON_NOEXCEPT(DataReference, value_type);
249 friend inline void swap(DataReference lhs, DataReference rhs)
251 const value_type lhsValue = lhs.get();
256#ifndef QT_NO_DEBUG_STREAM
257 friend inline QDebug operator<<(QDebug dbg,
const DataReference &ref)
259 return dbg << ref.get();
262#ifndef QT_NO_DATASTREAM
263 friend inline QDataStream &operator<<(QDataStream &ds,
const DataReference &ref)
265 return ds << ref.get();
267 friend inline QDataStream &operator>>(QDataStream &ds, DataReference &ref)
276 template <
typename Iterator,
typename Adapter>
277 struct ColumnIteratorBase
279 using iterator_category = std::random_access_iterator_tag;
280 using difference_type =
int;
282 ColumnIteratorBase() =
default;
283 ColumnIteratorBase(
const ColumnIteratorBase &other) =
default;
284 ColumnIteratorBase(ColumnIteratorBase &&other) =
default;
285 ColumnIteratorBase &operator=(
const ColumnIteratorBase &other) =
default;
286 ColumnIteratorBase &operator=(ColumnIteratorBase &&other) =
default;
288 ColumnIteratorBase(
const QModelIndex &rowIndex,
int column, Adapter *adapter)
noexcept
289 : m_rowIndex(rowIndex), m_column(column), m_adapter(adapter)
293 void swap(ColumnIteratorBase &other)
noexcept
295 qSwap(m_rowIndex, other.m_rowIndex);
296 qSwap(m_column, other.m_column);
297 q_ptr_swap(m_adapter, other.m_adapter);
300 friend Iterator &operator++(Iterator &that)
noexcept
305 friend Iterator operator++(Iterator &that,
int)
noexcept
311 friend Iterator operator+(
const Iterator &that, difference_type n)
noexcept
313 return {that.m_rowIndex, that.m_column + n, that.m_adapter};
315 friend Iterator operator+(difference_type n,
const Iterator &that)
noexcept
319 friend Iterator &operator+=(Iterator &that, difference_type n)
noexcept
325 friend Iterator &operator--(Iterator &that)
noexcept
330 friend Iterator operator--(Iterator &that,
int)
noexcept
336 friend Iterator operator-(
const Iterator &that, difference_type n)
noexcept
338 return {that.m_rowIndex, that.m_column - n, that.m_adapter};
340 friend Iterator operator-(difference_type n,
const Iterator &that)
noexcept
344 friend Iterator &operator-=(Iterator &that, difference_type n)
noexcept
350 friend difference_type operator-(
const Iterator &lhs,
const Iterator &rhs)
noexcept
352 Q_PRE(lhs.m_rowIndex == rhs.m_rowIndex);
353 Q_PRE(lhs.m_adapter == rhs.m_adapter);
354 return lhs.m_column - rhs.m_column;
358 ~ColumnIteratorBase() =
default;
359 QModelIndex m_rowIndex;
361 Adapter *m_adapter =
nullptr;
364 friend bool comparesEqual(
const Iterator &lhs,
const Iterator &rhs)
366 Q_ASSERT(lhs.m_rowIndex == rhs.m_rowIndex);
367 return lhs.m_column == rhs.m_column;
369 friend Qt::strong_ordering compareThreeWay(
const Iterator &lhs,
const Iterator &rhs)
371 Q_ASSERT(lhs.m_rowIndex == rhs.m_rowIndex);
372 return qCompareThreeWay(lhs.m_column, rhs.m_column);
375 Q_DECLARE_STRONGLY_ORDERED_NON_NOEXCEPT(Iterator)
377#ifndef QT_NO_DEBUG_STREAM
378 friend inline QDebug operator<<(QDebug dbg,
const Iterator &it)
380 QDebugStateSaver saver(dbg);
382 return dbg <<
"ColumnIterator(" << it.m_rowIndex.siblingAtColumn(it.m_column) <<
")";
387 struct ConstColumnIterator : ColumnIteratorBase<ConstColumnIterator,
const QRangeModelAdapter>
389 using Base = ColumnIteratorBase<ConstColumnIterator,
const QRangeModelAdapter>;
390 using difference_type =
typename Base::difference_type;
391 using value_type = data_type;
392 using reference = const_data_type;
393 using pointer = QRangeModelDetails::data_pointer_t<value_type>;
396 using Base::operator=;
397 ~ConstColumnIterator() =
default;
399 pointer operator->()
const
401 return pointer{operator*()};
404 reference operator*()
const
406 return std::as_const(
this->m_adapter)->at(
this->m_rowIndex.row(),
this->m_column);
409 reference operator[](difference_type n)
const
415 struct ColumnIterator : ColumnIteratorBase<ColumnIterator, QRangeModelAdapter>
417 using Base = ColumnIteratorBase<ColumnIterator, QRangeModelAdapter>;
418 using difference_type =
typename Base::difference_type;
419 using value_type = DataReference;
420 using reference = DataReference;
421 using pointer = reference;
424 using Base::operator=;
425 ~ColumnIterator() =
default;
427 operator ConstColumnIterator()
const
429 return ConstColumnIterator{
this->m_rowIndex,
this->m_column,
this->m_adapter};
432 pointer operator->()
const
437 reference operator*()
const
439 return reference{
this->m_rowIndex.siblingAtColumn(
this->m_column)};
442 reference operator[](difference_type n)
const
448 template <
typename Reference,
typename const_row_type,
typename =
void>
451 const_row_type get()
const
453 const Reference *that =
static_cast<
const Reference *>(
this);
454 const auto *impl = that->m_adapter->storage.implementation();
455 auto *childRange = impl->childRange(that->m_index.parent());
456 if constexpr (std::is_convertible_v<
const row_type &, const_row_type>) {
457 return *std::next(QRangeModelDetails::adl_begin(childRange), that->m_index.row());
459 const auto &row = *std::next(QRangeModelDetails::adl_begin(childRange),
460 that->m_index.row());
461 return const_row_type{QRangeModelDetails::adl_begin(row),
462 QRangeModelDetails::adl_end(row)};
466 const_row_type operator->()
const
471 operator const_row_type()
const
477 template <
typename Reference,
typename const_row_type>
478 struct RowGetter<Reference, const_row_type,
479 std::enable_if_t<std::is_reference_v<const_row_type>>>
481 const_row_type get()
const
483 const Reference *that =
static_cast<
const Reference *>(
this);
484 const auto *impl = that->m_adapter->storage.implementation();
485 return *std::next(QRangeModelDetails::begin(
486 QRangeModelDetails::refTo(impl->childRange(that->m_index.parent()))),
487 that->m_index.row());
490 auto operator->()
const
492 return std::addressof(get());
495 operator const_row_type()
const
501 template <
typename Reference,
typename const_row_type>
502 struct RowGetter<Reference, const_row_type,
503 std::enable_if_t<std::is_pointer_v<const_row_type>>>
505 const_row_type get()
const
507 const Reference *that =
static_cast<
const Reference *>(
this);
508 const auto *impl = that->m_adapter->storage.implementation();
509 return *std::next(QRangeModelDetails::begin(
510 QRangeModelDetails::refTo(impl->childRange(that->m_index.parent()))),
511 that->m_index.row());
514 const_row_type operator->()
const
519 operator const_row_type()
const
525 template <
typename Reference,
typename Adapter>
526 struct RowReferenceBase : RowGetter<Reference, QRangeModelDetails::asConstRow_t<row_type>>
528 using const_iterator = ConstColumnIterator;
529 using size_type =
int;
530 using difference_type =
int;
531 using const_row_type = QRangeModelDetails::asConstRow_t<row_type>;
533 RowReferenceBase(
const QModelIndex &index, Adapter *adapter)
noexcept
534 : m_index(index), m_adapter(adapter)
537 template <
typename I = Impl, if_tree<I> =
true>
538 bool hasChildren()
const
540 return m_adapter->model()->hasChildren(m_index);
543 template <
typename I = Impl, if_tree<I> =
true>
544 auto children()
const
546 using ConstRange = QRangeModelDetails::asConst_t<Range>;
547 return QRangeModelAdapter<ConstRange, Protocol, Model>(m_adapter->storage.m_model,
548 m_index, std::in_place);
551 ConstColumnIterator cbegin()
const
553 return ConstColumnIterator{m_index, 0, m_adapter};
555 ConstColumnIterator cend()
const
557 return ConstColumnIterator{m_index, m_adapter->columnCount(), m_adapter};
560 ConstColumnIterator begin()
const {
return cbegin(); }
561 ConstColumnIterator end()
const {
return cend(); }
563 size_type size()
const
565 return m_adapter->columnCount();
568 auto at(
int column)
const
570 Q_ASSERT(column >= 0 && column < m_adapter->columnCount());
571 return *ConstColumnIterator{m_index, column, m_adapter};
574 auto operator[](
int column)
const
580 friend struct RowGetter<Reference, const_row_type>;
581 ~RowReferenceBase() =
default;
586 friend bool comparesEqual(
const Reference &lhs,
const Reference &rhs)
588 Q_ASSERT(lhs.m_adapter == rhs.m_adapter);
589 return lhs.m_index == rhs.m_index;
591 friend Qt::strong_ordering compareThreeWay(
const Reference &lhs,
const Reference &rhs)
593 Q_ASSERT(lhs.m_adapter == rhs.m_adapter);
594 return qCompareThreeWay(lhs.m_index, rhs.m_index);
597 Q_DECLARE_STRONGLY_ORDERED_NON_NOEXCEPT(Reference)
599 friend bool comparesEqual(
const Reference &lhs,
const row_type &rhs)
601 return lhs.get() == rhs;
603 Q_DECLARE_EQUALITY_COMPARABLE_NON_NOEXCEPT(Reference, row_type)
605#ifndef QT_NO_DEBUG_STREAM
606 friend inline QDebug operator<<(QDebug dbg,
const Reference &ref)
608 QDebugStateSaver saver(dbg);
610 return dbg <<
"RowReference(" << ref.m_index <<
")";
613#ifndef QT_NO_DATASTREAM
614 friend inline QDataStream &operator<<(QDataStream &ds,
const Reference &ref)
616 return ds << ref.get();
621 struct ConstRowReference : RowReferenceBase<ConstRowReference,
const QRangeModelAdapter>
623 using Base = RowReferenceBase<ConstRowReference,
const QRangeModelAdapter>;
626 ConstRowReference() =
default;
627 ConstRowReference(
const ConstRowReference &) =
default;
628 ConstRowReference(ConstRowReference &&) =
default;
629 ConstRowReference &operator=(
const ConstRowReference &) =
default;
630 ConstRowReference &operator=(ConstRowReference &&) =
default;
631 ~ConstRowReference() =
default;
634 struct RowReference : RowReferenceBase<RowReference, QRangeModelAdapter>
636 using Base = RowReferenceBase<RowReference, QRangeModelAdapter>;
637 using iterator = ColumnIterator;
638 using const_iterator =
typename Base::const_iterator;
639 using size_type =
typename Base::size_type;
640 using difference_type =
typename Base::difference_type;
641 using const_row_type =
typename Base::const_row_type;
644 RowReference() =
delete;
645 ~RowReference() =
default;
646 RowReference(
const RowReference &other) =
default;
647 RowReference(RowReference &&other) =
default;
650 RowReference &operator=(
const ConstRowReference &other)
656 RowReference &operator=(
const RowReference &other)
662 RowReference &operator=(
const row_type &other)
668 RowReference &operator=(row_type &&other)
670 assign(std::move(other));
674 operator ConstRowReference()
const
676 return ConstRowReference{
this->m_index,
this->m_adapter};
679 template <
typename ConstRowType = const_row_type,
680 std::enable_if_t<!std::is_same_v<ConstRowType,
const row_type &>,
bool> =
true>
681 RowReference &operator=(
const ConstRowType &other)
687 template <
typename T,
typename It,
typename Sentinel>
688 RowReference &operator=(
const QRangeModelDetails::RowView<T, It, Sentinel> &other)
690 *
this = row_type{other.begin(), other.end()};
694 friend inline void swap(RowReference lhs, RowReference rhs)
696 auto lhsRow = lhs.get();
698 rhs = std::move(lhsRow);
701 template <
typename I = Impl, if_tree<I> =
true>
704 return QRangeModelAdapter(
this->m_adapter->storage.m_model,
this->m_index,
709 ColumnIterator begin()
711 return ColumnIterator{
this->m_index, 0,
this->m_adapter};
717 return ColumnIterator{
this->m_index,
this->m_adapter->columnCount(),
this->m_adapter};
723 Q_ASSERT(column >= 0 && column <
this->m_adapter->columnCount());
724 return *ColumnIterator{
this->m_index, column,
this->m_adapter};
727 using Base::operator[];
728 auto operator[](
int column)
734 template <
typename RHS>
735 void verifyRows(
const row_type &oldRow,
const RHS &newRow)
737 if constexpr (QRangeModelDetails::test_size<row_type>::value) {
739 Q_ASSERT_X(Impl::size(newRow) == Impl::size(oldRow),
740 "RowReference::operator=()",
741 "The new row has the wrong size!");
744 if constexpr (is_tree<Impl>) {
746 Q_ASSERT_X(QRangeModelDetails::isValid(newRow),
747 "RowReference::operator=()",
748 "An invalid row can not inserted into a tree!");
752 template <
typename R>
753 void assign(R &&other)
755 auto *impl =
this->m_adapter->storage.implementation();
756 decltype(
auto) oldRow = impl->rowData(
this->m_index);
758 verifyRows(oldRow, other);
760 if constexpr (is_tree<Impl>) {
761 auto &protocol = impl->protocol();
762 auto *oldParent = protocol.parentRow(QRangeModelDetails::refTo(oldRow));
766 if (
decltype(
auto) oldChildren = protocol.childRows(QRangeModelDetails::refTo(oldRow));
767 QRangeModelDetails::isValid(oldChildren)) {
768 if (
int oldChildCount =
this->m_adapter->model()->rowCount(
this->m_index)) {
769 impl->beginRemoveRows(
this->m_index, 0, oldChildCount - 1);
770 impl->deleteRemovedRows(QRangeModelDetails::refTo(oldChildren));
772 QRangeModelDetails::refTo(oldChildren) = range_type{};
773 impl->endRemoveRows();
777 if constexpr (protocol_traits::has_deleteRow)
778 protocol.deleteRow(oldRow);
779 oldRow = std::forward<R>(other);
780 if constexpr (protocol_traits::has_setParentRow) {
781 protocol.setParentRow(QRangeModelDetails::refTo(oldRow), oldParent);
782 if (
decltype(
auto) newChildren = protocol.childRows(QRangeModelDetails::refTo(oldRow));
783 QRangeModelDetails::isValid(newChildren)) {
784 impl->beginInsertRows(
this->m_index, 0,
785 Impl::size(QRangeModelDetails::refTo(newChildren)) - 1);
786 impl->setParentRow(QRangeModelDetails::refTo(newChildren),
787 QRangeModelDetails::pointerTo(oldRow));
788 impl->endInsertRows();
792 oldRow = std::forward<R>(other);
794 this->m_adapter->emitDataChanged(
this->m_index,
795 this->m_index.siblingAtColumn(
this->m_adapter->columnCount() - 1));
796 if constexpr (Impl::itemsAreQObjects) {
797 if (
this->m_adapter->model()->autoConnectPolicy() == QRangeModel::AutoConnectPolicy::Full) {
798 impl->autoConnectPropertiesInRow(oldRow,
this->m_index.row(),
this->m_index.parent());
799 if constexpr (is_tree<Impl>)
800 impl->autoConnectProperties(
this->m_index);
806#ifndef QT_NO_DATASTREAM
807 friend inline QDataStream &operator>>(QDataStream &ds, RowReference &ref)
817 template <
typename Iterator,
typename Adapter>
818 struct RowIteratorBase : QRangeModelDetails::ParentIndex<is_tree<Impl>>
820 using iterator_category = std::random_access_iterator_tag;
821 using difference_type =
int;
823 RowIteratorBase() =
default;
824 RowIteratorBase(
const RowIteratorBase &) =
default;
825 RowIteratorBase(RowIteratorBase &&) =
default;
826 RowIteratorBase &operator=(
const RowIteratorBase &) =
default;
827 RowIteratorBase &operator=(RowIteratorBase &&) =
default;
829 RowIteratorBase(
int row,
const QModelIndex &parent, Adapter *adapter)
830 : QRangeModelDetails::ParentIndex<is_tree<Impl>>{parent}
831 , m_row(row), m_adapter(adapter)
834 void swap(RowIteratorBase &other)
noexcept
836 qSwap(m_row, other.m_row);
837 qSwap(
this->m_rootIndex, other.m_rootIndex);
838 q_ptr_swap(m_adapter, other.m_adapter);
841 friend Iterator &operator++(Iterator &that)
noexcept
846 friend Iterator operator++(Iterator &that,
int)
noexcept
852 friend Iterator operator+(
const Iterator &that, difference_type n)
noexcept
854 return {that.m_row + n, that.root(), that.m_adapter};
856 friend Iterator operator+(difference_type n,
const Iterator &that)
noexcept
860 friend Iterator &operator+=(Iterator &that, difference_type n)
noexcept
866 friend Iterator &operator--(Iterator &that)
noexcept
871 friend Iterator operator--(Iterator &that,
int)
noexcept
877 friend Iterator operator-(
const Iterator &that, difference_type n)
noexcept
879 return {that.m_row - n, that.root(), that.m_adapter};
881 friend Iterator operator-(difference_type n,
const Iterator &that)
noexcept
885 friend Iterator &operator-=(Iterator &that, difference_type n)
noexcept
891 friend difference_type operator-(
const Iterator &lhs,
const Iterator &rhs)
noexcept
893 return lhs.m_row - rhs.m_row;
897 ~RowIteratorBase() =
default;
899 Adapter *m_adapter =
nullptr;
902 friend bool comparesEqual(
const Iterator &lhs,
const Iterator &rhs)
noexcept
904 return lhs.m_row == rhs.m_row && lhs.root() == rhs.root();
906 friend Qt::strong_ordering compareThreeWay(
const Iterator &lhs,
const Iterator &rhs)
noexcept
908 if (lhs.root() == rhs.root())
909 return qCompareThreeWay(lhs.m_row, rhs.m_row);
910 return qCompareThreeWay(lhs.root(), rhs.root());
913 Q_DECLARE_STRONGLY_ORDERED(Iterator)
915#ifndef QT_NO_DEBUG_STREAM
916 friend inline QDebug operator<<(QDebug dbg,
const Iterator &it)
918 QDebugStateSaver saver(dbg);
920 return dbg <<
"RowIterator(" << it.m_row << it.root() <<
")";
926 struct ConstRowIterator :
public RowIteratorBase<ConstRowIterator,
const QRangeModelAdapter>
928 using Base = RowIteratorBase<ConstRowIterator,
const QRangeModelAdapter>;
931 using difference_type =
typename Base::difference_type;
932 using value_type = std::conditional_t<is_list<Impl>,
935 using reference = std::conditional_t<is_list<Impl>,
938 using pointer = std::conditional_t<is_list<Impl>,
939 QRangeModelDetails::data_pointer_t<const_data_type>,
942 ConstRowIterator(
const ConstRowIterator &other) =
default;
943 ConstRowIterator(ConstRowIterator &&other) =
default;
944 ConstRowIterator &operator=(
const ConstRowIterator &other) =
default;
945 ConstRowIterator &operator=(ConstRowIterator &&other) =
default;
946 ~ConstRowIterator() =
default;
948 pointer operator->()
const
950 return pointer{operator*()};
953 reference operator*()
const
955 if constexpr (is_list<Impl>) {
956 return this->m_adapter->at(
this->m_row);
958 const QModelIndex index =
this->m_adapter->model()->index(
this->m_row, 0,
960 return ConstRowReference{index,
this->m_adapter};
964 reference operator[](difference_type n)
const
970 struct RowIterator :
public RowIteratorBase<RowIterator, QRangeModelAdapter>
972 using Base = RowIteratorBase<RowIterator, QRangeModelAdapter>;
975 using difference_type =
typename Base::difference_type;
976 using value_type = std::conditional_t<is_list<Impl>,
979 using reference = std::conditional_t<is_list<Impl>,
982 using pointer = std::conditional_t<is_list<Impl>,
986 RowIterator(
const RowIterator &other) =
default;
987 RowIterator(RowIterator &&other) =
default;
988 RowIterator &operator=(
const RowIterator &other) =
default;
989 RowIterator &operator=(RowIterator &&other) =
default;
990 ~RowIterator() =
default;
992 operator ConstRowIterator()
const
994 return ConstRowIterator{
this->m_row,
this->root(),
this->m_adapter};
997 pointer operator->()
const
999 return pointer{operator*()};
1002 reference operator*()
const
1004 const QModelIndex index =
this->m_adapter->model()->index(
this->m_row, 0,
this->root());
1005 if constexpr (is_list<Impl>) {
1006 return reference{index};
1008 return reference{index,
this->m_adapter};
1012 reference operator[](difference_type n)
const
1014 return *(*
this + n);
1018 using const_iterator = ConstRowIterator;
1019 using iterator = RowIterator;
1021 template <
typename R,
1023 if_compatible_model_params<R, P> =
true>
1024 explicit QRangeModelAdapter(R &&range, P &&protocol)
1025 : QRangeModelAdapter(
new Model(QRangeModelDetails::forwardOrConvert<Range>(std::forward<R>(range)),
1026 QRangeModelDetails::forwardOrConvert<Protocol>(std::forward<P>(protocol))))
1029 template <
typename R,
1031 if_compatible_model_params<R, P> =
true,
1032 unless_adapter<R> =
true>
1033 explicit QRangeModelAdapter(R &&range)
1034 : QRangeModelAdapter(
new Model(QRangeModelDetails::forwardOrConvert<Range>(std::forward<R>(range))))
1039 Model *model()
const
1041 return storage.m_model.get();
1044 const range_type &range()
const
1046 return QRangeModelDetails::refTo(storage.implementation()->childRange(storage.root()));
1049 Q_IMPLICIT operator
const range_type &()
const
1054 template <
typename NewRange = range_type, if_assignable_range<NewRange> =
true>
1055 void setRange(NewRange &&newRange)
1057 setRangeImpl(qsizetype(Impl::size(QRangeModelDetails::refTo(newRange))) - 1,
1058 [&newRange](
auto &oldRange) {
1059 oldRange = std::forward<NewRange>(newRange);
1063 template <
typename NewRange = range_type, if_assignable_range<NewRange> =
true,
1064 unless_adapter<NewRange> =
true>
1065 QRangeModelAdapter &operator=(NewRange &&newRange)
1067 setRange(std::forward<NewRange>(newRange));
1071 template <
typename Row, if_assignable_range<std::initializer_list<Row>> =
true>
1072 void setRange(std::initializer_list<Row> newRange)
1074 setRangeImpl(qsizetype(newRange.size() - 1), [&newRange](
auto &oldRange) {
1075 oldRange = newRange;
1079 template <
typename Row, if_assignable_range<std::initializer_list<Row>> =
true>
1080 QRangeModelAdapter &operator=(std::initializer_list<Row> newRange)
1086 template <
typename Row, if_assignable_range<std::initializer_list<Row>> =
true>
1087 void assign(std::initializer_list<Row> newRange)
1092 template <
typename InputIterator,
typename Sentinel,
typename I = Impl, if_writable<I> =
true>
1093 void setRange(InputIterator first, Sentinel last)
1095 setRangeImpl(qsizetype(std::distance(first, last) - 1), [first, last](
auto &oldRange) {
1096 oldRange.assign(first, last);
1100 template <
typename InputIterator,
typename Sentinel,
typename I = Impl, if_writable<I> =
true>
1101 void assign(InputIterator first, Sentinel last)
1103 setRange(first, last);
1107 ConstRowIterator cbegin()
const
1109 return ConstRowIterator{ 0, storage.root(),
this };
1111 ConstRowIterator begin()
const {
return cbegin(); }
1113 ConstRowIterator cend()
const
1115 return ConstRowIterator{ rowCount(), storage.root(),
this };
1117 ConstRowIterator end()
const {
return cend(); }
1119 template <
typename I = Impl, if_writable<I> =
true>
1122 return RowIterator{ 0, storage.root(),
this };
1125 template <
typename I = Impl, if_writable<I> =
true>
1128 return RowIterator{ rowCount(), storage.root(),
this };
1136 template <
typename I = Impl, if_list<I> =
true>
1137 QModelIndex index(
int row)
const
1139 return storage->index(row, 0, storage.root());
1142 template <
typename I = Impl, unless_list<I> =
true>
1143 QModelIndex index(
int row,
int column)
const
1145 return storage->index(row, column, storage.root());
1148 template <
typename I = Impl, if_tree<I> =
true>
1149 QModelIndex index(QSpan<
const int> path,
int col)
const
1152 QModelIndex result = storage.root();
1153 auto count = path.size();
1154 for (
const int r : path) {
1156 result = storage->index(r, 0, result);
1158 result = storage->index(r, col, result);
1163 int columnCount()
const
1166 return storage->columnCount({});
1169 int rowCount()
const
1171 return storage->rowCount(storage.root());
1174 template <
typename I = Impl, if_tree<I> =
true>
1175 int rowCount(
int row)
const
1177 return storage->rowCount(index(row, 0));
1180 template <
typename I = Impl, if_tree<I> =
true>
1181 int rowCount(QSpan<
const int> path)
const
1183 return storage->rowCount(index(path, 0));
1186 template <
typename I = Impl, if_tree<I> =
true>
1187 constexpr bool hasChildren(
int row)
const
1189 return storage.m_model->hasChildren(index(row, 0));
1192 template <
typename I = Impl, if_tree<I> =
true>
1193 constexpr bool hasChildren(QSpan<
const int> path)
const
1195 return storage.m_model->hasChildren(index(path, 0));
1198 template <
typename I = Impl, if_list<I> =
true>
1199 QVariant data(
int row)
const
1201 return QRangeModelDetails::dataAtIndex<QVariant>(index(row));
1204 template <
typename I = Impl, if_list<I> =
true>
1205 QVariant data(
int row,
int role)
const
1207 return QRangeModelDetails::dataAtIndex<QVariant>(index(row), role);
1210 template <
typename I = Impl, if_list<I> =
true, if_writable<I> =
true>
1211 bool setData(
int row,
const QVariant &value,
int role = Qt::EditRole)
1213 return storage->setData(index(row), value, role);
1216 template <
typename I = Impl, unless_list<I> =
true>
1217 QVariant data(
int row,
int column)
const
1219 return QRangeModelDetails::dataAtIndex<QVariant>(index(row, column));
1222 template <
typename I = Impl, unless_list<I> =
true>
1223 QVariant data(
int row,
int column,
int role)
const
1225 return QRangeModelDetails::dataAtIndex<QVariant>(index(row, column), role);
1228 template <
typename I = Impl, unless_list<I> =
true, if_writable<I> =
true>
1229 bool setData(
int row,
int column,
const QVariant &value,
int role = Qt::EditRole)
1231 return storage->setData(index(row, column), value, role);
1234 template <
typename I = Impl, if_tree<I> =
true>
1235 QVariant data(QSpan<
const int> path,
int column)
const
1237 return QRangeModelDetails::dataAtIndex<QVariant>(index(path, column));
1240 template <
typename I = Impl, if_tree<I> =
true>
1241 QVariant data(QSpan<
const int> path,
int column,
int role)
const
1243 return QRangeModelDetails::dataAtIndex<QVariant>(index(path, column), role);
1246 template <
typename I = Impl, if_tree<I> =
true, if_writable<I> =
true>
1247 bool setData(QSpan<
const int> path,
int column,
const QVariant &value,
int role = Qt::EditRole)
1249 return storage->setData(index(path, column), value, role);
1254 template <
typename I= Impl, if_list<I> =
true>
1255 const_data_type at(
int row)
const
1257 return QRangeModelDetails::dataAtIndex<data_type>(index(row));
1259 template <
typename I = Impl, if_list<I> =
true>
1260 const_data_type operator[](
int row)
const {
return at(row); }
1262 template <
typename I= Impl, if_list<I> =
true, if_writable<I> =
true>
1263 auto at(
int row) {
return DataReference{
this->index(row)}; }
1264 template <
typename I = Impl, if_list<I> =
true, if_writable<I> =
true>
1265 auto operator[](
int row) {
return DataReference{
this->index(row)}; }
1268 template <
typename I = Impl, unless_list<I> =
true>
1269 decltype(
auto) at(
int row)
const
1271 return ConstRowReference{index(row, 0),
this}.get();
1273 template <
typename I = Impl, unless_list<I> =
true>
1274 decltype(
auto) operator[](
int row)
const {
return at(row); }
1276 template <
typename I = Impl, if_table<I> =
true, if_writable<I> =
true>
1279 return RowReference{index(row, 0),
this};
1281 template <
typename I = Impl, if_table<I> =
true, if_writable<I> =
true>
1282 auto operator[](
int row) {
return at(row); }
1285 template <
typename I = Impl, unless_list<I> =
true>
1286 const_data_type at(
int row,
int column)
const
1288 return QRangeModelDetails::dataAtIndex<data_type>(index(row, column));
1291#ifdef __cpp_multidimensional_subscript
1292 template <
typename I = Impl, unless_list<I> =
true>
1293 const_data_type operator[](
int row,
int column)
const {
return at(row, column); }
1296 template <
typename I = Impl, unless_list<I> =
true, if_writable<I> =
true>
1297 auto at(
int row,
int column)
1299 return DataReference{
this->index(row, column)};
1301#ifdef __cpp_multidimensional_subscript
1302 template <
typename I = Impl, unless_list<I> =
true, if_writable<I> =
true>
1303 auto operator[](
int row,
int column) {
return at(row, column); }
1308 template <
typename I = Impl, if_tree<I> =
true, if_writable<I> =
true>
1311 return RowReference{index(row, 0),
this};
1313 template <
typename I = Impl, if_tree<I> =
true, if_writable<I> =
true>
1314 auto operator[](
int row) {
return at(row); }
1317 template <
typename I = Impl, if_tree<I> =
true>
1318 decltype(
auto) at(QSpan<
const int> path)
const
1320 return ConstRowReference{index(path, 0),
this}.get();
1322 template <
typename I = Impl, if_tree<I> =
true>
1323 decltype(
auto) operator[](QSpan<
const int> path)
const {
return at(path); }
1325 template <
typename I = Impl, if_tree<I> =
true, if_writable<I> =
true>
1326 auto at(QSpan<
const int> path)
1328 return RowReference{index(path, 0),
this};
1330 template <
typename I = Impl, if_tree<I> =
true, if_writable<I> =
true>
1331 auto operator[](QSpan<
const int> path) {
return at(path); }
1334 template <
typename I = Impl, if_tree<I> =
true>
1335 const_data_type at(QSpan<
const int> path,
int column)
const
1338 return QRangeModelDetails::dataAtIndex<data_type>(index(path, column));
1341#ifdef __cpp_multidimensional_subscript
1342 template <
typename I = Impl, if_tree<I> =
true>
1343 const_data_type operator[](QSpan<
const int> path,
int column)
const {
return at(path, column); }
1346 template <
typename I = Impl, if_tree<I> =
true, if_writable<I> =
true>
1347 auto at(QSpan<
const int> path,
int column)
1350 return DataReference{
this->index(path, column)};
1352#ifdef __cpp_multidimensional_subscript
1353 template <
typename I = Impl, if_tree<I> =
true, if_writable<I> =
true>
1354 auto operator[](QSpan<
const int> path,
int column) {
return at(path, column); }
1357 template <
typename I = Impl, if_canInsertRows<I> =
true>
1358 bool insertRow(
int before)
1360 return storage.m_model->insertRow(before);
1363 template <
typename I = Impl, if_canInsertRows<I> =
true, if_tree<I> =
true>
1364 bool insertRow(QSpan<
const int> before)
1366 Q_PRE(before.size());
1367 return storage.m_model->insertRow(before.back(),
this->index(before.first(before.size() - 1), 0));
1370 template <
typename D = row_type,
typename I = Impl,
1371 if_canInsertRows<I> =
true, if_compatible_row<D> =
true>
1372 bool insertRow(
int before, D &&data)
1374 return insertRowImpl(before, storage.root(), std::forward<D>(data));
1377 template <
typename D = row_type,
typename I = Impl,
1378 if_canInsertRows<I> =
true, if_compatible_row<D> =
true, if_tree<I> =
true>
1379 bool insertRow(QSpan<
const int> before, D &&data)
1381 return insertRowImpl(before, storage.root(), std::forward<D>(data));
1384 template <
typename C,
typename I = Impl,
1385 if_canInsertRows<I> =
true, if_compatible_row_range<C> =
true>
1386 bool insertRows(
int before, C &&data)
1388 return insertRowsImpl(before, storage.root(), std::forward<C>(data));
1391 template <
typename C,
typename I = Impl,
1392 if_canInsertRows<I> =
true, if_compatible_row_range<C> =
true, if_tree<I> =
true>
1393 bool insertRows(QSpan<
const int> before, C &&data)
1395 return insertRowsImpl(before.back(),
this->index(before.first(before.size() - 1), 0),
1396 std::forward<C>(data));
1399 template <
typename I = Impl, if_canRemoveRows<I> =
true>
1400 bool removeRow(
int row)
1402 return removeRows(row, 1);
1405 template <
typename I = Impl, if_canRemoveRows<I> =
true, if_tree<I> =
true>
1406 bool removeRow(QSpan<
const int> path)
1408 return removeRows(path, 1);
1411 template <
typename I = Impl, if_canRemoveRows<I> =
true>
1412 bool removeRows(
int row,
int count)
1414 return storage->removeRows(row, count, storage.root());
1417 template <
typename I = Impl, if_canRemoveRows<I> =
true, if_tree<I> =
true>
1418 bool removeRows(QSpan<
const int> path,
int count)
1420 return storage->removeRows(path.back(), count,
1421 this->index(path.first(path.size() - 1), 0));
1424 template <
typename F = range_features, if_canMoveItems<F> =
true>
1425 bool moveRow(
int source,
int destination)
1427 return moveRows(source, 1, destination);
1430 template <
typename F = range_features, if_canMoveItems<F> =
true>
1431 bool moveRows(
int source,
int count,
int destination)
1433 return storage->moveRows(storage.root(), source, count, storage.root(), destination);
1436 template <
typename I = Impl,
typename F = range_features,
1437 if_canMoveItems<F> =
true, if_tree<I> =
true>
1438 bool moveRow(QSpan<
const int> source, QSpan<
const int> destination)
1440 return moveRows(source, 1, destination);
1443 template <
typename I = Impl,
typename F = range_features,
1444 if_canMoveItems<F> =
true, if_tree<I> =
true>
1445 bool moveRows(QSpan<
const int> source,
int count, QSpan<
const int> destination)
1447 return storage->moveRows(
this->index(source.first(source.size() - 1), 0),
1450 this->index(destination.first(destination.size() - 1), 0),
1451 destination.back());
1454 template <
typename I = Impl, if_canInsertColumns<I> =
true>
1455 bool insertColumn(
int before)
1457 return storage.m_model->insertColumn(before);
1460 template <
typename D,
typename I = Impl,
1461 if_canInsertColumns<I> =
true, if_compatible_column_data<D> =
true>
1462 bool insertColumn(
int before, D &&data)
1464 return insertColumnImpl(before, storage.root(), std::forward<D>(data));
1467 template <
typename C,
typename I = Impl,
1468 if_canInsertColumns<I> =
true, if_compatible_column_range<C> =
true>
1469 bool insertColumns(
int before, C &&data)
1471 return insertColumnsImpl(before, storage.root(), std::forward<C>(data));
1474 template <
typename I = Impl, if_canRemoveColumns<I> =
true>
1475 bool removeColumn(
int column)
1477 return storage.m_model->removeColumn(column);
1480 template <
typename I = Impl, if_canRemoveColumns<I> =
true>
1481 bool removeColumns(
int column,
int count)
1483 return storage->removeColumns(column, count, {});
1486 template <
typename F = row_features, if_canMoveItems<F> =
true>
1487 bool moveColumn(
int from,
int to)
1489 return moveColumns(from, 1, to);
1492 template <
typename F = row_features, if_canMoveItems<F> =
true>
1493 bool moveColumns(
int from,
int count,
int to)
1495 return storage->moveColumns(storage.root(), from, count, storage.root(), to);
1498 template <
typename I = Impl,
typename F = row_features,
1499 if_canMoveItems<F> =
true, if_tree<I> =
true>
1500 bool moveColumn(QSpan<
const int> source,
int to)
1502 const QModelIndex parent =
this->index(source.first(source.size() - 1), 0);
1503 return storage->moveColumns(parent, source.back(), 1, parent, to);
1506 template <
typename I = Impl,
typename F = row_features,
1507 if_canMoveItems<F> =
true, if_tree<I> =
true>
1508 bool moveColumns(QSpan<
const int> source,
int count,
int destination)
1510 const QModelIndex parent =
this->index(source.first(source.size() - 1), 0);
1511 return storage->moveColumns(parent, source.back(), count, parent, destination);
1516 bool comparesEqual(
const QRangeModelAdapter &lhs,
const QRangeModelAdapter &rhs)
noexcept
1518 return lhs.storage.m_model == rhs.storage.m_model;
1520 Q_DECLARE_EQUALITY_COMPARABLE(QRangeModelAdapter)
1523 bool comparesEqual(
const QRangeModelAdapter &lhs,
const range_type &rhs)
1525 return lhs.range() == rhs;
1527 Q_DECLARE_EQUALITY_COMPARABLE_NON_NOEXCEPT(QRangeModelAdapter, range_type)
1530 void emitDataChanged(
const QModelIndex &topLeft,
const QModelIndex &bottomRight)
1532 Q_EMIT storage.implementation()->dataChanged(topLeft, bottomRight, {});
1535 void beginSetRangeImpl(Impl *impl, range_type *oldRange, qsizetype newLastRow)
1537 const QModelIndex root = storage.root();
1538 const qsizetype oldLastRow = qsizetype(Impl::size(oldRange)) - 1;
1540 if (!root.isValid()) {
1541 impl->beginResetModel();
1542 impl->deleteOwnedRows();
1543 }
else if constexpr (is_tree<Impl>) {
1544 if (oldLastRow > 0) {
1545 impl->beginRemoveRows(root, 0, model()->rowCount(root) - 1);
1546 impl->deleteRemovedRows(QRangeModelDetails::refTo(oldRange));
1547 impl->endRemoveRows();
1550 impl->beginInsertRows(root, 0, newLastRow);
1552 Q_ASSERT_X(
false,
"QRangeModelAdapter::setRange",
1553 "Internal error: The root index in a table or list must be invalid.");
1557 void endSetRangeImpl(Impl *impl, qsizetype newLastRow)
1559 const QModelIndex root = storage.root();
1560 if (!root.isValid()) {
1561 impl->endResetModel();
1562 }
else if constexpr (is_tree<Impl>) {
1563 if (newLastRow > 0) {
1564 Q_ASSERT(model()->hasChildren(root));
1567 impl->setParentRow(QRangeModelDetails::refTo(impl->childRange(root)),
1568 QRangeModelDetails::pointerTo(impl->rowData(root)));
1569 impl->endInsertRows();
1574 template <
typename Assigner>
1575 void setRangeImpl(qsizetype newLastRow, Assigner &&assigner)
1577 auto *impl = storage.implementation();
1578 auto *oldRange = impl->childRange(storage.root());
1579 beginSetRangeImpl(impl, oldRange, newLastRow);
1580 assigner(QRangeModelDetails::refTo(oldRange));
1581 endSetRangeImpl(impl, newLastRow);
1583 if constexpr (Impl::itemsAreQObjects) {
1584 if (model()->autoConnectPolicy() == QRangeModel::AutoConnectPolicy::Full) {
1585 const auto begin = QRangeModelDetails::begin(QRangeModelDetails::refTo(oldRange));
1586 const auto end = QRangeModelDetails::end(QRangeModelDetails::refTo(oldRange));
1588 for (
auto it = begin; it != end; ++it, ++rowIndex)
1589 impl->autoConnectPropertiesInRow(*it, rowIndex, storage.root());
1594 template <
typename P>
1595 static auto setParentRow(P protocol, row_type &newRow, row_ptr parentRow)
1596 ->
decltype(protocol.setParentRow(std::declval<row_type&>(), std::declval<row_ptr>()))
1598 return protocol.setParentRow(newRow, parentRow);
1601 template <
typename ...Args>
static constexpr void setParentRow(Args &&...) {}
1603 template <
typename D>
1604 bool insertRowImpl(
int before,
const QModelIndex &parent, D &&data)
1606 return storage.implementation()->doInsertRows(before, 1, parent, [&data,
this]
1607 (range_type &range,
auto parentRow,
int row,
int count) {
1609 const auto oldSize = range.size();
1610 auto newRow = range.emplace(QRangeModelDetails::pos(range, row), std::forward<D>(data));
1611 setParentRow(storage.implementation()->protocol(), *newRow, parentRow);
1612 return range.size() == oldSize + count;
1616 template <
typename LHS>
1617 static auto selfInsertion(LHS *lhs, LHS *rhs) ->
decltype(lhs == rhs)
1621 qCritical(
"Inserting data into itself is not supported");
1627 template <
typename LHS,
typename RHS>
1628 static constexpr bool selfInsertion(LHS *, RHS *) {
return false; }
1630 template <
typename C>
1631 bool insertRowsImpl(
int before,
const QModelIndex &parent, C &&data)
1633 bool result =
false;
1634 result = storage->doInsertRows(before,
int(std::size(data)), parent, [&data,
this]
1635 (range_type &range,
auto parentRow,
int row,
int count){
1636 Q_UNUSED(parentRow);
1638 const auto pos = QRangeModelDetails::pos(range, row);
1639 const auto oldSize = range.size();
1641 auto dataRange = [&data]{
1642 if constexpr (std::is_rvalue_reference_v<C&&>) {
1643 return std::make_pair(
1644 std::move_iterator(std::begin(data)),
1645 std::move_iterator(std::end(data))
1648 return std::make_pair(std::begin(data), std::end(data));
1652 if constexpr (range_features::has_insert_range) {
1653 if (selfInsertion(&range, &data))
1655 auto start = range.insert(pos, dataRange.first, dataRange.second);
1656 if constexpr (protocol_traits::has_setParentRow) {
1658 setParentRow(storage->protocol(), *start, parentRow);
1666 auto newRow = range.insert(pos, count, row_type{});
1667 while (dataRange.first != dataRange.second) {
1668 *newRow = *dataRange.first;
1669 setParentRow(storage->protocol(), *newRow, parentRow);
1674 return range.size() == oldSize + count;
1679 template <
typename D,
typename =
void>
1680 struct DataFromList {
1681 static constexpr auto first(D &data) {
return &data; }
1682 static constexpr auto next(D &, D *entry) {
return entry; }
1685 template <
typename D>
1686 struct DataFromList<D, std::enable_if_t<QRangeModelDetails::range_traits<D>::value>>
1688 static constexpr auto first(D &data) {
return std::begin(data); }
1689 static constexpr auto next(D &data,
typename D::iterator entry)
1692 if (entry == std::end(data))
1693 entry = first(data);
1698 template <
typename D,
typename =
void>
struct RowFromTable
1700 static constexpr auto first(D &data) {
return &data; }
1701 static constexpr auto next(D &, D *entry) {
return entry; }
1704 template <
typename D>
1705 struct RowFromTable<D, std::enable_if_t<std::conjunction_v<
1706 QRangeModelDetails::range_traits<D>,
1707 QRangeModelDetails::range_traits<
typename D::value_type>
1712 template <
typename D>
1713 bool insertColumnImpl(
int before,
const QModelIndex &parent, D data)
1715 auto entry = DataFromList<D>::first(data);
1717 return storage->doInsertColumns(before, 1, parent, [&entry, &data]
1718 (
auto &range,
auto pos,
int count) {
1719 const auto oldSize = range.size();
1720 range.insert(pos, *entry);
1721 entry = DataFromList<D>::next(data, entry);
1722 return range.size() == oldSize + count;
1726 template <
typename C>
1727 bool insertColumnsImpl(
int before,
const QModelIndex &parent, C data)
1729 bool result =
false;
1730 auto entries = RowFromTable<C>::first(data);
1731 auto begin = std::begin(*entries);
1732 auto end = std::end(*entries);
1733 result = storage->doInsertColumns(before,
int(std::size(*entries)), parent,
1734 [&begin, &end, &entries, &data](
auto &range,
auto pos,
int count) {
1735 const auto oldSize = range.size();
1736 if constexpr (row_features::has_insert_range) {
1737 range.insert(pos, begin, end);
1739 auto start = range.insert(pos, count, {});
1740 std::copy(begin, end, start);
1742 entries = RowFromTable<C>::next(data, entries);
1743 begin = std::begin(*entries);
1744 end = std::end(*entries);
1745 return range.size() == oldSize + count;