File indexing completed on 2026-08-02 09:27:24
0001
0002
0003
0004
0005 #ifndef QRANGEMODELADAPTER_IMPL_H
0006 #define QRANGEMODELADAPTER_IMPL_H
0007
0008 #ifndef Q_QDOC
0009
0010 #ifndef QRANGEMODELADAPTER_H
0011 #error Do not include qrangemodeladapter_impl.h directly
0012 #endif
0013
0014 #if 0
0015 #pragma qt_sync_skip_header_check
0016 #pragma qt_sync_stop_processing
0017 #endif
0018
0019 #include <QtCore/qrangemodel.h>
0020 #include <QtCore/qspan.h>
0021 #include <set>
0022 #include <memory>
0023
0024 QT_BEGIN_NAMESPACE
0025
0026 namespace QRangeModelDetails
0027 {
0028 template <typename Range, typename Protocol>
0029 using RangeImplementation = std::conditional_t<std::is_void_v<Protocol>,
0030 std::conditional_t<is_tree_range<Range>::value,
0031 QGenericTreeItemModelImpl<Range, DefaultTreeProtocol<Range>>,
0032 QGenericTableItemModelImpl<Range>
0033 >,
0034 QGenericTreeItemModelImpl<Range, Protocol>
0035 >;
0036
0037 template <typename ...Args>
0038 using construct_rangeModel_test = decltype(QRangeModel(std::declval<Args &&>()...));
0039
0040 template <typename ...Args>
0041 static constexpr bool can_construct_rangeModel = qxp::is_detected_v<construct_rangeModel_test,
0042 Args...>;
0043
0044 template <typename ...Args>
0045 using if_can_construct = std::enable_if_t<can_construct_rangeModel<Args...>, bool>;
0046
0047 template <typename Output, typename Input>
0048 decltype(auto) forwardOrConvert(Input&& input)
0049 {
0050 if constexpr (std::is_same_v<q20::remove_cvref<Output>, q20::remove_cvref<Input>>)
0051 return std::forward<Input>(input);
0052 else
0053 return Output(std::forward<Input>(input));
0054 }
0055
0056
0057
0058 template <typename T, typename = void>
0059 struct data_type { using type = T; };
0060 template <>
0061 struct data_type<void> { using type = QVariant; };
0062
0063
0064
0065 template <typename T, typename = void> struct test_pointerAccess : std::false_type {};
0066 template <typename T> struct test_pointerAccess<T *> : std::true_type {};
0067 template <typename T>
0068 struct test_pointerAccess<T, std::void_t<decltype(std::declval<T>().operator->())>>
0069 : std::true_type
0070 {};
0071
0072 template <typename T>
0073 using data_pointer_t = std::conditional_t<test_pointerAccess<T>::value,
0074 T, QtPrivate::ArrowProxy<T>>;
0075
0076
0077
0078
0079
0080
0081 template <typename T, typename = void> struct AsConstData { using type = T; };
0082 template <typename T> struct AsConstData<const T &> { using type = T; };
0083 template <typename T> struct AsConstData<T *> { using type = const T *; };
0084 template <template <typename> typename U, typename T>
0085 struct AsConstData<U<T>, std::enable_if_t<is_any_shared_ptr<U<T>>::value>>
0086 { using type = U<const T>; };
0087 template <typename T> struct AsConstData<std::reference_wrapper<T>>
0088 { using type = std::reference_wrapper<const T>; };
0089
0090 template <typename T> using asConst_t = typename AsConstData<T>::type;
0091
0092
0093
0094
0095
0096 template <typename const_row_type, typename Iterator, typename Sentinel>
0097 struct RowView
0098 {
0099
0100
0101 struct iterator
0102 {
0103 using value_type = asConst_t<typename Iterator::value_type>;
0104 using difference_type = typename Iterator::difference_type;
0105 using pointer = QRangeModelDetails::data_pointer_t<value_type>;
0106 using reference = value_type;
0107 using const_reference = value_type;
0108 using iterator_category = typename std::iterator_traits<Iterator>::iterator_category;
0109
0110 template <typename I, typename Category>
0111 static constexpr bool is_atLeast = std::is_base_of_v<Category,
0112 typename std::iterator_traits<I>::iterator_category>;
0113 template <typename I, typename Category>
0114 using if_atLeast = std::enable_if_t<is_atLeast<I, Category>, bool>;
0115
0116 reference operator*() const { return *m_it; }
0117 pointer operator->() const { return operator*(); }
0118
0119
0120
0121 friend constexpr iterator &operator++(iterator &it)
0122 noexcept(noexcept(++std::declval<Iterator&>()))
0123 {
0124 ++it.m_it;
0125 return it;
0126 }
0127 friend constexpr iterator operator++(iterator &it, int)
0128 noexcept(noexcept(std::declval<Iterator&>()++))
0129 {
0130 iterator copy = it;
0131 ++copy.m_it;
0132 return copy;
0133 }
0134
0135 template <typename I = Iterator, if_atLeast<I, std::bidirectional_iterator_tag> = true>
0136 friend constexpr iterator &operator--(iterator &it)
0137 noexcept(noexcept(--std::declval<I&>()))
0138 {
0139 --it.m_it;
0140 return it;
0141 }
0142 template <typename I = Iterator, if_atLeast<I, std::bidirectional_iterator_tag> = true>
0143 friend constexpr iterator operator--(iterator &it, int)
0144 noexcept(noexcept(std::declval<I&>()--))
0145 {
0146 iterator copy = it;
0147 --it.m_it;
0148 return copy;
0149 }
0150
0151 template <typename I = Iterator, if_atLeast<I, std::random_access_iterator_tag> = true>
0152 friend constexpr iterator &operator+=(iterator &it, difference_type n)
0153 noexcept(noexcept(std::declval<I&>() += 1))
0154 {
0155 it.m_it += n;
0156 return it;
0157 }
0158 template <typename I = Iterator, if_atLeast<I, std::random_access_iterator_tag> = true>
0159 friend constexpr iterator &operator-=(iterator &it, difference_type n)
0160 noexcept(noexcept(std::declval<I&>() -= 1))
0161 {
0162 it.m_it -= n;
0163 return it;
0164 }
0165
0166 template <typename I = Iterator, if_atLeast<I, std::random_access_iterator_tag> = true>
0167 friend constexpr iterator operator+(const iterator &it, difference_type n)
0168 noexcept(noexcept(std::declval<I&>() + 1))
0169 {
0170 iterator copy = it;
0171 copy.m_it += n;
0172 return copy;
0173 }
0174 template <typename I = Iterator, if_atLeast<I, std::random_access_iterator_tag> = true>
0175 friend constexpr iterator operator+(difference_type n, const iterator &it)
0176 noexcept(noexcept(1 + std::declval<I&>()))
0177 {
0178 return it + n;
0179 }
0180 template <typename I = Iterator, if_atLeast<I, std::random_access_iterator_tag> = true>
0181 friend constexpr iterator operator-(const iterator &it, difference_type n)
0182 noexcept(noexcept(std::declval<I&>() - 1))
0183 {
0184 iterator copy = it;
0185 copy.m_it = it.m_it - n;
0186 return copy;
0187 }
0188
0189 template <typename I = Iterator, if_atLeast<I, std::random_access_iterator_tag> = true>
0190 constexpr reference operator[](difference_type n) const
0191 noexcept(noexcept(I::operator[]()))
0192 {
0193 return m_it[n];
0194 }
0195
0196 template <typename I = Iterator, if_atLeast<I, std::random_access_iterator_tag> = true>
0197 friend constexpr difference_type operator-(const iterator &lhs, const iterator &rhs)
0198 noexcept(noexcept(std::declval<I&>() - std::declval<I&>()))
0199 {
0200 return lhs.m_it - rhs.m_it;
0201 }
0202
0203 template <typename I = Iterator, if_atLeast<I, std::random_access_iterator_tag> = true>
0204 friend constexpr bool operator<(const iterator &lhs, const iterator &rhs)
0205 noexcept(noexcept(std::declval<I&>() < std::declval<I&>()))
0206 {
0207 return lhs.m_it < rhs.m_it;
0208 }
0209 template <typename I = Iterator, if_atLeast<I, std::random_access_iterator_tag> = true>
0210 friend constexpr bool operator<=(const iterator &lhs, const iterator &rhs)
0211 noexcept(noexcept(std::declval<I&>() <= std::declval<I&>()))
0212 {
0213 return lhs.m_it <= rhs.m_it;
0214 }
0215
0216 template <typename I = Iterator, if_atLeast<I, std::random_access_iterator_tag> = true>
0217 friend constexpr bool operator>(const iterator &lhs, const iterator &rhs)
0218 noexcept(noexcept(std::declval<I&>() > std::declval<I&>()))
0219 {
0220 return lhs.m_it > rhs.m_it;
0221 }
0222 template <typename I = Iterator, if_atLeast<I, std::random_access_iterator_tag> = true>
0223 friend constexpr bool operator>=(const iterator &lhs, const iterator &rhs)
0224 noexcept(noexcept(std::declval<I&>() >= std::declval<I&>()))
0225 {
0226 return lhs.m_it >= rhs.m_it;
0227 }
0228
0229
0230
0231
0232
0233
0234
0235
0236
0237
0238
0239
0240
0241
0242
0243
0244
0245
0246
0247 friend bool comparesEqual(const iterator &lhs, const iterator &rhs) noexcept
0248 {
0249 return lhs.m_it == rhs.m_it;
0250 }
0251 Q_DECLARE_EQUALITY_COMPARABLE(iterator)
0252
0253 Iterator m_it;
0254 };
0255
0256 using value_type = typename iterator::value_type;
0257 using difference_type = typename iterator::difference_type;
0258
0259 friend bool comparesEqual(const RowView &lhs, const RowView &rhs) noexcept
0260 {
0261 return lhs.m_begin == rhs.m_begin;
0262 }
0263 Q_DECLARE_EQUALITY_COMPARABLE(RowView)
0264
0265 template <typename RHS>
0266 bool operator==(const RHS &rhs) const noexcept
0267 {
0268 return m_begin == QRangeModelDetails::begin(rhs);
0269 }
0270 template <typename RHS>
0271 bool operator!=(const RHS &rhs) const noexcept
0272 {
0273 return !operator==(rhs);
0274 }
0275
0276 value_type at(difference_type n) const { return *std::next(m_begin, n); }
0277
0278 iterator begin() const { return iterator{m_begin}; }
0279 iterator end() const { return iterator{m_end}; }
0280
0281 Iterator m_begin;
0282 Sentinel m_end;
0283 };
0284
0285
0286
0287 template <typename T, typename = void> struct AsConstRow { using type = const T &; };
0288
0289 template <typename T> struct AsConstRow<T *> : AsConstData<T *> {};
0290 template <template <typename> typename U, typename T>
0291 struct AsConstRow<U<T>, std::enable_if_t<is_any_shared_ptr<U<T>>::value>> : AsConstData<U<T>> {};
0292 template <typename T> struct AsConstRow<std::reference_wrapper<T>>
0293 : AsConstData<std::reference_wrapper<T>> {};
0294
0295 template <typename T> using if_range = std::enable_if_t<is_range_v<T>, bool>;
0296
0297
0298 template <template <typename, typename ...> typename R, typename T, typename ...Args>
0299 struct AsConstRow<R<T, Args...>, if_range<R<T, Args...>>>
0300 {
0301 using type = const R<T, Args...> &;
0302 };
0303
0304
0305 template <template <typename, typename ...> typename R, typename T, typename ...Args>
0306 struct AsConstRow<R<T *, Args...>, if_range<R<T *, Args...>>>
0307 {
0308 using row_type = R<T, Args...>;
0309 using const_iterator = typename row_type::const_iterator;
0310 using const_row_type = R<asConst_t<T>>;
0311 using type = RowView<const_row_type, const_iterator, const_iterator>;
0312 };
0313
0314 template <template <typename, typename ...> typename R, typename T, typename ...Args>
0315 struct AsConstRow<R<T, Args...>,
0316 std::enable_if_t<std::conjunction_v<is_range<R<T, Args...>>, is_any_shared_ptr<T>>>
0317 >
0318 {
0319 using row_type = R<T, Args...>;
0320 using const_iterator = typename row_type::const_iterator;
0321 using const_row_type = R<asConst_t<T>>;
0322 using type = RowView<const_row_type, const_iterator, const_iterator>;
0323 };
0324
0325 template <typename T>
0326 using asConstRow_t = typename AsConstRow<T>::type;
0327
0328 Q_CORE_EXPORT QVariant qVariantAtIndex(const QModelIndex &index);
0329
0330 template <typename Type>
0331 static inline Type dataAtIndex(const QModelIndex &index)
0332 {
0333 Q_ASSERT_X(index.isValid(), "QRangeModelAdapter::dataAtIndex", "Index at position is invalid");
0334 QVariant variant = qVariantAtIndex(index);
0335
0336 if constexpr (std::is_same_v<QVariant, Type>)
0337 return variant;
0338 else
0339 return variant.value<Type>();
0340 }
0341
0342 template <typename Type>
0343 static inline Type dataAtIndex(const QModelIndex &index, int role)
0344 {
0345 Q_ASSERT_X(index.isValid(), "QRangeModelAdapter::dataAtIndex", "Index at position is invalid");
0346 QVariant variant = index.data(role);
0347
0348 if constexpr (std::is_same_v<QVariant, Type>)
0349 return variant;
0350 else
0351 return variant.value<Type>();
0352 }
0353
0354 template <bool isTree = false>
0355 struct ParentIndex
0356 {
0357 ParentIndex(const QModelIndex &dummy = {}) { Q_ASSERT(!dummy.isValid()); }
0358 QModelIndex root() const { return {}; }
0359 };
0360
0361 template <>
0362 struct ParentIndex<true>
0363 {
0364 QModelIndex m_rootIndex;
0365 QModelIndex root() const { return m_rootIndex; }
0366 };
0367
0368 template <typename Model, typename Impl>
0369 struct AdapterStorage : ParentIndex<Impl::protocol_traits::is_tree>
0370 {
0371
0372
0373
0374 static constexpr bool isRangeModel = std::is_same_v<Model, QRangeModel>;
0375 static_assert(isRangeModel, "The model must be a QRangeModel (not a subclass).");
0376 std::shared_ptr<QRangeModel> m_model;
0377
0378 template <typename I = Impl, std::enable_if_t<I::protocol_traits::is_tree, bool> = true>
0379 explicit AdapterStorage(const std::shared_ptr<QRangeModel> &model, const QModelIndex &root)
0380 : ParentIndex<Impl::protocol_traits::is_tree>{root}, m_model(model)
0381 {
0382 }
0383
0384 explicit AdapterStorage(Model *model)
0385 : m_model{model}
0386 {}
0387
0388 const Impl *implementation() const
0389 {
0390 return static_cast<const Impl *>(QRangeModelImplBase::getImplementation(m_model.get()));
0391 }
0392
0393 Impl *implementation()
0394 {
0395 return static_cast<Impl *>(QRangeModelImplBase::getImplementation(m_model.get()));
0396 }
0397
0398 auto *operator->()
0399 {
0400 if constexpr (isRangeModel)
0401 return implementation();
0402 else
0403 return m_model.get();
0404 }
0405
0406 const auto *operator->() const
0407 {
0408 if constexpr (isRangeModel)
0409 return implementation();
0410 else
0411 return m_model.get();
0412 }
0413 };
0414
0415 }
0416
0417 QT_END_NAMESPACE
0418
0419 #endif
0420
0421 #endif