File indexing completed on 2026-08-02 09:27:24
0001
0002
0003
0004
0005 #ifndef QRANGEMODELADAPTER_H
0006 #define QRANGEMODELADAPTER_H
0007
0008 #include <QtCore/qrangemodeladapter_impl.h>
0009
0010 #include <QtCore/q26numeric.h>
0011
0012 QT_BEGIN_NAMESPACE
0013
0014 template <typename Range, typename Protocol = void, typename Model = QRangeModel>
0015 class QT_TECH_PREVIEW_API QRangeModelAdapter
0016 {
0017 using Impl = QRangeModelDetails::RangeImplementation<Range, Protocol>;
0018 using Storage = QRangeModelDetails::AdapterStorage<Model, Impl>;
0019
0020 Storage storage;
0021
0022 #ifdef Q_QDOC
0023 using range_type = Range;
0024 #else
0025 using range_type = QRangeModelDetails::wrapped_t<Range>;
0026 #endif
0027 using const_row_reference = typename Impl::const_row_reference;
0028 using row_reference = typename Impl::row_reference;
0029 using range_features = typename QRangeModelDetails::range_traits<range_type>;
0030 using row_type = std::remove_reference_t<row_reference>;
0031 using row_features = QRangeModelDetails::range_traits<typename Impl::wrapped_row_type>;
0032 using row_ptr = typename Impl::wrapped_row_type *;
0033 using row_traits = typename Impl::row_traits;
0034 using item_type = std::remove_reference_t<typename row_traits::item_type>;
0035 using data_type = typename QRangeModelDetails::data_type<item_type>::type;
0036 using const_data_type = QRangeModelDetails::asConst_t<data_type>;
0037 using protocol_traits = typename Impl::protocol_traits;
0038
0039 template <typename I> static constexpr bool is_list = I::protocol_traits::is_list;
0040 template <typename I> static constexpr bool is_table = I::protocol_traits::is_table;
0041 template <typename I> static constexpr bool is_tree = I::protocol_traits::is_tree;
0042 template <typename I> static constexpr bool canInsertColumns = I::dynamicColumns()
0043 && I::isMutable()
0044 && row_features::has_insert;
0045 template <typename I> static constexpr bool canRemoveColumns = I::dynamicColumns()
0046 && I::isMutable()
0047 && row_features::has_erase;
0048
0049 template <typename I> using if_writable = std::enable_if_t<I::isMutable(), bool>;
0050 template <typename I> using if_list = std::enable_if_t<is_list<I>, bool>;
0051 template <typename I> using unless_list = std::enable_if_t<!is_list<I>, bool>;
0052 template <typename I> using if_table = std::enable_if_t<is_table<I>, bool>;
0053 template <typename I> using if_tree = std::enable_if_t<is_tree<I>, bool>;
0054 template <typename I> using unless_tree = std::enable_if_t<!is_tree<I>, bool>;
0055 template <typename I> using if_flat = std::enable_if_t<is_list<I> || is_table<I>, bool>;
0056
0057 template <typename I>
0058 using if_canInsertRows = std::enable_if_t<I::canInsertRows(), bool>;
0059 template <typename I>
0060 using if_canRemoveRows = std::enable_if_t<I::canRemoveRows(), bool>;
0061 template <typename F>
0062 using if_canMoveItems = std::enable_if_t<F::has_rotate || F::has_splice, bool>;
0063
0064 template <typename I>
0065 using if_canInsertColumns = std::enable_if_t<canInsertColumns<I>, bool>;
0066 template <typename I>
0067 using if_canRemoveColumns = std::enable_if_t<canRemoveColumns<I>, bool>;
0068
0069 template <typename Row>
0070 static constexpr bool is_compatible_row = std::is_convertible_v<Row, const_row_reference>;
0071 template <typename Row>
0072 using if_compatible_row = std::enable_if_t<is_compatible_row<Row>, bool>;
0073
0074 template <typename C>
0075 static constexpr bool is_compatible_row_range = is_compatible_row<
0076 decltype(*std::begin(std::declval<C&>()))
0077 >;
0078 template <typename C>
0079 using if_compatible_row_range = std::enable_if_t<is_compatible_row_range<C>, bool>;
0080 template <typename Data>
0081 static constexpr bool is_compatible_data = std::is_convertible_v<Data, data_type>;
0082 template <typename Data>
0083 using if_compatible_data = std::enable_if_t<is_compatible_data<Data>, bool>;
0084 template <typename C>
0085 static constexpr bool is_compatible_data_range = is_compatible_data<
0086 typename QRangeModelDetails::data_type<
0087 typename QRangeModelDetails::row_traits<
0088 decltype(*std::begin(std::declval<C&>()))
0089 >::item_type
0090 >::type
0091 >;
0092 template <typename C>
0093 using if_compatible_column_data = std::enable_if_t<is_compatible_data<C>
0094 || is_compatible_data_range<C>, bool>;
0095 template <typename C>
0096 using if_compatible_column_range = std::enable_if_t<is_compatible_data_range<C>, bool>;
0097
0098 template <typename R>
0099 using if_assignable_range = std::enable_if_t<std::is_assignable_v<range_type, R>, bool>;
0100
0101 friend class QRangeModel;
0102 template <typename T>
0103 static constexpr bool is_adapter = QRangeModelDetails::is_any_of<q20::remove_cvref_t<T>,
0104 QRangeModelAdapter>::value;
0105 template <typename T>
0106 using unless_adapter = std::enable_if_t<!is_adapter<T>, bool>;
0107
0108 template <typename R, typename P>
0109 using if_compatible_model_params =
0110 std::enable_if_t<
0111 std::conjunction_v<
0112 std::disjunction<
0113 std::is_convertible<R &&, Range>,
0114 std::is_convertible<R &&, Range &&>
0115 >,
0116 std::is_convertible<P, Protocol>
0117 >, bool>;
0118
0119 #if !defined(Q_OS_VXWORKS) && !defined(Q_OS_INTEGRITY)
0120
0121
0122
0123
0124
0125 template <typename T> static constexpr T asMutable(const T &);
0126 template <typename T> static constexpr T *asMutable(const T *);
0127 template <template <typename, typename...> typename U, typename T, typename ...Args>
0128 static constexpr U<T, Args...> asMutable(const U<const T, Args...> &);
0129
0130 template <typename T>
0131 using asMutable_t = decltype(asMutable(std::declval<T>()));
0132 friend class QRangeModelAdapter<asMutable_t<Range>, Protocol, Model>;
0133 #else
0134 template <typename R, typename P, typename M>
0135 friend class QRangeModelAdapter;
0136 #endif
0137
0138 explicit QRangeModelAdapter(const std::shared_ptr<QRangeModel> &model, const QModelIndex &root,
0139 std::in_place_t)
0140 : storage{model, root}
0141 {}
0142
0143 explicit QRangeModelAdapter(QRangeModel *model)
0144 : storage(model)
0145 {}
0146
0147 public:
0148 struct DataReference
0149 {
0150 #ifdef Q_QDOC
0151 using value_type = int;
0152 using const_value_type = const int;
0153 using pointer = void *;
0154 #else
0155 using value_type = data_type;
0156 using const_value_type = const_data_type;
0157 using pointer = QRangeModelDetails::data_pointer_t<const_value_type>;
0158 #endif
0159
0160 explicit DataReference(const QModelIndex &index) noexcept
0161 : m_index(index)
0162 {}
0163
0164 DataReference(const DataReference &other) = default;
0165 DataReference(DataReference &&other) = default;
0166
0167
0168 DataReference &operator=(const DataReference &other)
0169 {
0170 *this = other.get();
0171 return *this;
0172 }
0173
0174 DataReference &operator=(DataReference &&other)
0175 {
0176 *this = other.get();
0177 return *this;
0178 }
0179
0180 ~DataReference() = default;
0181
0182 DataReference &operator=(const value_type &value)
0183 {
0184 assign(value);
0185 return *this;
0186 }
0187
0188 DataReference &operator=(value_type &&value)
0189 {
0190 assign(std::move(value));
0191 return *this;
0192 }
0193
0194 const_value_type get() const
0195 {
0196 Q_ASSERT_X(m_index.isValid(), "QRangeModelAdapter::at", "Index at position is invalid");
0197 return QRangeModelDetails::dataAtIndex<q20::remove_cvref_t<value_type>>(m_index);
0198 }
0199
0200 operator const_value_type() const
0201 {
0202 return get();
0203 }
0204
0205 pointer operator->() const
0206 {
0207 return {get()};
0208 }
0209
0210 bool isValid() const { return m_index.isValid(); }
0211
0212 private:
0213 QModelIndex m_index;
0214
0215 template <typename Value>
0216 void assign(Value &&value)
0217 {
0218 constexpr Qt::ItemDataRole dataRole = Qt::RangeModelAdapterRole;
0219
0220 if (m_index.isValid()) {
0221 auto model = const_cast<QAbstractItemModel *>(m_index.model());
0222 [[maybe_unused]] bool couldWrite = false;
0223 if constexpr (std::is_same_v<q20::remove_cvref_t<Value>, QVariant>) {
0224 couldWrite = model->setData(m_index, value, dataRole);
0225 } else {
0226 couldWrite = model->setData(m_index,
0227 QVariant::fromValue(std::forward<Value>(value)),
0228 dataRole);
0229 }
0230 #ifndef QT_NO_DEBUG
0231 if (!couldWrite) {
0232 qWarning() << "Writing value of type"
0233 << QMetaType::fromType<q20::remove_cvref_t<Value>>().name()
0234 << "to role" << dataRole << "at index" << m_index << "failed";
0235 }
0236 } else {
0237 qCritical("Data reference for invalid index, can't write to model");
0238 #endif
0239 }
0240 }
0241
0242 friend inline bool comparesEqual(const DataReference &lhs, const DataReference &rhs)
0243 {
0244 return lhs.m_index == rhs.m_index
0245 || lhs.get() == rhs.get();
0246 }
0247 Q_DECLARE_EQUALITY_COMPARABLE_NON_NOEXCEPT(DataReference);
0248
0249 friend inline bool comparesEqual(const DataReference &lhs, const value_type &rhs)
0250 {
0251 return lhs.get() == rhs;
0252 }
0253 Q_DECLARE_EQUALITY_COMPARABLE_NON_NOEXCEPT(DataReference, value_type);
0254
0255 friend inline void swap(DataReference lhs, DataReference rhs)
0256 {
0257 const value_type lhsValue = lhs.get();
0258 lhs = rhs;
0259 rhs = lhsValue;
0260 }
0261
0262 #ifndef QT_NO_DEBUG_STREAM
0263 friend inline QDebug operator<<(QDebug dbg, const DataReference &ref)
0264 {
0265 return dbg << ref.get();
0266 }
0267 #endif
0268 #ifndef QT_NO_DATASTREAM
0269 friend inline QDataStream &operator<<(QDataStream &ds, const DataReference &ref)
0270 {
0271 return ds << ref.get();
0272 }
0273 friend inline QDataStream &operator>>(QDataStream &ds, DataReference &ref)
0274 {
0275 value_type value;
0276 ds >> value;
0277 ref = std::move(value);
0278 return ds;
0279 }
0280 #endif
0281 };
0282 template <typename Iterator, typename Adapter>
0283 struct ColumnIteratorBase
0284 {
0285 using iterator_category = std::random_access_iterator_tag;
0286 using difference_type = int;
0287
0288 ColumnIteratorBase() = default;
0289 ColumnIteratorBase(const ColumnIteratorBase &other) = default;
0290 ColumnIteratorBase(ColumnIteratorBase &&other) = default;
0291 ColumnIteratorBase &operator=(const ColumnIteratorBase &other) = default;
0292 ColumnIteratorBase &operator=(ColumnIteratorBase &&other) = default;
0293
0294 ColumnIteratorBase(const QModelIndex &rowIndex, int column, Adapter *adapter) noexcept
0295 : m_rowIndex(rowIndex), m_column(column), m_adapter(adapter)
0296 {
0297 }
0298
0299 void swap(ColumnIteratorBase &other) noexcept
0300 {
0301 std::swap(m_rowIndex, other.m_rowIndex);
0302 std::swap(m_column, other.m_column);
0303 q_ptr_swap(m_adapter, other.m_adapter);
0304 }
0305
0306 friend Iterator &operator++(Iterator &that)
0307 {
0308 ++that.m_column;
0309 return that;
0310 }
0311 friend Iterator operator++(Iterator &that, int)
0312 {
0313 auto copy = that;
0314 ++that;
0315 return copy;
0316 }
0317 friend Iterator operator+(const Iterator &that, difference_type n)
0318 {
0319 return {that.m_rowIndex, that.m_column + n, that.m_adapter};
0320 }
0321 friend Iterator operator+(difference_type n, const Iterator &that)
0322 {
0323 return that + n;
0324 }
0325 friend Iterator &operator+=(Iterator &that, difference_type n)
0326 {
0327 that.m_column += n;
0328 return that;
0329 }
0330
0331 friend Iterator &operator--(Iterator &that)
0332 {
0333 --that.m_column;
0334 return that;
0335 }
0336 friend Iterator operator--(Iterator &that, int)
0337 {
0338 auto copy = that;
0339 --that;
0340 return copy;
0341 }
0342 friend Iterator operator-(const Iterator &that, difference_type n)
0343 {
0344 return {that.m_rowIndex, that.m_column - n, that.m_adapter};
0345 }
0346 friend Iterator operator-(difference_type n, const Iterator &that)
0347 {
0348 return that - n;
0349 }
0350 friend Iterator &operator-=(Iterator &that, difference_type n)
0351 {
0352 that.m_column -= n;
0353 return that;
0354 }
0355
0356 friend difference_type operator-(const Iterator &lhs, const Iterator &rhs)
0357 {
0358 Q_PRE(lhs.m_rowIndex == rhs.m_rowIndex);
0359 Q_PRE(lhs.m_adapter == rhs.m_adapter);
0360 return lhs.m_column - rhs.m_column;
0361 }
0362
0363 protected:
0364 ~ColumnIteratorBase() = default;
0365 QModelIndex m_rowIndex;
0366 int m_column = -1;
0367 Adapter *m_adapter = nullptr;
0368
0369 private:
0370 friend bool comparesEqual(const Iterator &lhs, const Iterator &rhs)
0371 {
0372 Q_ASSERT(lhs.m_rowIndex == rhs.m_rowIndex);
0373 return lhs.m_column == rhs.m_column;
0374 }
0375 friend Qt::strong_ordering compareThreeWay(const Iterator &lhs, const Iterator &rhs)
0376 {
0377 Q_ASSERT(lhs.m_rowIndex == rhs.m_rowIndex);
0378 return qCompareThreeWay(lhs.m_column, rhs.m_column);
0379 }
0380
0381 Q_DECLARE_STRONGLY_ORDERED_NON_NOEXCEPT(Iterator)
0382
0383 #ifndef QT_NO_DEBUG_STREAM
0384 friend inline QDebug operator<<(QDebug dbg, const Iterator &it)
0385 {
0386 QDebugStateSaver saver(dbg);
0387 dbg.nospace();
0388 return dbg << "ColumnIterator(" << it.m_rowIndex.siblingAtColumn(it.m_column) << ")";
0389 }
0390 #endif
0391 };
0392
0393 struct ConstColumnIterator : ColumnIteratorBase<ConstColumnIterator, const QRangeModelAdapter>
0394 {
0395 private:
0396 using Base = ColumnIteratorBase<ConstColumnIterator, const QRangeModelAdapter>;
0397 public:
0398 using difference_type = typename Base::difference_type;
0399 using value_type = data_type;
0400 using reference = const_data_type;
0401 using pointer = QRangeModelDetails::data_pointer_t<value_type>;
0402
0403 using Base::Base;
0404 using Base::operator=;
0405 ~ConstColumnIterator() = default;
0406
0407 pointer operator->() const
0408 {
0409 return pointer{operator*()};
0410 }
0411
0412 reference operator*() const
0413 {
0414 return std::as_const(this->m_adapter)->at(this->m_rowIndex.row(), this->m_column);
0415 }
0416
0417 reference operator[](difference_type n) const
0418 {
0419 return *(*this + n);
0420 }
0421 };
0422
0423 struct ColumnIterator : ColumnIteratorBase<ColumnIterator, QRangeModelAdapter>
0424 {
0425 private:
0426 using Base = ColumnIteratorBase<ColumnIterator, QRangeModelAdapter>;
0427 public:
0428 using difference_type = typename Base::difference_type;
0429 using value_type = DataReference;
0430 using reference = DataReference;
0431 using pointer = reference;
0432
0433 using Base::Base;
0434 using Base::operator=;
0435 ~ColumnIterator() = default;
0436
0437 operator ConstColumnIterator() const
0438 {
0439 return ConstColumnIterator{this->m_rowIndex, this->m_column, this->m_adapter};
0440 }
0441
0442 pointer operator->() const
0443 {
0444 return operator*();
0445 }
0446
0447 reference operator*() const
0448 {
0449 return reference{this->m_rowIndex.siblingAtColumn(this->m_column)};
0450 }
0451
0452 reference operator[](difference_type n) const
0453 {
0454 return *(*this + n);
0455 }
0456 };
0457
0458 template <typename Reference, typename const_row_type, typename = void>
0459 struct RowGetter
0460 {
0461 const_row_type get() const
0462 {
0463 const Reference *that = static_cast<const Reference *>(this);
0464 const auto *impl = that->m_adapter->storage.implementation();
0465 auto *childRange = impl->childRange(that->m_index.parent());
0466 if constexpr (std::is_convertible_v<const row_type &, const_row_type>) {
0467 return *std::next(QRangeModelDetails::adl_begin(childRange), that->m_index.row());
0468 } else {
0469 const auto &row = *std::next(QRangeModelDetails::adl_begin(childRange),
0470 that->m_index.row());
0471 return const_row_type{QRangeModelDetails::adl_begin(row),
0472 QRangeModelDetails::adl_end(row)};
0473 }
0474 }
0475
0476 const_row_type operator->() const
0477 {
0478 return {get()};
0479 }
0480
0481 operator const_row_type() const
0482 {
0483 return get();
0484 }
0485 };
0486
0487 template <typename Reference, typename const_row_type>
0488 struct RowGetter<Reference, const_row_type,
0489 std::enable_if_t<std::is_reference_v<const_row_type>>>
0490 {
0491 const_row_type get() const
0492 {
0493 const Reference *that = static_cast<const Reference *>(this);
0494 const auto *impl = that->m_adapter->storage.implementation();
0495 return *std::next(QRangeModelDetails::begin(
0496 QRangeModelDetails::refTo(impl->childRange(that->m_index.parent()))),
0497 that->m_index.row());
0498 }
0499
0500 auto operator->() const
0501 {
0502 return std::addressof(get());
0503 }
0504
0505 operator const_row_type() const
0506 {
0507 return get();
0508 }
0509 };
0510
0511 template <typename Reference, typename const_row_type>
0512 struct RowGetter<Reference, const_row_type,
0513 std::enable_if_t<std::is_pointer_v<const_row_type>>>
0514 {
0515 const_row_type get() const
0516 {
0517 const Reference *that = static_cast<const Reference *>(this);
0518 const auto *impl = that->m_adapter->storage.implementation();
0519 return *std::next(QRangeModelDetails::begin(
0520 QRangeModelDetails::refTo(impl->childRange(that->m_index.parent()))),
0521 that->m_index.row());
0522 }
0523
0524 const_row_type operator->() const
0525 {
0526 return get();
0527 }
0528
0529 operator const_row_type() const
0530 {
0531 return get();
0532 }
0533 };
0534
0535 template <typename Reference, typename Adapter>
0536 struct RowReferenceBase : RowGetter<Reference, QRangeModelDetails::asConstRow_t<row_type>>
0537 {
0538 using const_iterator = ConstColumnIterator;
0539 using size_type = int;
0540 using difference_type = int;
0541 using const_row_type = QRangeModelDetails::asConstRow_t<row_type>;
0542
0543 RowReferenceBase(const QModelIndex &index, Adapter *adapter) noexcept
0544 : m_index(index), m_adapter(adapter)
0545 {}
0546
0547 template <typename I = Impl, if_tree<I> = true>
0548 bool hasChildren() const
0549 {
0550 return m_adapter->model()->hasChildren(m_index);
0551 }
0552
0553 template <typename I = Impl, if_tree<I> = true>
0554 auto children() const
0555 {
0556 using ConstRange = QRangeModelDetails::asConst_t<Range>;
0557 return QRangeModelAdapter<ConstRange, Protocol, Model>(m_adapter->storage.m_model,
0558 m_index, std::in_place);
0559 }
0560
0561 ConstColumnIterator cbegin() const
0562 {
0563 return ConstColumnIterator{m_index, 0, m_adapter};
0564 }
0565 ConstColumnIterator cend() const
0566 {
0567 return ConstColumnIterator{m_index, m_adapter->columnCount(), m_adapter};
0568 }
0569
0570 ConstColumnIterator begin() const { return cbegin(); }
0571 ConstColumnIterator end() const { return cend(); }
0572
0573 size_type size() const
0574 {
0575 return m_adapter->columnCount();
0576 }
0577
0578 auto at(int column) const
0579 {
0580 Q_ASSERT(column >= 0 && column < m_adapter->columnCount());
0581 return *ConstColumnIterator{m_index, column, m_adapter};
0582 }
0583
0584 auto operator[](int column) const
0585 {
0586 return at(column);
0587 }
0588
0589 protected:
0590 friend struct RowGetter<Reference, const_row_type>;
0591 ~RowReferenceBase() = default;
0592 QModelIndex m_index;
0593 Adapter *m_adapter;
0594
0595 private:
0596 friend bool comparesEqual(const Reference &lhs, const Reference &rhs)
0597 {
0598 Q_ASSERT(lhs.m_adapter == rhs.m_adapter);
0599 return lhs.m_index == rhs.m_index;
0600 }
0601 friend Qt::strong_ordering compareThreeWay(const Reference &lhs, const Reference &rhs)
0602 {
0603 Q_ASSERT(lhs.m_adapter == rhs.m_adapter);
0604 return qCompareThreeWay(lhs.m_index, rhs.m_index);
0605 }
0606
0607 Q_DECLARE_STRONGLY_ORDERED_NON_NOEXCEPT(Reference)
0608
0609 friend bool comparesEqual(const Reference &lhs, const row_type &rhs)
0610 {
0611 return lhs.get() == rhs;
0612 }
0613 Q_DECLARE_EQUALITY_COMPARABLE_NON_NOEXCEPT(Reference, row_type)
0614
0615 #ifndef QT_NO_DEBUG_STREAM
0616 friend inline QDebug operator<<(QDebug dbg, const Reference &ref)
0617 {
0618 QDebugStateSaver saver(dbg);
0619 dbg.nospace();
0620 return dbg << "RowReference(" << ref.m_index << ")";
0621 }
0622 #endif
0623 #ifndef QT_NO_DATASTREAM
0624 friend inline QDataStream &operator<<(QDataStream &ds, const Reference &ref)
0625 {
0626 return ds << ref.get();
0627 }
0628 #endif
0629 };
0630
0631 struct ConstRowReference : RowReferenceBase<ConstRowReference, const QRangeModelAdapter>
0632 {
0633 private:
0634 using Base = RowReferenceBase<ConstRowReference, const QRangeModelAdapter>;
0635 public:
0636 using Base::Base;
0637
0638 ConstRowReference() = default;
0639 ConstRowReference(const ConstRowReference &) = default;
0640 ConstRowReference(ConstRowReference &&) = default;
0641 ConstRowReference &operator=(const ConstRowReference &) = default;
0642 ConstRowReference &operator=(ConstRowReference &&) = default;
0643 ~ConstRowReference() = default;
0644 };
0645
0646 struct RowReference : RowReferenceBase<RowReference, QRangeModelAdapter>
0647 {
0648 private:
0649 using Base = RowReferenceBase<RowReference, QRangeModelAdapter>;
0650 public:
0651 using iterator = ColumnIterator;
0652 using const_iterator = typename Base::const_iterator;
0653 using size_type = typename Base::size_type;
0654 using difference_type = typename Base::difference_type;
0655 #ifdef Q_QDOC
0656 using row_type = int;
0657 #endif
0658 using const_row_type = typename Base::const_row_type;
0659
0660 using Base::Base;
0661 RowReference() = delete;
0662 ~RowReference() = default;
0663 RowReference(const RowReference &other) = default;
0664 RowReference(RowReference &&other) = default;
0665
0666
0667 RowReference &operator=(const ConstRowReference &other)
0668 {
0669 *this = other.get();
0670 return *this;
0671 }
0672
0673 RowReference &operator=(const RowReference &other)
0674 {
0675 *this = other.get();
0676 return *this;
0677 }
0678
0679 RowReference &operator=(const row_type &other)
0680 {
0681 assign(other);
0682 return *this;
0683 }
0684
0685 RowReference &operator=(row_type &&other)
0686 {
0687 assign(std::move(other));
0688 return *this;
0689 }
0690
0691 operator ConstRowReference() const
0692 {
0693 return ConstRowReference{this->m_index, this->m_adapter};
0694 }
0695
0696 template <typename ConstRowType = const_row_type,
0697 std::enable_if_t<!std::is_same_v<ConstRowType, const row_type &>, bool> = true>
0698 RowReference &operator=(const ConstRowType &other)
0699 {
0700 assign(other);
0701 return *this;
0702 }
0703
0704 template <typename T, typename It, typename Sentinel>
0705 RowReference &operator=(const QRangeModelDetails::RowView<T, It, Sentinel> &other)
0706 {
0707 *this = row_type{other.begin(), other.end()};
0708 return *this;
0709 }
0710
0711 friend inline void swap(RowReference lhs, RowReference rhs)
0712 {
0713 auto lhsRow = lhs.get();
0714 lhs = rhs.get();
0715 rhs = std::move(lhsRow);
0716 }
0717
0718 template <typename I = Impl, if_tree<I> = true>
0719 auto children()
0720 {
0721 return QRangeModelAdapter(this->m_adapter->storage.m_model, this->m_index,
0722 std::in_place);
0723 }
0724
0725 using Base::begin;
0726 ColumnIterator begin()
0727 {
0728 return ColumnIterator{this->m_index, 0, this->m_adapter};
0729 }
0730
0731 using Base::end;
0732 ColumnIterator end()
0733 {
0734 return ColumnIterator{this->m_index, this->m_adapter->columnCount(), this->m_adapter};
0735 }
0736
0737 using Base::at;
0738 auto at(int column)
0739 {
0740 Q_ASSERT(column >= 0 && column < this->m_adapter->columnCount());
0741 return *ColumnIterator{this->m_index, column, this->m_adapter};
0742 }
0743
0744 using Base::operator[];
0745 auto operator[](int column)
0746 {
0747 return at(column);
0748 }
0749
0750 private:
0751 template <typename RHS>
0752 void verifyRows(const row_type &oldRow, const RHS &newRow)
0753 {
0754 if constexpr (QRangeModelDetails::test_size<row_type>::value) {
0755
0756 Q_ASSERT_X(Impl::size(newRow) == Impl::size(oldRow),
0757 "RowReference::operator=()",
0758 "The new row has the wrong size!");
0759 }
0760
0761 if constexpr (is_tree<Impl>) {
0762
0763 Q_ASSERT_X(QRangeModelDetails::isValid(newRow),
0764 "RowReference::operator=()",
0765 "An invalid row can not inserted into a tree!");
0766 }
0767 }
0768
0769 template <typename R>
0770 void assign(R &&other)
0771 {
0772 auto *impl = this->m_adapter->storage.implementation();
0773 decltype(auto) oldRow = impl->rowData(this->m_index);
0774
0775 verifyRows(oldRow, other);
0776
0777 if constexpr (is_tree<Impl>) {
0778 auto &protocol = impl->protocol();
0779 auto *oldParent = protocol.parentRow(QRangeModelDetails::refTo(oldRow));
0780
0781
0782
0783 if (decltype(auto) oldChildren = protocol.childRows(QRangeModelDetails::refTo(oldRow));
0784 QRangeModelDetails::isValid(oldChildren)) {
0785 if (int oldChildCount = this->m_adapter->model()->rowCount(this->m_index)) {
0786 impl->beginRemoveRows(this->m_index, 0, oldChildCount - 1);
0787 impl->deleteRemovedRows(QRangeModelDetails::refTo(oldChildren));
0788
0789 QRangeModelDetails::refTo(oldChildren) = range_type{};
0790 impl->endRemoveRows();
0791 }
0792 }
0793
0794 if constexpr (protocol_traits::has_deleteRow)
0795 protocol.deleteRow(oldRow);
0796 oldRow = std::forward<R>(other);
0797 if constexpr (protocol_traits::has_setParentRow) {
0798 protocol.setParentRow(QRangeModelDetails::refTo(oldRow),
0799 QRangeModelDetails::pointerTo(oldParent));
0800 if (decltype(auto) newChildren = protocol.childRows(QRangeModelDetails::refTo(oldRow));
0801 QRangeModelDetails::isValid(newChildren)) {
0802 impl->beginInsertRows(this->m_index, 0,
0803 Impl::size(QRangeModelDetails::refTo(newChildren)) - 1);
0804 impl->setParentRow(QRangeModelDetails::refTo(newChildren),
0805 QRangeModelDetails::pointerTo(oldRow));
0806 impl->endInsertRows();
0807 }
0808 }
0809 } else {
0810 oldRow = std::forward<R>(other);
0811 }
0812 this->m_adapter->emitDataChanged(this->m_index,
0813 this->m_index.siblingAtColumn(this->m_adapter->columnCount() - 1));
0814 if constexpr (Impl::itemsAreQObjects) {
0815 if (this->m_adapter->model()->autoConnectPolicy() == QRangeModel::AutoConnectPolicy::Full) {
0816 impl->autoConnectPropertiesInRow(oldRow, this->m_index.row(), this->m_index.parent());
0817 if constexpr (is_tree<Impl>)
0818 impl->autoConnectProperties(this->m_index);
0819 }
0820
0821 }
0822 }
0823
0824 #ifndef QT_NO_DATASTREAM
0825 friend inline QDataStream &operator>>(QDataStream &ds, RowReference &ref)
0826 {
0827 row_type value;
0828 ds >> value;
0829 ref = value;
0830 return ds;
0831 }
0832 #endif
0833 };
0834
0835 template <typename Iterator, typename Adapter>
0836 struct RowIteratorBase : QRangeModelDetails::ParentIndex<is_tree<Impl>>
0837 {
0838 using iterator_category = std::random_access_iterator_tag;
0839 using difference_type = int;
0840
0841 RowIteratorBase() = default;
0842 RowIteratorBase(const RowIteratorBase &) = default;
0843 RowIteratorBase(RowIteratorBase &&) = default;
0844 RowIteratorBase &operator=(const RowIteratorBase &) = default;
0845 RowIteratorBase &operator=(RowIteratorBase &&) = default;
0846
0847 RowIteratorBase(int row, const QModelIndex &parent, Adapter *adapter)
0848 : QRangeModelDetails::ParentIndex<is_tree<Impl>>{parent}
0849 , m_row(row), m_adapter(adapter)
0850 {}
0851
0852 void swap(RowIteratorBase &other) noexcept
0853 {
0854 qSwap(m_row, other.m_row);
0855 qSwap(this->m_rootIndex, other.m_rootIndex);
0856 q_ptr_swap(m_adapter, other.m_adapter);
0857 }
0858
0859 friend Iterator &operator++(Iterator &that)
0860 {
0861 ++that.m_row;
0862 return that;
0863 }
0864 friend Iterator operator++(Iterator &that, int)
0865 {
0866 auto copy = that;
0867 ++that;
0868 return copy;
0869 }
0870 friend Iterator operator+(const Iterator &that, difference_type n)
0871 {
0872 return {that.m_row + n, that.root(), that.m_adapter};
0873 }
0874 friend Iterator operator+(difference_type n, const Iterator &that)
0875 {
0876 return that + n;
0877 }
0878 friend Iterator &operator+=(Iterator &that, difference_type n)
0879 {
0880 that.m_row += n;
0881 return that;
0882 }
0883
0884 friend Iterator &operator--(Iterator &that)
0885 {
0886 --that.m_row;
0887 return that;
0888 }
0889 friend Iterator operator--(Iterator &that, int)
0890 {
0891 auto copy = that;
0892 --that;
0893 return copy;
0894 }
0895 friend Iterator operator-(const Iterator &that, difference_type n)
0896 {
0897 return {that.m_row - n, that.root(), that.m_adapter};
0898 }
0899 friend Iterator operator-(difference_type n, const Iterator &that)
0900 {
0901 return that - n;
0902 }
0903 friend Iterator &operator-=(Iterator &that, difference_type n)
0904 {
0905 that.m_row -= n;
0906 return that;
0907 }
0908
0909 friend difference_type operator-(const Iterator &lhs, const Iterator &rhs)
0910 {
0911 return lhs.m_row - rhs.m_row;
0912 }
0913
0914 protected:
0915 ~RowIteratorBase() = default;
0916 int m_row = -1;
0917 Adapter *m_adapter = nullptr;
0918
0919 private:
0920 friend bool comparesEqual(const Iterator &lhs, const Iterator &rhs) noexcept
0921 {
0922 return lhs.m_row == rhs.m_row && lhs.root() == rhs.root();
0923 }
0924 friend Qt::strong_ordering compareThreeWay(const Iterator &lhs, const Iterator &rhs) noexcept
0925 {
0926 if (lhs.root() == rhs.root())
0927 return qCompareThreeWay(lhs.m_row, rhs.m_row);
0928 return qCompareThreeWay(lhs.root(), rhs.root());
0929 }
0930
0931 Q_DECLARE_STRONGLY_ORDERED(Iterator)
0932
0933 #ifndef QT_NO_DEBUG_STREAM
0934 friend inline QDebug operator<<(QDebug dbg, const Iterator &it)
0935 {
0936 QDebugStateSaver saver(dbg);
0937 dbg.nospace();
0938 return dbg << "RowIterator(" << it.m_row << it.root() << ")";
0939 }
0940 #endif
0941 };
0942
0943 public:
0944 struct ConstRowIterator : public RowIteratorBase<ConstRowIterator, const QRangeModelAdapter>
0945 {
0946 private:
0947 using Base = RowIteratorBase<ConstRowIterator, const QRangeModelAdapter>;
0948 public:
0949 using Base::Base;
0950
0951 using difference_type = typename Base::difference_type;
0952 using value_type = std::conditional_t<is_list<Impl>,
0953 const_data_type,
0954 ConstRowReference>;
0955 using reference = std::conditional_t<is_list<Impl>,
0956 const_data_type,
0957 ConstRowReference>;
0958 using pointer = std::conditional_t<is_list<Impl>,
0959 QRangeModelDetails::data_pointer_t<const_data_type>,
0960 ConstRowReference>;
0961
0962 ConstRowIterator(const ConstRowIterator &other) = default;
0963 ConstRowIterator(ConstRowIterator &&other) = default;
0964 ConstRowIterator &operator=(const ConstRowIterator &other) = default;
0965 ConstRowIterator &operator=(ConstRowIterator &&other) = default;
0966 ~ConstRowIterator() = default;
0967
0968 pointer operator->() const
0969 {
0970 return pointer{operator*()};
0971 }
0972
0973 reference operator*() const
0974 {
0975 if constexpr (is_list<Impl>) {
0976 return this->m_adapter->at(this->m_row);
0977 } else {
0978 const QModelIndex index = this->m_adapter->model()->index(this->m_row, 0,
0979 this->root());
0980 return ConstRowReference{index, this->m_adapter};
0981 }
0982 }
0983
0984 reference operator[](difference_type n) const
0985 {
0986 return *(*this + n);
0987 }
0988 };
0989
0990 struct RowIterator : public RowIteratorBase<RowIterator, QRangeModelAdapter>
0991 {
0992 private:
0993 using Base = RowIteratorBase<RowIterator, QRangeModelAdapter>;
0994 public:
0995 using Base::Base;
0996
0997 using difference_type = typename Base::difference_type;
0998 using value_type = std::conditional_t<is_list<Impl>,
0999 DataReference,
1000 RowReference>;
1001 using reference = std::conditional_t<is_list<Impl>,
1002 DataReference,
1003 RowReference>;
1004 using pointer = std::conditional_t<is_list<Impl>,
1005 DataReference,
1006 RowReference>;
1007
1008 RowIterator(const RowIterator &other) = default;
1009 RowIterator(RowIterator &&other) = default;
1010 RowIterator &operator=(const RowIterator &other) = default;
1011 RowIterator &operator=(RowIterator &&other) = default;
1012 ~RowIterator() = default;
1013
1014 operator ConstRowIterator() const
1015 {
1016 return ConstRowIterator{this->m_row, this->root(), this->m_adapter};
1017 }
1018
1019 pointer operator->() const
1020 {
1021 return pointer{operator*()};
1022 }
1023
1024 reference operator*() const
1025 {
1026 const QModelIndex index = this->m_adapter->model()->index(this->m_row, 0, this->root());
1027 if constexpr (is_list<Impl>) {
1028 return reference{index};
1029 } else {
1030 return reference{index, this->m_adapter};
1031 }
1032 }
1033
1034 reference operator[](difference_type n) const
1035 {
1036 return *(*this + n);
1037 }
1038 };
1039
1040 using const_iterator = ConstRowIterator;
1041 using iterator = RowIterator;
1042
1043 template <typename R,
1044 typename P,
1045 if_compatible_model_params<R, P> = true>
1046 explicit QRangeModelAdapter(R &&range, P &&protocol)
1047 : QRangeModelAdapter(new Model(QRangeModelDetails::forwardOrConvert<Range>(std::forward<R>(range)),
1048 QRangeModelDetails::forwardOrConvert<Protocol>(std::forward<P>(protocol))))
1049 {}
1050
1051 template <typename R,
1052 typename P = void,
1053 if_compatible_model_params<R, P> = true,
1054 unless_adapter<R> = true>
1055 explicit QRangeModelAdapter(R &&range)
1056 : QRangeModelAdapter(new Model(QRangeModelDetails::forwardOrConvert<Range>(std::forward<R>(range))))
1057 {}
1058
1059
1060
1061 Model *model() const
1062 {
1063 return storage.m_model.get();
1064 }
1065
1066 const range_type &range() const
1067 {
1068 return QRangeModelDetails::refTo(storage.implementation()->childRange(storage.root()));
1069 }
1070
1071 template <typename NewRange = range_type, if_assignable_range<NewRange> = true>
1072 void assign(NewRange &&newRange)
1073 {
1074 assignImpl(qsizetype(Impl::size(QRangeModelDetails::refTo(newRange))),
1075 [&newRange](auto &oldRange) {
1076 oldRange = std::forward<NewRange>(newRange);
1077 });
1078 }
1079
1080 template <typename NewRange = range_type, if_assignable_range<NewRange> = true,
1081 unless_adapter<NewRange> = true>
1082 QRangeModelAdapter &operator=(NewRange &&newRange)
1083 {
1084 assign(std::forward<NewRange>(newRange));
1085 return *this;
1086 }
1087
1088 template <typename Row, if_assignable_range<std::initializer_list<Row>> = true>
1089 void assign(std::initializer_list<Row> newRange)
1090 {
1091 assignImpl(newRange.size(), [&newRange](auto &oldRange) {
1092 oldRange = newRange;
1093 });
1094 }
1095
1096 template <typename Row, if_assignable_range<std::initializer_list<Row>> = true>
1097 QRangeModelAdapter &operator=(std::initializer_list<Row> newRange)
1098 {
1099 assign(newRange);
1100 return *this;
1101 }
1102
1103 template <typename InputIterator, typename Sentinel, typename I = Impl, if_writable<I> = true>
1104 void assign(InputIterator first, Sentinel last)
1105 {
1106 assignImpl(size_t(std::distance(first, last)), [first, last](auto &oldRange) {
1107 oldRange.assign(first, last);
1108 });
1109 }
1110
1111
1112 ConstRowIterator cbegin() const
1113 {
1114 return ConstRowIterator{ 0, storage.root(), this };
1115 }
1116 ConstRowIterator begin() const { return cbegin(); }
1117
1118 ConstRowIterator cend() const
1119 {
1120 return ConstRowIterator{ rowCount(), storage.root(), this };
1121 }
1122 ConstRowIterator end() const { return cend(); }
1123
1124 template <typename I = Impl, if_writable<I> = true>
1125 RowIterator begin()
1126 {
1127 return RowIterator{ 0, storage.root(), this };
1128 }
1129
1130 template <typename I = Impl, if_writable<I> = true>
1131 RowIterator end()
1132 {
1133 return RowIterator{ rowCount(), storage.root(), this };
1134 }
1135
1136 int size() const
1137 {
1138 return rowCount();
1139 }
1140
1141 template <typename I = Impl, if_list<I> = true>
1142 QModelIndex index(int row) const
1143 {
1144 return storage->index(row, 0, storage.root());
1145 }
1146
1147 template <typename I = Impl, unless_list<I> = true>
1148 QModelIndex index(int row, int column) const
1149 {
1150 return storage->index(row, column, storage.root());
1151 }
1152
1153 template <typename I = Impl, if_tree<I> = true>
1154 QModelIndex index(QSpan<const int> path, int col) const
1155 {
1156 QModelIndex result = storage.root();
1157 auto count = path.size();
1158 for (const int r : path) {
1159 if (--count)
1160 result = storage->index(r, 0, result);
1161 else
1162 result = storage->index(r, col, result);
1163 }
1164 return result;
1165 }
1166
1167 int columnCount() const
1168 {
1169
1170 return storage->columnCount({});
1171 }
1172
1173 int rowCount() const
1174 {
1175 return storage->rowCount(storage.root());
1176 }
1177
1178 template <typename I = Impl, if_tree<I> = true>
1179 int rowCount(int row) const
1180 {
1181 return storage->rowCount(index(row, 0));
1182 }
1183
1184 template <typename I = Impl, if_tree<I> = true>
1185 int rowCount(QSpan<const int> path) const
1186 {
1187 return storage->rowCount(index(path, 0));
1188 }
1189
1190 template <typename I = Impl, if_tree<I> = true>
1191 constexpr bool hasChildren(int row) const
1192 {
1193 return storage.m_model->hasChildren(index(row, 0));
1194 }
1195
1196 template <typename I = Impl, if_tree<I> = true>
1197 constexpr bool hasChildren(QSpan<const int> path) const
1198 {
1199 return storage.m_model->hasChildren(index(path, 0));
1200 }
1201
1202 template <typename I = Impl, if_list<I> = true>
1203 QVariant data(int row) const
1204 {
1205 return QRangeModelDetails::dataAtIndex<QVariant>(index(row));
1206 }
1207
1208 template <typename I = Impl, if_list<I> = true>
1209 QVariant data(int row, int role) const
1210 {
1211 return QRangeModelDetails::dataAtIndex<QVariant>(index(row), role);
1212 }
1213
1214 template <typename I = Impl, if_list<I> = true, if_writable<I> = true>
1215 bool setData(int row, const QVariant &value, int role = Qt::EditRole)
1216 {
1217 return storage->setData(index(row), value, role);
1218 }
1219
1220 template <typename I = Impl, unless_list<I> = true>
1221 QVariant data(int row, int column) const
1222 {
1223 return QRangeModelDetails::dataAtIndex<QVariant>(index(row, column));
1224 }
1225
1226 template <typename I = Impl, unless_list<I> = true>
1227 QVariant data(int row, int column, int role) const
1228 {
1229 return QRangeModelDetails::dataAtIndex<QVariant>(index(row, column), role);
1230 }
1231
1232 template <typename I = Impl, unless_list<I> = true, if_writable<I> = true>
1233 bool setData(int row, int column, const QVariant &value, int role = Qt::EditRole)
1234 {
1235 return storage->setData(index(row, column), value, role);
1236 }
1237
1238 template <typename I = Impl, if_tree<I> = true>
1239 QVariant data(QSpan<const int> path, int column) const
1240 {
1241 return QRangeModelDetails::dataAtIndex<QVariant>(index(path, column));
1242 }
1243
1244 template <typename I = Impl, if_tree<I> = true>
1245 QVariant data(QSpan<const int> path, int column, int role) const
1246 {
1247 return QRangeModelDetails::dataAtIndex<QVariant>(index(path, column), role);
1248 }
1249
1250 template <typename I = Impl, if_tree<I> = true, if_writable<I> = true>
1251 bool setData(QSpan<const int> path, int column, const QVariant &value, int role = Qt::EditRole)
1252 {
1253 return storage->setData(index(path, column), value, role);
1254 }
1255
1256
1257
1258 template <typename I= Impl, if_list<I> = true>
1259 const_data_type at(int row) const
1260 {
1261 return QRangeModelDetails::dataAtIndex<data_type>(index(row));
1262 }
1263 template <typename I = Impl, if_list<I> = true>
1264 const_data_type operator[](int row) const { return at(row); }
1265
1266 template <typename I= Impl, if_list<I> = true, if_writable<I> = true>
1267 auto at(int row) {
1268 const QModelIndex idx = this->index(row);
1269 Q_ASSERT_X(idx.isValid(), "QRangeModelAdapter::at", "Index at row is invalid");
1270 return DataReference{idx};
1271 }
1272 template <typename I = Impl, if_list<I> = true, if_writable<I> = true>
1273 auto operator[](int row) {
1274 const QModelIndex idx = this->index(row);
1275 Q_ASSERT_X(idx.isValid(), "QRangeModelAdapter::operator[]", "Index at row is invalid");
1276 return DataReference{idx};
1277 }
1278
1279
1280 template <typename I = Impl, unless_list<I> = true>
1281 decltype(auto) at(int row) const
1282 {
1283 return ConstRowReference{index(row, 0), this}.get();
1284 }
1285 template <typename I = Impl, unless_list<I> = true>
1286 decltype(auto) operator[](int row) const { return at(row); }
1287
1288 template <typename I = Impl, if_table<I> = true, if_writable<I> = true>
1289 auto at(int row)
1290 {
1291 return RowReference{index(row, 0), this};
1292 }
1293 template <typename I = Impl, if_table<I> = true, if_writable<I> = true>
1294 auto operator[](int row) { return at(row); }
1295
1296
1297 template <typename I = Impl, unless_list<I> = true>
1298 const_data_type at(int row, int column) const
1299 {
1300 return QRangeModelDetails::dataAtIndex<data_type>(index(row, column));
1301 }
1302
1303 #ifdef __cpp_multidimensional_subscript
1304 template <typename I = Impl, unless_list<I> = true>
1305 const_data_type operator[](int row, int column) const { return at(row, column); }
1306 #endif
1307
1308 template <typename I = Impl, unless_list<I> = true, if_writable<I> = true>
1309 auto at(int row, int column)
1310 {
1311 const QModelIndex idx = this->index(row, column);
1312 Q_ASSERT_X(idx.isValid(), "QRangeModelAdapter::at", "Index at cell is invalid");
1313 return DataReference{idx};
1314 }
1315 #ifdef __cpp_multidimensional_subscript
1316 template <typename I = Impl, unless_list<I> = true, if_writable<I> = true>
1317 auto operator[](int row, int column)
1318 {
1319 const QModelIndex idx = this->index(row, column);
1320 Q_ASSERT_X(idx.isValid(), "QRangeModelAdapter::operator[]", "Index at cell is invalid");
1321 return DataReference{idx};
1322 }
1323 #endif
1324
1325
1326
1327 template <typename I = Impl, if_tree<I> = true, if_writable<I> = true>
1328 auto at(int row)
1329 {
1330 return RowReference{index(row, 0), this};
1331 }
1332 template <typename I = Impl, if_tree<I> = true, if_writable<I> = true>
1333 auto operator[](int row) { return at(row); }
1334
1335
1336 template <typename I = Impl, if_tree<I> = true>
1337 decltype(auto) at(QSpan<const int> path) const
1338 {
1339 return ConstRowReference{index(path, 0), this}.get();
1340 }
1341 template <typename I = Impl, if_tree<I> = true>
1342 decltype(auto) operator[](QSpan<const int> path) const { return at(path); }
1343
1344 template <typename I = Impl, if_tree<I> = true, if_writable<I> = true>
1345 auto at(QSpan<const int> path)
1346 {
1347 return RowReference{index(path, 0), this};
1348 }
1349 template <typename I = Impl, if_tree<I> = true, if_writable<I> = true>
1350 auto operator[](QSpan<const int> path) { return at(path); }
1351
1352
1353 template <typename I = Impl, if_tree<I> = true>
1354 const_data_type at(QSpan<const int> path, int column) const
1355 {
1356 Q_PRE(path.size());
1357 return QRangeModelDetails::dataAtIndex<data_type>(index(path, column));
1358 }
1359
1360 #ifdef __cpp_multidimensional_subscript
1361 template <typename I = Impl, if_tree<I> = true>
1362 const_data_type operator[](QSpan<const int> path, int column) const { return at(path, column); }
1363 #endif
1364
1365 template <typename I = Impl, if_tree<I> = true, if_writable<I> = true>
1366 auto at(QSpan<const int> path, int column)
1367 {
1368 Q_PRE(path.size());
1369 const QModelIndex idx = this->index(path, column);
1370 Q_ASSERT_X(idx.isValid(), "QRangeModelAdapter::at", "Index at path is invalid");
1371 return DataReference{idx};
1372 }
1373 #ifdef __cpp_multidimensional_subscript
1374 template <typename I = Impl, if_tree<I> = true, if_writable<I> = true>
1375 auto operator[](QSpan<const int> path, int column)
1376 {
1377 const QModelIndex idx = this->index(path, column);
1378 Q_ASSERT_X(idx.isValid(), "QRangeModelAdapter::operator[]", "Index at path is invalid");
1379 return DataReference{idx};
1380 }
1381 #endif
1382
1383 template <typename I = Impl, if_canInsertRows<I> = true>
1384 bool insertRow(int before)
1385 {
1386 return storage.m_model->insertRow(before);
1387 }
1388
1389 template <typename I = Impl, if_canInsertRows<I> = true, if_tree<I> = true>
1390 bool insertRow(QSpan<const int> before)
1391 {
1392 Q_PRE(before.size());
1393 return storage.m_model->insertRow(before.back(), this->index(before.first(before.size() - 1), 0));
1394 }
1395
1396 template <typename D = row_type, typename I = Impl,
1397 if_canInsertRows<I> = true, if_compatible_row<D> = true>
1398 bool insertRow(int before, D &&data)
1399 {
1400 return insertRowImpl(before, storage.root(), std::forward<D>(data));
1401 }
1402
1403 template <typename D = row_type, typename I = Impl,
1404 if_canInsertRows<I> = true, if_compatible_row<D> = true, if_tree<I> = true>
1405 bool insertRow(QSpan<const int> before, D &&data)
1406 {
1407 return insertRowImpl(before.back(), this->index(before.sliced(0, before.size() - 1), 0),
1408 std::forward<D>(data));
1409 }
1410
1411 template <typename C, typename I = Impl,
1412 if_canInsertRows<I> = true, if_compatible_row_range<C> = true>
1413 bool insertRows(int before, C &&data)
1414 {
1415 return insertRowsImpl(before, storage.root(), std::forward<C>(data));
1416 }
1417
1418 template <typename C, typename I = Impl,
1419 if_canInsertRows<I> = true, if_compatible_row_range<C> = true, if_tree<I> = true>
1420 bool insertRows(QSpan<const int> before, C &&data)
1421 {
1422 return insertRowsImpl(before.back(), this->index(before.sliced(0, before.size() - 1), 0),
1423 std::forward<C>(data));
1424 }
1425
1426 template <typename I = Impl, if_canRemoveRows<I> = true>
1427 bool removeRow(int row)
1428 {
1429 return removeRows(row, 1);
1430 }
1431
1432 template <typename I = Impl, if_canRemoveRows<I> = true, if_tree<I> = true>
1433 bool removeRow(QSpan<const int> path)
1434 {
1435 return removeRows(path, 1);
1436 }
1437
1438 template <typename I = Impl, if_canRemoveRows<I> = true>
1439 bool removeRows(int row, int count)
1440 {
1441 return storage->removeRows(row, count, storage.root());
1442 }
1443
1444 template <typename I = Impl, if_canRemoveRows<I> = true, if_tree<I> = true>
1445 bool removeRows(QSpan<const int> path, int count)
1446 {
1447 return storage->removeRows(path.back(), count,
1448 this->index(path.first(path.size() - 1), 0));
1449 }
1450
1451 template <typename F = range_features, if_canMoveItems<F> = true>
1452 bool moveRow(int source, int destination)
1453 {
1454 return moveRows(source, 1, destination);
1455 }
1456
1457 template <typename F = range_features, if_canMoveItems<F> = true>
1458 bool moveRows(int source, int count, int destination)
1459 {
1460 return storage->moveRows(storage.root(), source, count, storage.root(), destination);
1461 }
1462
1463 template <typename I = Impl, typename F = range_features,
1464 if_canMoveItems<F> = true, if_tree<I> = true>
1465 bool moveRow(QSpan<const int> source, QSpan<const int> destination)
1466 {
1467 return moveRows(source, 1, destination);
1468 }
1469
1470 template <typename I = Impl, typename F = range_features,
1471 if_canMoveItems<F> = true, if_tree<I> = true>
1472 bool moveRows(QSpan<const int> source, int count, QSpan<const int> destination)
1473 {
1474 return storage->moveRows(this->index(source.first(source.size() - 1), 0),
1475 source.back(),
1476 count,
1477 this->index(destination.first(destination.size() - 1), 0),
1478 destination.back());
1479 }
1480
1481 template <typename I = Impl, if_canInsertColumns<I> = true>
1482 bool insertColumn(int before)
1483 {
1484 return storage.m_model->insertColumn(before);
1485 }
1486
1487 template <typename D, typename I = Impl,
1488 if_canInsertColumns<I> = true, if_compatible_column_data<D> = true>
1489 bool insertColumn(int before, D &&data)
1490 {
1491 return insertColumnImpl(before, storage.root(), std::forward<D>(data));
1492 }
1493
1494 template <typename C, typename I = Impl,
1495 if_canInsertColumns<I> = true, if_compatible_column_range<C> = true>
1496 bool insertColumns(int before, C &&data)
1497 {
1498 return insertColumnsImpl(before, storage.root(), std::forward<C>(data));
1499 }
1500
1501 template <typename I = Impl, if_canRemoveColumns<I> = true>
1502 bool removeColumn(int column)
1503 {
1504 return storage.m_model->removeColumn(column);
1505 }
1506
1507 template <typename I = Impl, if_canRemoveColumns<I> = true>
1508 bool removeColumns(int column, int count)
1509 {
1510 return storage->removeColumns(column, count, {});
1511 }
1512
1513 template <typename F = row_features, if_canMoveItems<F> = true>
1514 bool moveColumn(int from, int to)
1515 {
1516 return moveColumns(from, 1, to);
1517 }
1518
1519 template <typename F = row_features, if_canMoveItems<F> = true>
1520 bool moveColumns(int from, int count, int to)
1521 {
1522 return storage->moveColumns(storage.root(), from, count, storage.root(), to);
1523 }
1524
1525 template <typename I = Impl, typename F = row_features,
1526 if_canMoveItems<F> = true, if_tree<I> = true>
1527 bool moveColumn(QSpan<const int> source, int to)
1528 {
1529 const QModelIndex parent = this->index(source.first(source.size() - 1), 0);
1530 return storage->moveColumns(parent, source.back(), 1, parent, to);
1531 }
1532
1533 template <typename I = Impl, typename F = row_features,
1534 if_canMoveItems<F> = true, if_tree<I> = true>
1535 bool moveColumns(QSpan<const int> source, int count, int destination)
1536 {
1537 const QModelIndex parent = this->index(source.first(source.size() - 1), 0);
1538 return storage->moveColumns(parent, source.back(), count, parent, destination);
1539 }
1540
1541 private:
1542 friend inline
1543 bool comparesEqual(const QRangeModelAdapter &lhs, const QRangeModelAdapter &rhs) noexcept
1544 {
1545 return lhs.storage.m_model == rhs.storage.m_model;
1546 }
1547 Q_DECLARE_EQUALITY_COMPARABLE(QRangeModelAdapter)
1548
1549 friend inline
1550 bool comparesEqual(const QRangeModelAdapter &lhs, const range_type &rhs)
1551 {
1552 return lhs.range() == rhs;
1553 }
1554 Q_DECLARE_EQUALITY_COMPARABLE_NON_NOEXCEPT(QRangeModelAdapter, range_type)
1555
1556
1557 void emitDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
1558 {
1559 Q_EMIT storage.implementation()->dataChanged(topLeft, bottomRight, {});
1560 }
1561
1562 void beginAssignImpl(Impl *impl, range_type *oldRange, int newLastRow)
1563 {
1564 const QModelIndex root = storage.root();
1565 const qsizetype oldLastRow = qsizetype(Impl::size(oldRange)) - 1;
1566
1567 if (!root.isValid()) {
1568 impl->beginResetModel();
1569 impl->deleteOwnedRows();
1570 } else if constexpr (is_tree<Impl>) {
1571 if (oldLastRow >= 0) {
1572 impl->beginRemoveRows(root, 0, model()->rowCount(root) - 1);
1573 impl->deleteRemovedRows(QRangeModelDetails::refTo(oldRange));
1574 impl->endRemoveRows();
1575 }
1576 if (newLastRow >= 0)
1577 impl->beginInsertRows(root, 0, newLastRow);
1578 } else {
1579 Q_ASSERT_X(false, "QRangeModelAdapter::assign",
1580 "Internal error: The root index in a table or list must be invalid.");
1581 }
1582 }
1583
1584 void endAssignImpl(Impl *impl, int newLastRow)
1585 {
1586 const QModelIndex root = storage.root();
1587 if (!root.isValid()) {
1588 impl->endResetModel();
1589 } else if constexpr (is_tree<Impl>) {
1590 if (newLastRow >= 0) {
1591 Q_ASSERT(model()->hasChildren(root));
1592
1593
1594 impl->setParentRow(QRangeModelDetails::refTo(impl->childRange(root)),
1595 QRangeModelDetails::pointerTo(impl->rowData(root)));
1596 impl->endInsertRows();
1597 }
1598 }
1599 }
1600
1601 template <typename Assigner>
1602 void assignImpl(std::size_t newSize, Assigner &&assigner)
1603 {
1604 const auto sz = q26::saturating_cast<int>(newSize);
1605 Q_ASSERT_X(q20::cmp_equal(sz, newSize),
1606 "QRangeModelAdapter::assign", "New range is too large");
1607 const int newLastRow = sz - 1;
1608
1609 auto *impl = storage.implementation();
1610 auto *oldRange = impl->childRange(storage.root());
1611 beginAssignImpl(impl, oldRange, newLastRow);
1612 assigner(QRangeModelDetails::refTo(oldRange));
1613 endAssignImpl(impl, newLastRow);
1614
1615 if constexpr (Impl::itemsAreQObjects) {
1616 if (model()->autoConnectPolicy() == QRangeModel::AutoConnectPolicy::Full) {
1617 const auto begin = QRangeModelDetails::begin(QRangeModelDetails::refTo(oldRange));
1618 const auto end = QRangeModelDetails::end(QRangeModelDetails::refTo(oldRange));
1619 int rowIndex = 0;
1620 for (auto it = begin; it != end; ++it, ++rowIndex)
1621 impl->autoConnectPropertiesInRow(*it, rowIndex, storage.root());
1622 }
1623 }
1624 }
1625
1626
1627 template <typename P, typename Row>
1628 static auto setParentRow(P &protocol, Row &newRow, row_ptr parentRow)
1629 -> decltype(protocol.setParentRow(newRow, parentRow))
1630 {
1631 return protocol.setParentRow(newRow, parentRow);
1632 }
1633 template <typename ...Args> static constexpr void setParentRow(Args &&...)
1634 {
1635 static_assert(!protocol_traits::has_setParentRow,
1636 "Internal error, wrong setParentRow overload called");
1637 }
1638
1639 template <typename D>
1640 bool insertRowImpl(int before, const QModelIndex &parent, D &&data)
1641 {
1642 return storage.implementation()->doInsertRows(before, 1, parent, [&data, this]
1643 (range_type &range, auto *parentRow, int row, int count) {
1644 Q_UNUSED(this);
1645 const auto oldSize = range.size();
1646 auto newRow = range.emplace(QRangeModelDetails::pos(range, row), std::forward<D>(data));
1647 setParentRow(storage->protocol(), QRangeModelDetails::refTo(*newRow),
1648 QRangeModelDetails::pointerTo(parentRow));
1649 return range.size() == oldSize + count;
1650 });
1651 }
1652
1653 template <typename LHS>
1654 static auto selfInsertion(LHS *lhs, LHS *rhs) -> decltype(lhs == rhs)
1655 {
1656 if (lhs == rhs) {
1657 #ifndef QT_NO_DEBUG
1658 qCritical("Inserting data into itself is not supported");
1659 #endif
1660 return true;
1661 }
1662 return false;
1663 }
1664 template <typename LHS, typename RHS>
1665 static constexpr bool selfInsertion(LHS *, RHS *) { return false; }
1666
1667 template <typename C>
1668 bool insertRowsImpl(int before, const QModelIndex &parent, C &&data)
1669 {
1670 bool result = false;
1671 result = storage->doInsertRows(before, int(std::size(data)), parent, [&data, this]
1672 (range_type &range, auto *parentRow, int row, int count){
1673 Q_UNUSED(parentRow);
1674 Q_UNUSED(this);
1675 const auto pos = QRangeModelDetails::pos(range, row);
1676 const auto oldSize = range.size();
1677
1678 auto dataRange = [&data]{
1679 if constexpr (std::is_rvalue_reference_v<C&&>) {
1680 return std::make_pair(
1681 std::move_iterator(std::begin(data)),
1682 std::move_iterator(std::end(data))
1683 );
1684 } else {
1685 return std::make_pair(std::begin(data), std::end(data));
1686 }
1687 }();
1688
1689 if constexpr (range_features::has_insert_range) {
1690 if (selfInsertion(&range, &data))
1691 return false;
1692 auto start = range.insert(pos, dataRange.first, dataRange.second);
1693 if constexpr (protocol_traits::has_setParentRow) {
1694 while (count) {
1695 setParentRow(storage->protocol(), QRangeModelDetails::refTo(*start),
1696 QRangeModelDetails::pointerTo(parentRow));
1697 ++start;
1698 --count;
1699 }
1700 } else {
1701 Q_UNUSED(start);
1702 }
1703 } else {
1704 auto newRow = range.insert(pos, count, row_type{});
1705 while (dataRange.first != dataRange.second) {
1706 *newRow = *dataRange.first;
1707 setParentRow(storage->protocol(), QRangeModelDetails::refTo(*newRow),
1708 QRangeModelDetails::pointerTo(parentRow));
1709 ++dataRange.first;
1710 ++newRow;
1711 }
1712 }
1713 return range.size() == oldSize + count;
1714 });
1715 return result;
1716 }
1717
1718 template <typename D, typename = void>
1719 struct DataFromList {
1720 static constexpr auto first(D &data) { return &data; }
1721 static constexpr auto next(D &, D *entry) { return entry; }
1722 };
1723
1724 template <typename D>
1725 struct DataFromList<D, std::enable_if_t<QRangeModelDetails::range_traits<D>::value>>
1726 {
1727 static constexpr auto first(D &data) { return std::begin(data); }
1728 static constexpr auto next(D &data, typename D::iterator entry)
1729 {
1730 ++entry;
1731 if (entry == std::end(data))
1732 entry = first(data);
1733 return entry;
1734 }
1735 };
1736
1737 template <typename D, typename = void> struct RowFromTable
1738 {
1739 static constexpr auto first(D &data) { return &data; }
1740 static constexpr auto next(D &, D *entry) { return entry; }
1741 };
1742
1743 template <typename D>
1744 struct RowFromTable<D, std::enable_if_t<std::conjunction_v<
1745 QRangeModelDetails::range_traits<D>,
1746 QRangeModelDetails::range_traits<typename D::value_type>
1747 >>
1748 > : DataFromList<D>
1749 {};
1750
1751 template <typename D>
1752 bool insertColumnImpl(int before, const QModelIndex &parent, D data)
1753 {
1754 auto entry = DataFromList<D>::first(data);
1755
1756 return storage->doInsertColumns(before, 1, parent, [&entry, &data]
1757 (auto &range, auto pos, int count) {
1758 const auto oldSize = range.size();
1759 range.insert(pos, *entry);
1760 entry = DataFromList<D>::next(data, entry);
1761 return range.size() == oldSize + count;
1762 });
1763 }
1764
1765 template <typename C>
1766 bool insertColumnsImpl(int before, const QModelIndex &parent, C data)
1767 {
1768 bool result = false;
1769 auto entries = RowFromTable<C>::first(data);
1770 auto begin = std::begin(*entries);
1771 auto end = std::end(*entries);
1772 result = storage->doInsertColumns(before, int(std::size(*entries)), parent,
1773 [&begin, &end, &entries, &data](auto &range, auto pos, int count) {
1774 const auto oldSize = range.size();
1775 if constexpr (row_features::has_insert_range) {
1776 range.insert(pos, begin, end);
1777 } else {
1778 auto start = range.insert(pos, count, {});
1779 std::copy(begin, end, start);
1780 }
1781 entries = RowFromTable<C>::next(data, entries);
1782 begin = std::begin(*entries);
1783 end = std::end(*entries);
1784 return range.size() == oldSize + count;
1785 });
1786 return result;
1787 }
1788 };
1789
1790
1791
1792
1793 template <typename Range, typename Protocol,
1794 QRangeModelDetails::if_can_construct<Range, Protocol> = true>
1795 QRangeModelAdapter(Range &&, Protocol &&) -> QRangeModelAdapter<Range, Protocol>;
1796
1797 template <typename Range,
1798 QRangeModelDetails::if_can_construct<Range> = true>
1799 QRangeModelAdapter(Range &&) -> QRangeModelAdapter<Range, void>;
1800
1801 QT_END_NAMESPACE
1802
1803 #endif