File indexing completed on 2026-01-07 10:16:28
0001
0002
0003
0004
0005 #ifndef QRANGEMODEL_IMPL_H
0006 #define QRANGEMODEL_IMPL_H
0007
0008 #ifndef Q_QDOC
0009
0010 #ifndef QRANGEMODEL_H
0011 #error Do not include qrangemodel_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/qabstractitemmodel.h>
0020 #include <QtCore/qmetaobject.h>
0021 #include <QtCore/qvariant.h>
0022 #include <QtCore/qmap.h>
0023
0024 #include <algorithm>
0025 #include <functional>
0026 #include <iterator>
0027 #include <type_traits>
0028 #include <QtCore/q20type_traits.h>
0029 #include <tuple>
0030 #include <QtCore/q23utility.h>
0031
0032 QT_BEGIN_NAMESPACE
0033
0034 namespace QtPrivate {
0035
0036 template <typename Applier, size_t ...Is>
0037 void applyIndexSwitch(size_t index, Applier&& applier, std::index_sequence<Is...>)
0038 {
0039
0040
0041
0042
0043
0044 static_cast<void>(((Is == index ? (applier(std::integral_constant<size_t, Is>{}), true) : false)
0045 || ...));
0046 }
0047
0048 template <size_t IndexCount, typename Applier>
0049 void applyIndexSwitch(size_t index, Applier&& applier)
0050 {
0051 applyIndexSwitch(index, std::forward<Applier>(applier), std::make_index_sequence<IndexCount>());
0052 }
0053
0054
0055 template <typename Interface>
0056 class QQuasiVirtualInterface
0057 {
0058 private:
0059 template <typename Arg>
0060 static constexpr bool passArgAsValue = sizeof(Arg) <= sizeof(size_t)
0061 && std::is_trivially_destructible_v<Arg>;
0062
0063 template <typename ...>
0064 struct MethodImpl;
0065
0066 template <typename M, typename R, typename I, typename... Args>
0067 struct MethodImpl<M, R, I, Args...>
0068 {
0069 static_assert(std::is_base_of_v<I, Interface>, "The method must belong to the interface");
0070 using return_type = R;
0071 using call_args = std::tuple<std::conditional_t<passArgAsValue<Args>, Args, Args&&>...>;
0072
0073 static constexpr size_t index()
0074 {
0075 return index(std::make_index_sequence<std::tuple_size_v<Methods<>>>());
0076 }
0077
0078 private:
0079 template <size_t Ix>
0080 static constexpr bool matchesAt()
0081 {
0082 return std::is_base_of_v<M, std::tuple_element_t<Ix, Methods<>>>;
0083 }
0084
0085 template <size_t... Is>
0086 static constexpr size_t index(std::index_sequence<Is...>)
0087 {
0088 constexpr size_t matchesCount = (size_t(matchesAt<Is>()) + ...);
0089 static_assert(matchesCount == 1, "Expected exactly one match");
0090 return ((size_t(matchesAt<Is>()) * Is) + ...);
0091 }
0092
0093 static R invoke(I &intf , Args... args)
0094 {
0095 Q_ASSERT(intf.m_callFN);
0096
0097 auto& baseIntf = static_cast<base_interface&>(const_cast<std::remove_const_t<I>&>(intf));
0098 call_args callArgs(std::forward<Args>(args)...);
0099 if constexpr (std::is_void_v<R>) {
0100 intf.m_callFN(index(), baseIntf, nullptr, &callArgs);
0101 } else {
0102 alignas(R) std::byte buf[sizeof(R)];
0103 intf.m_callFN(index(), baseIntf, buf, &callArgs);
0104
0105 R* result = std::launder(reinterpret_cast<R*>(buf));
0106 QScopeGuard destroyBuffer([result]() { std::destroy_at(result); });
0107 return std::forward<R>(*result);
0108 }
0109 }
0110
0111 friend class QQuasiVirtualInterface<Interface>;
0112 };
0113
0114 template <typename M, typename R, typename I, typename... Args>
0115 struct MethodImpl<M, R(I::*)(Args...)> : MethodImpl<M, R, I, Args...> {
0116 template <typename Subclass>
0117 using Overridden = R(Subclass::*)(Args...);
0118 };
0119
0120 template <typename M, typename R, typename I, typename... Args>
0121 struct MethodImpl<M, R(I::*)(Args...) const> : MethodImpl<M, R, const I, Args...> {
0122 template <typename Subclass>
0123 using Overridden = R(Subclass::*)(Args...) const;
0124 };
0125
0126 template <typename C = Interface> using Methods = typename C::template MethodTemplates<C>;
0127
0128 public:
0129 template <auto prototype>
0130 struct Method : MethodImpl<Method<prototype>, decltype(prototype)> {};
0131
0132 template <typename Method, typename... Args>
0133 auto call(Args &&... args) const
0134 {
0135 return Method::invoke(static_cast<const Interface &>(*this), std::forward<Args>(args)...);
0136 }
0137
0138 template <typename Method, typename... Args>
0139 auto call(Args &&... args)
0140 {
0141 return Method::invoke(static_cast<Interface &>(*this), std::forward<Args>(args)...);
0142 }
0143
0144 void destroy();
0145 using Destroy = Method<&QQuasiVirtualInterface::destroy>;
0146
0147 struct Deleter
0148 {
0149 void operator () (QQuasiVirtualInterface* self) const { self->call<Destroy>(); }
0150 };
0151
0152 protected:
0153 using base_interface = QQuasiVirtualInterface<Interface>;
0154 using CallFN = void (*)(size_t index, base_interface &intf, void *ret, void *args);
0155 void initCallFN(CallFN func) { m_callFN = func; }
0156
0157 QQuasiVirtualInterface() = default;
0158 ~QQuasiVirtualInterface() = default;
0159
0160 private:
0161 Q_DISABLE_COPY_MOVE(QQuasiVirtualInterface)
0162 CallFN m_callFN = nullptr;
0163 };
0164
0165 template <typename Subclass, typename Interface>
0166 class QQuasiVirtualSubclass : public Interface
0167 {
0168 private:
0169 template <typename C = Subclass> using Methods = typename C::template MethodTemplates<C>;
0170
0171 template <size_t OverriddenIndex>
0172 static constexpr size_t interfaceMethodIndex() {
0173 return std::tuple_element_t<OverriddenIndex, Methods<>>::index();
0174 }
0175
0176 template <size_t... Is>
0177 static void callImpl(size_t index, Subclass &subclass, void *ret, void *args, std::index_sequence<Is...>)
0178 {
0179
0180 static constexpr std::uint64_t methodIndexMask = ((uint64_t(1)
0181 << interfaceMethodIndex<Is>()) | ...);
0182 static_assert(sizeof...(Is) == std::tuple_size_v<Methods<Interface>>,
0183 "Base and overridden methods count are different");
0184 static_assert(methodIndexMask == (uint64_t(1) << sizeof...(Is)) - 1,
0185 "Mapping between base and overridden methods is not unique");
0186
0187 auto doInvoke = [&](auto idxConstant) {
0188 std::tuple_element_t<idxConstant.value, Methods<>>::doInvoke(subclass, ret, args);
0189 };
0190 applyIndexSwitch(index, doInvoke, std::index_sequence<interfaceMethodIndex<Is>()...>{});
0191 }
0192
0193 static void callImpl(size_t index, typename Interface::base_interface &intf, void *ret, void *args)
0194 {
0195 constexpr auto seq = std::make_index_sequence<std::tuple_size_v<Methods<>>>();
0196 callImpl(index, static_cast<Subclass&>(intf), ret, args, seq);
0197 }
0198
0199 template <typename BaseMethod>
0200 using OverridenSignature = typename BaseMethod::template Overridden<Subclass>;
0201
0202 protected:
0203 template <typename... Args>
0204 QQuasiVirtualSubclass(Args &&... args)
0205 : Interface(std::forward<Args>(args)...)
0206 {
0207 Interface::initCallFN(&QQuasiVirtualSubclass::callImpl);
0208 }
0209
0210 public:
0211 template <typename BaseMethod, OverridenSignature<BaseMethod> overridden>
0212 struct Override : BaseMethod
0213 {
0214 private:
0215 static constexpr void doInvoke(Subclass &subclass, void *ret, void *args)
0216 {
0217 using Return = typename BaseMethod::return_type;
0218 using PackedArgs = typename BaseMethod::call_args;
0219
0220 Q_ASSERT(args);
0221 Q_ASSERT(std::is_void_v<Return> == !ret);
0222
0223 auto invoke = [&subclass](auto &&...params)
0224 {
0225 return std::invoke(overridden, &subclass, std::forward<decltype(params)>(params)...);
0226 };
0227
0228 if constexpr (std::is_void_v<Return>) {
0229 std::apply(invoke, std::move(*static_cast<PackedArgs *>(args)));
0230 } else {
0231
0232
0233 using Alloc = std::allocator<Return>;
0234 Alloc alloc;
0235 std::allocator_traits<Alloc>::construct(alloc, static_cast<Return *>(ret),
0236 std::apply(invoke, std::move(*static_cast<PackedArgs *>(args))));
0237 }
0238
0239 }
0240
0241 friend class QQuasiVirtualSubclass<Subclass, Interface>;
0242 };
0243 };
0244
0245 }
0246
0247 namespace QRangeModelDetails
0248 {
0249 template <typename T, template <typename...> typename... Templates>
0250 struct is_any_of_impl : std::false_type {};
0251
0252 template <template <typename...> typename Template,
0253 typename... Params,
0254 template <typename...> typename... Templates>
0255 struct is_any_of_impl<Template<Params...>, Template, Templates...> : std::true_type {};
0256
0257 template <typename T,
0258 template <typename...> typename Template,
0259 template <typename...> typename... Templates>
0260 struct is_any_of_impl<T, Template, Templates...> : is_any_of_impl<T, Templates...> {};
0261
0262 template <typename T, template <typename...> typename... Templates>
0263 using is_any_of = is_any_of_impl<std::remove_cv_t<T>, Templates...>;
0264
0265 template <typename T, typename = void>
0266 struct is_validatable : std::false_type {};
0267
0268 template <typename T>
0269 struct is_validatable<T, std::void_t<decltype(*std::declval<T>())>>
0270 : std::is_constructible<bool, T> {};
0271
0272 template <typename T, typename = void>
0273 struct is_smart_ptr : std::false_type {};
0274
0275 template <typename T>
0276 struct is_smart_ptr<T,
0277 std::enable_if_t<std::conjunction_v<
0278 std::is_pointer<decltype(std::declval<T&>().get())>,
0279 std::is_same<decltype(*std::declval<T&>().get()), decltype(*std::declval<T&>())>,
0280 is_validatable<T>
0281 >>>
0282 : std::true_type
0283 {};
0284
0285
0286
0287 template <typename T>
0288 using is_any_unique_ptr = is_any_of<T,
0289 #ifndef QT_NO_SCOPED_POINTER
0290 QScopedPointer,
0291 #endif
0292 std::unique_ptr
0293 >;
0294
0295 template <typename T>
0296 using is_any_shared_ptr = is_any_of<T, std::shared_ptr, QSharedPointer,
0297 QExplicitlySharedDataPointer, QSharedDataPointer>;
0298
0299 template <typename T>
0300 using is_owning_or_raw_pointer = std::disjunction<is_any_shared_ptr<T>, is_any_unique_ptr<T>,
0301 std::is_pointer<T>>;
0302
0303 template <typename T>
0304 static auto pointerTo(T&& t) {
0305 using Type = q20::remove_cvref_t<T>;
0306 if constexpr (is_any_of<Type, std::optional>())
0307 return t ? std::addressof(*std::forward<T>(t)) : nullptr;
0308 else if constexpr (std::is_pointer<Type>())
0309 return t;
0310 else if constexpr (is_smart_ptr<Type>())
0311 return t.get();
0312 else if constexpr (is_any_of<Type, std::reference_wrapper>())
0313 return std::addressof(t.get());
0314 else
0315 return std::addressof(std::forward<T>(t));
0316 }
0317
0318 template <typename T>
0319 using wrapped_t = std::remove_pointer_t<decltype(pointerTo(std::declval<T&>()))>;
0320
0321 template <typename T>
0322 using is_wrapped = std::negation<std::is_same<wrapped_t<T>, std::remove_reference_t<T>>>;
0323
0324 template <typename T, typename = void>
0325 struct tuple_like : std::false_type {};
0326 template <typename T, std::size_t N>
0327 struct tuple_like<std::array<T, N>> : std::false_type {};
0328 template <typename T>
0329 struct tuple_like<T, std::void_t<std::tuple_element_t<0, wrapped_t<T>>>> : std::true_type {};
0330 template <typename T>
0331 [[maybe_unused]] static constexpr bool tuple_like_v = tuple_like<T>::value;
0332
0333 template <typename T, typename = void>
0334 struct array_like : std::false_type {};
0335 template <typename T, std::size_t N>
0336 struct array_like<std::array<T, N>> : std::true_type {};
0337 template <typename T, std::size_t N>
0338 struct array_like<T[N]> : std::true_type {};
0339 template <typename T>
0340 [[maybe_unused]] static constexpr bool array_like_v = array_like<T>::value;
0341
0342 template <typename T, typename = void>
0343 struct has_metaobject : std::false_type {};
0344 template <typename T>
0345 struct has_metaobject<T, std::void_t<decltype(wrapped_t<T>::staticMetaObject)>>
0346 : std::true_type {};
0347 template <typename T>
0348 [[maybe_unused]] static constexpr bool has_metaobject_v = has_metaobject<T>::value;
0349
0350 template <typename T>
0351 static constexpr bool isValid(const T &t) noexcept
0352 {
0353 if constexpr (is_validatable<T>())
0354 return bool(t);
0355 else
0356 return true;
0357 }
0358
0359 template <typename T>
0360 static decltype(auto) refTo(T&& t) {
0361 Q_ASSERT(isValid(t));
0362
0363 using Type = q20::remove_cvref_t<T>;
0364 if constexpr (is_any_of<T, std::optional>())
0365 return *std::forward<T>(t);
0366 if constexpr (!is_wrapped<Type>() || is_any_unique_ptr<Type>())
0367 return q23::forward_like<T>(*pointerTo(t));
0368 else
0369 return *pointerTo(t);
0370 }
0371
0372 template <typename It>
0373 auto key(It&& it) -> decltype(it.key()) { return std::forward<It>(it).key(); }
0374 template <typename It>
0375 auto key(It&& it) -> decltype((it->first)) { return std::forward<It>(it)->first; }
0376
0377 template <typename It>
0378 auto value(It&& it) -> decltype(it.value()) { return std::forward<It>(it).value(); }
0379 template <typename It>
0380 auto value(It&& it) -> decltype((it->second)) { return std::forward<It>(it)->second; }
0381
0382
0383 template <typename C>
0384 static auto begin(C &&c) -> decltype(std::begin(refTo(std::forward<C>(c))))
0385 { return std::begin(refTo(std::forward<C>(c))); }
0386 template <typename C>
0387 static auto end(C &&c) -> decltype(std::end(refTo(std::forward<C>(c))))
0388 { return std::end(refTo(std::forward<C>(c))); }
0389 template <typename C>
0390 static auto pos(C &&c, int i)
0391 { return std::next(QRangeModelDetails::begin(std::forward<C>(c)), i); }
0392
0393
0394
0395
0396
0397
0398 template <typename C, typename = void>
0399 struct test_insert : std::false_type {};
0400
0401 template <typename C>
0402 struct test_insert<C, std::void_t<decltype(std::declval<C>().insert(
0403 std::declval<typename C::const_iterator>(),
0404 std::declval<typename C::size_type>(),
0405 std::declval<typename C::value_type>()
0406 ))>>
0407 : std::true_type
0408 {};
0409
0410
0411
0412 template <typename C, typename = void>
0413 struct test_insert_range : std::false_type {};
0414
0415 template <typename C>
0416 struct test_insert_range<C, std::void_t<decltype(std::declval<C&>().insert(
0417 std::declval<typename C::const_iterator&>(),
0418 std::declval<std::move_iterator<typename C::iterator>&>(),
0419 std::declval<std::move_iterator<typename C::iterator>&>()
0420 ))>>
0421 : std::true_type
0422 {};
0423
0424 template <typename C, typename = void>
0425 struct test_erase : std::false_type {};
0426
0427 template <typename C>
0428 struct test_erase<C, std::void_t<decltype(std::declval<C>().erase(
0429 std::declval<typename C::const_iterator>(),
0430 std::declval<typename C::const_iterator>()
0431 ))>>
0432 : std::true_type
0433 {};
0434
0435 template <typename C, typename = void>
0436 struct test_resize : std::false_type {};
0437
0438 template <typename C>
0439 struct test_resize<C, std::void_t<decltype(std::declval<C>().resize(
0440 std::declval<typename C::size_type>(),
0441 std::declval<typename C::value_type>()
0442 ))>>
0443 : std::true_type
0444 {};
0445
0446
0447 template <typename It, typename = void>
0448 struct test_rotate : std::false_type {};
0449
0450 template <typename It>
0451 struct test_rotate<It, std::void_t<decltype(std::swap(*std::declval<It>(),
0452 *std::declval<It>()))>>
0453 : std::true_type
0454 {};
0455
0456
0457
0458
0459
0460
0461 template <typename C, typename = void> struct is_multi_role : std::false_type
0462 {
0463 static constexpr bool int_key = false;
0464 };
0465 template <typename C>
0466 struct is_multi_role<C, std::void_t<typename C::key_type, typename C::mapped_type>>
0467 : std::conjunction<std::disjunction<std::is_same<typename C::key_type, int>,
0468 std::is_same<typename C::key_type, Qt::ItemDataRole>,
0469 std::is_same<typename C::key_type, QString>>,
0470 std::is_same<typename C::mapped_type, QVariant>>
0471 {
0472 static constexpr bool int_key = !std::is_same_v<typename C::key_type, QString>;
0473 };
0474 template <typename C>
0475 [[maybe_unused]]
0476 static constexpr bool is_multi_role_v = is_multi_role<C>::value;
0477
0478 template <typename C, typename = void>
0479 struct test_size : std::false_type {};
0480 template <typename C>
0481 struct test_size<C, std::void_t<decltype(std::size(std::declval<C&>()))>> : std::true_type {};
0482
0483 template <typename C, typename = void>
0484 struct range_traits : std::false_type {
0485 static constexpr bool is_mutable = !std::is_const_v<C>;
0486 static constexpr bool has_insert = false;
0487 static constexpr bool has_insert_range = false;
0488 static constexpr bool has_erase = false;
0489 static constexpr bool has_resize = false;
0490 static constexpr bool has_rotate = false;
0491 };
0492 template <typename C>
0493 struct range_traits<C, std::void_t<decltype(begin(std::declval<C&>())),
0494 decltype(end(std::declval<C&>())),
0495 std::enable_if_t<!is_multi_role_v<C>>
0496 >> : std::true_type
0497 {
0498 using iterator = decltype(begin(std::declval<C&>()));
0499 using value_type = std::remove_reference_t<decltype(*std::declval<iterator&>())>;
0500 static constexpr bool is_mutable = !std::is_const_v<C> && !std::is_const_v<value_type>;
0501 static constexpr bool has_insert = test_insert<C>();
0502 static constexpr bool has_insert_range = test_insert_range<C>();
0503 static constexpr bool has_erase = test_erase<C>();
0504 static constexpr bool has_resize = test_resize<C>();
0505 static constexpr bool has_rotate = test_rotate<iterator>();
0506 };
0507
0508
0509
0510 enum class Mutable { Yes, No };
0511 template <Mutable IsMutable>
0512 struct iterable_value : std::false_type {
0513 static constexpr bool is_mutable = IsMutable == Mutable::Yes;
0514 static constexpr bool has_insert = false;
0515 static constexpr bool has_erase = false;
0516 static constexpr bool has_resize = false;
0517 static constexpr bool has_rotate = false;
0518 };
0519 template <> struct range_traits<QByteArray> : iterable_value<Mutable::Yes> {};
0520 template <> struct range_traits<QString> : iterable_value<Mutable::Yes> {};
0521 template <class CharT, class Traits, class Allocator>
0522 struct range_traits<std::basic_string<CharT, Traits, Allocator>> : iterable_value<Mutable::Yes>
0523 {};
0524
0525
0526 template <typename T> struct range_traits<const T *> : iterable_value<Mutable::No> {};
0527 template <> struct range_traits<QLatin1StringView> : iterable_value<Mutable::No> {};
0528
0529 template <typename C>
0530 using is_range = range_traits<C>;
0531 template <typename C>
0532 [[maybe_unused]] static constexpr bool is_range_v = is_range<C>();
0533
0534
0535
0536 template <typename T> struct QRangeModelRowOptions;
0537
0538 template <typename T, typename = void>
0539 struct row_category : std::false_type
0540 {
0541 static constexpr bool isMultiRole = false;
0542 };
0543
0544 template <typename T>
0545 struct row_category<T, std::void_t<decltype(QRangeModelRowOptions<T>::rowCategory)>>
0546 : std::true_type
0547 {
0548 static constexpr auto rowCategory = QRangeModelRowOptions<T>::rowCategory;
0549 using RowCategory = decltype(rowCategory);
0550 static constexpr bool isMultiRole = rowCategory == RowCategory::MultiRoleItem;
0551 };
0552
0553
0554
0555
0556 template <typename T, typename = void>
0557 struct row_traits {
0558 static constexpr bool is_range = is_range_v<q20::remove_cvref_t<T>>;
0559
0560
0561
0562 static constexpr int static_size = is_range ? -1 : 0;
0563 using item_type = std::conditional_t<is_range, typename range_traits<T>::value_type, T>;
0564 static constexpr int fixed_size() { return 1; }
0565 static constexpr bool hasMetaObject = false;
0566 };
0567
0568
0569 template <typename T>
0570 struct row_traits<T, std::enable_if_t<tuple_like_v<T>>>
0571 {
0572 static constexpr std::size_t size64 = std::tuple_size_v<T>;
0573 static_assert(q20::in_range<int>(size64));
0574 static constexpr int static_size = int(size64);
0575
0576
0577 template <std::size_t ...I>
0578 static constexpr bool allSameTypes(std::index_sequence<I...>)
0579 {
0580 return (std::is_same_v<std::tuple_element_t<0, T>,
0581 std::tuple_element_t<I, T>> && ...);
0582 }
0583
0584 using item_type = std::conditional_t<allSameTypes(std::make_index_sequence<size64>{}),
0585 std::tuple_element_t<0, T>, void>;
0586 static constexpr int fixed_size() { return 0; }
0587 static constexpr bool hasMetaObject = false;
0588 };
0589
0590
0591 template <typename T, std::size_t N>
0592 struct row_traits<std::array<T, N>>
0593 {
0594 static_assert(q20::in_range<int>(N));
0595 static constexpr int static_size = int(N);
0596 using item_type = T;
0597 static constexpr int fixed_size() { return 0; }
0598 static constexpr bool hasMetaObject = false;
0599 };
0600
0601 template <typename T, std::size_t N>
0602 struct row_traits<T[N]> : row_traits<std::array<T, N>> {};
0603
0604
0605 template <typename T>
0606 struct row_traits<T, std::enable_if_t<has_metaobject_v<T> && !tuple_like_v<T>>>
0607 {
0608 static constexpr int static_size = 0;
0609 using item_type = std::conditional_t<row_category<T>::isMultiRole, T, void>;
0610 static int fixed_size() {
0611 if constexpr (row_category<T>::isMultiRole) {
0612 return 1;
0613 } else {
0614
0615
0616 static const int columnCount = []{
0617 const QMetaObject &mo = T::staticMetaObject;
0618 return mo.propertyCount() - mo.propertyOffset();
0619 }();
0620 return columnCount;
0621 }
0622 }
0623 static constexpr bool hasMetaObject = true;
0624 };
0625
0626 template <typename T>
0627 [[maybe_unused]] static constexpr int static_size_v =
0628 row_traits<std::remove_cv_t<wrapped_t<T>>>::static_size;
0629
0630 template <typename Range>
0631 struct ListProtocol
0632 {
0633 using row_type = typename range_traits<wrapped_t<Range>>::value_type;
0634
0635 template <typename R = row_type>
0636 auto newRow() -> decltype(R{}) { return R{}; }
0637 };
0638
0639 template <typename Range>
0640 struct TableProtocol
0641 {
0642 using row_type = typename range_traits<wrapped_t<Range>>::value_type;
0643
0644 template <typename R = row_type,
0645 std::enable_if_t<std::conjunction_v<std::is_destructible<wrapped_t<R>>,
0646 is_owning_or_raw_pointer<R>>, bool> = true>
0647 auto newRow() -> decltype(R(new wrapped_t<R>)) {
0648 if constexpr (is_any_of<R, std::shared_ptr>())
0649 return std::make_shared<wrapped_t<R>>();
0650 else
0651 return R(new wrapped_t<R>);
0652 }
0653
0654 template <typename R = row_type,
0655 std::enable_if_t<!is_owning_or_raw_pointer<R>::value, bool> = true>
0656 auto newRow() -> decltype(R{}) { return R{}; }
0657
0658 template <typename R = row_type,
0659 std::enable_if_t<std::is_pointer_v<std::remove_reference_t<R>>, bool> = true>
0660 auto deleteRow(R&& row) -> decltype(delete row) { delete row; }
0661 };
0662
0663 template <typename Range, typename R = typename range_traits<wrapped_t<Range>>::value_type>
0664 using table_protocol_t = std::conditional_t<static_size_v<R> == 0 && !has_metaobject_v<R>,
0665 ListProtocol<Range>, TableProtocol<Range>>;
0666
0667
0668
0669
0670 template <typename Range>
0671 struct DefaultTreeProtocol : TableProtocol<Range>
0672 {
0673 template <typename R >
0674 auto parentRow(const R& row) const -> decltype(row.parentRow())
0675 {
0676 return row.parentRow();
0677 }
0678
0679 template <typename R >
0680 auto setParentRow(R &row, R* parent) -> decltype(row.setParentRow(parent))
0681 {
0682 row.setParentRow(parent);
0683 }
0684
0685 template <typename R >
0686 auto childRows(const R &row) const -> decltype(row.childRows())
0687 {
0688 return row.childRows();
0689 }
0690
0691 template <typename R >
0692 auto childRows(R &row) -> decltype(row.childRows())
0693 {
0694 return row.childRows();
0695 }
0696 };
0697
0698 template <typename P, typename R, typename = void>
0699 struct protocol_parentRow : std::false_type {};
0700 template <typename P, typename R>
0701 struct protocol_parentRow<P, R,
0702 std::void_t<decltype(std::declval<P&>().parentRow(std::declval<wrapped_t<R>&>()))>>
0703 : std::true_type {};
0704
0705 template <typename P, typename R, typename = void>
0706 struct protocol_childRows : std::false_type {};
0707 template <typename P, typename R>
0708 struct protocol_childRows<P, R,
0709 std::void_t<decltype(std::declval<P&>().childRows(std::declval<wrapped_t<R>&>()))>>
0710 : std::true_type {};
0711
0712 template <typename P, typename R, typename = void>
0713 struct protocol_setParentRow : std::false_type {};
0714 template <typename P, typename R>
0715 struct protocol_setParentRow<P, R,
0716 std::void_t<decltype(std::declval<P&>().setParentRow(std::declval<wrapped_t<R>&>(),
0717 std::declval<wrapped_t<R>*>()))>>
0718 : std::true_type {};
0719
0720 template <typename P, typename R, typename = void>
0721 struct protocol_mutable_childRows : std::false_type {};
0722 template <typename P, typename R>
0723 struct protocol_mutable_childRows<P, R,
0724 std::void_t<decltype(refTo(std::declval<P&>().childRows(std::declval<wrapped_t<R>&>()))
0725 = {}) >>
0726 : std::true_type {};
0727
0728 template <typename P, typename = void>
0729 struct protocol_newRow : std::false_type {};
0730 template <typename P>
0731 struct protocol_newRow<P, std::void_t<decltype(std::declval<P&>().newRow())>>
0732 : std::true_type {};
0733
0734 template <typename P, typename R, typename = void>
0735 struct protocol_deleteRow : std::false_type {};
0736 template <typename P, typename R>
0737 struct protocol_deleteRow<P, R,
0738 std::void_t<decltype(std::declval<P&>().deleteRow(std::declval<R&&>()))>>
0739 : std::true_type {};
0740
0741 template <typename Range,
0742 typename Protocol = DefaultTreeProtocol<Range>,
0743 typename R = typename range_traits<Range>::value_type,
0744 typename = void>
0745 struct is_tree_range : std::false_type {};
0746
0747 template <typename Range, typename Protocol, typename R>
0748 struct is_tree_range<Range, Protocol, R,
0749 std::enable_if_t<std::conjunction_v<
0750 protocol_parentRow<Protocol, R>, protocol_childRows<Protocol, R>>>
0751 > : std::true_type {};
0752
0753 template <typename Range>
0754 using if_table_range = std::enable_if_t<std::conjunction_v<is_range<wrapped_t<Range>>,
0755 std::negation<is_tree_range<wrapped_t<Range>>>>,
0756 bool>;
0757
0758 template <typename Range, typename Protocol = DefaultTreeProtocol<Range>>
0759 using if_tree_range = std::enable_if_t<std::conjunction_v<is_range<wrapped_t<Range>>,
0760 is_tree_range<wrapped_t<Range>, wrapped_t<Protocol>>>,
0761 bool>;
0762
0763 template <typename Range, typename Protocol>
0764 struct protocol_traits
0765 {
0766 using protocol = wrapped_t<Protocol>;
0767 using row = typename range_traits<wrapped_t<Range>>::value_type;
0768
0769 static constexpr bool has_newRow = protocol_newRow<protocol>();
0770 static constexpr bool has_deleteRow = protocol_deleteRow<protocol, row>();
0771 static constexpr bool has_setParentRow = protocol_setParentRow<protocol, row>();
0772 static constexpr bool has_mutable_childRows = protocol_mutable_childRows<protocol, row>();
0773
0774 static constexpr bool is_default = is_any_of<protocol, ListProtocol, TableProtocol, DefaultTreeProtocol>();
0775 };
0776
0777 template <bool cacheProperties>
0778 struct PropertyData {
0779 static constexpr bool cachesProperties = false;
0780
0781 void invalidateCaches() {}
0782 };
0783
0784 template <>
0785 struct PropertyData<true>
0786 {
0787 static constexpr bool cachesProperties = true;
0788 mutable QHash<int, QMetaProperty> properties;
0789
0790 void invalidateCaches()
0791 {
0792 properties.clear();
0793 }
0794 };
0795
0796
0797
0798
0799 template <typename ModelStorage, typename ItemType>
0800 struct ModelData : PropertyData<has_metaobject_v<ItemType>>
0801 {
0802 auto model() { return pointerTo(m_model); }
0803 auto model() const { return pointerTo(m_model); }
0804
0805 template <typename Model = ModelStorage>
0806 ModelData(Model &&model)
0807 : m_model(std::forward<Model>(model))
0808 {}
0809 ModelStorage m_model;
0810 };
0811 }
0812
0813 class QRangeModel;
0814
0815 class QRangeModelImplBase : public QtPrivate::QQuasiVirtualInterface<QRangeModelImplBase>
0816 {
0817 private:
0818 using Self = QRangeModelImplBase;
0819 using QtPrivate::QQuasiVirtualInterface<Self>::Method;
0820 protected:
0821
0822
0823 template <typename StaticContainer, typename F>
0824 static auto for_element_at(StaticContainer &&container, std::size_t idx, F &&function)
0825 {
0826 using type = std::remove_cv_t<QRangeModelDetails::wrapped_t<StaticContainer>>;
0827 static_assert(QRangeModelDetails::array_like_v<type> || QRangeModelDetails::tuple_like_v<type>,
0828 "Internal error: expected an array-like or a tuple-like type");
0829
0830 if (QRangeModelDetails::isValid(container)) {
0831 auto& ref = QRangeModelDetails::refTo(std::forward<StaticContainer>(container));
0832 if constexpr (QRangeModelDetails::array_like_v<type>) {
0833 Q_ASSERT(idx < std::size(ref));
0834 function(ref[idx]);
0835 } else {
0836 constexpr size_t size = std::tuple_size_v<type>;
0837 Q_ASSERT(idx < std::tuple_size_v<type>);
0838 QtPrivate::applyIndexSwitch<size>(idx, [&](auto idxConstant) {
0839 function(get<idxConstant>(ref));
0840 });
0841 }
0842 }
0843 }
0844
0845
0846
0847 template <typename T>
0848 static constexpr QMetaType meta_type_at(size_t idx)
0849 {
0850 using type = QRangeModelDetails::wrapped_t<T>;
0851 if constexpr (QRangeModelDetails::array_like_v<type>) {
0852 Q_UNUSED(idx);
0853 return QMetaType::fromType<std::tuple_element_t<0, type>>();
0854 } else {
0855 constexpr auto size = std::tuple_size_v<type>;
0856 Q_ASSERT(idx < size);
0857 QMetaType metaType;
0858 QtPrivate::applyIndexSwitch<size>(idx, [&metaType](auto idxConstant) {
0859 using ElementType = std::tuple_element_t<idxConstant.value, type>;
0860 metaType = QMetaType::fromType<QRangeModelDetails::wrapped_t<ElementType>>();
0861 });
0862 return metaType;
0863 }
0864 }
0865
0866 public:
0867
0868
0869 void invalidateCaches();
0870 bool setHeaderData(int section, Qt::Orientation orientation, const QVariant &data, int role);
0871 bool setData(const QModelIndex &index, const QVariant &data, int role);
0872 bool setItemData(const QModelIndex &index, const QMap<int, QVariant> &data);
0873 bool clearItemData(const QModelIndex &index);
0874 bool insertColumns(int column, int count, const QModelIndex &parent);
0875 bool removeColumns(int column, int count, const QModelIndex &parent);
0876 bool moveColumns(const QModelIndex &sourceParent, int sourceColumn, int count, const QModelIndex &destParent, int destColumn);
0877 bool insertRows(int row, int count, const QModelIndex &parent);
0878 bool removeRows(int row, int count, const QModelIndex &parent);
0879 bool moveRows(const QModelIndex &sourceParent, int sourceRow, int count, const QModelIndex &destParent, int destRow);
0880
0881 QModelIndex index(int row, int column, const QModelIndex &parent) const;
0882 QModelIndex sibling(int row, int column, const QModelIndex &index) const;
0883 int rowCount(const QModelIndex &parent) const;
0884 int columnCount(const QModelIndex &parent) const;
0885 Qt::ItemFlags flags(const QModelIndex &index) const;
0886 QVariant headerData(int section, Qt::Orientation orientation, int role) const;
0887 QVariant data(const QModelIndex &index, int role) const;
0888 QMap<int, QVariant> itemData(const QModelIndex &index) const;
0889 QHash<int, QByteArray> roleNames() const;
0890 QModelIndex parent(const QModelIndex &child) const;
0891
0892
0893
0894 using InvalidateCaches = Method<&Self::invalidateCaches>;
0895 using SetHeaderData = Method<&Self::setHeaderData>;
0896 using SetData = Method<&Self::setData>;
0897 using SetItemData = Method<&Self::setItemData>;
0898 using ClearItemData = Method<&Self::clearItemData>;
0899 using InsertColumns = Method<&Self::insertColumns>;
0900 using RemoveColumns = Method<&Self::removeColumns>;
0901 using MoveColumns = Method<&Self::moveColumns>;
0902 using InsertRows = Method<&Self::insertRows>;
0903 using RemoveRows = Method<&Self::removeRows>;
0904 using MoveRows = Method<&Self::moveRows>;
0905
0906 using Index = Method<&Self::index>;
0907 using Sibling = Method<&Self::sibling>;
0908 using RowCount = Method<&Self::rowCount>;
0909 using ColumnCount = Method<&Self::columnCount>;
0910 using Flags = Method<&Self::flags>;
0911 using HeaderData = Method<&Self::headerData>;
0912 using Data = Method<&Self::data>;
0913 using ItemData = Method<&Self::itemData>;
0914 using RoleNames = Method<&Self::roleNames>;
0915 using Parent = Method<&Self::parent>;
0916
0917 template <typename C>
0918 using MethodTemplates = std::tuple<
0919 typename C::Destroy,
0920 typename C::InvalidateCaches,
0921 typename C::SetHeaderData,
0922 typename C::SetData,
0923 typename C::SetItemData,
0924 typename C::ClearItemData,
0925 typename C::InsertColumns,
0926 typename C::RemoveColumns,
0927 typename C::MoveColumns,
0928 typename C::InsertRows,
0929 typename C::RemoveRows,
0930 typename C::MoveRows,
0931 typename C::Index,
0932 typename C::Parent,
0933 typename C::Sibling,
0934 typename C::RowCount,
0935 typename C::ColumnCount,
0936 typename C::Flags,
0937 typename C::HeaderData,
0938 typename C::Data,
0939 typename C::ItemData,
0940 typename C::RoleNames
0941 >;
0942
0943 private:
0944 friend class QRangeModelPrivate;
0945 QRangeModel *m_rangeModel;
0946
0947 protected:
0948 explicit QRangeModelImplBase(QRangeModel *itemModel)
0949 : m_rangeModel(itemModel)
0950 {}
0951
0952 inline QModelIndex createIndex(int row, int column, const void *ptr = nullptr) const;
0953 inline void changePersistentIndexList(const QModelIndexList &from, const QModelIndexList &to);
0954 inline void dataChanged(const QModelIndex &from, const QModelIndex &to,
0955 const QList<int> &roles);
0956 inline void beginInsertColumns(const QModelIndex &parent, int start, int count);
0957 inline void endInsertColumns();
0958 inline void beginRemoveColumns(const QModelIndex &parent, int start, int count);
0959 inline void endRemoveColumns();
0960 inline bool beginMoveColumns(const QModelIndex &sourceParent, int sourceFirst, int sourceLast,
0961 const QModelIndex &destParent, int destRow);
0962 inline void endMoveColumns();
0963 inline void beginInsertRows(const QModelIndex &parent, int start, int count);
0964 inline void endInsertRows();
0965 inline void beginRemoveRows(const QModelIndex &parent, int start, int count);
0966 inline void endRemoveRows();
0967 inline bool beginMoveRows(const QModelIndex &sourceParent, int sourceFirst, int sourceLast,
0968 const QModelIndex &destParent, int destRow);
0969 inline void endMoveRows();
0970 inline QAbstractItemModel &itemModel();
0971 inline const QAbstractItemModel &itemModel() const;
0972
0973
0974 Q_CORE_EXPORT static QHash<int, QByteArray> roleNamesForMetaObject(const QAbstractItemModel &model,
0975 const QMetaObject &metaObject);
0976 Q_CORE_EXPORT static QHash<int, QByteArray> roleNamesForSimpleType();
0977 };
0978
0979 template <typename Structure, typename Range,
0980 typename Protocol = QRangeModelDetails::table_protocol_t<Range>>
0981 class QRangeModelImpl
0982 : public QtPrivate::QQuasiVirtualSubclass<QRangeModelImpl<Structure, Range, Protocol>,
0983 QRangeModelImplBase>
0984 {
0985 public:
0986 using range_type = QRangeModelDetails::wrapped_t<Range>;
0987 using row_reference = decltype(*QRangeModelDetails::begin(std::declval<range_type&>()));
0988 using const_row_reference = decltype(*QRangeModelDetails::begin(std::declval<const range_type&>()));
0989 using row_type = std::remove_reference_t<row_reference>;
0990 using protocol_type = QRangeModelDetails::wrapped_t<Protocol>;
0991
0992 static_assert(!QRangeModelDetails::is_any_of<range_type, std::optional>() &&
0993 !QRangeModelDetails::is_any_of<row_type, std::optional>(),
0994 "Currently, std::optional is not supported for ranges and rows, as "
0995 "it has range semantics in c++26. Once the required behavior is clarified, "
0996 "std::optional for ranges and rows will be supported.");
0997
0998 protected:
0999
1000 using Self = QRangeModelImpl<Structure, Range, Protocol>;
1001 using Ancestor = QtPrivate::QQuasiVirtualSubclass<Self, QRangeModelImplBase>;
1002
1003 Structure& that() { return static_cast<Structure &>(*this); }
1004 const Structure& that() const { return static_cast<const Structure &>(*this); }
1005
1006 template <typename C>
1007 static constexpr int size(const C &c)
1008 {
1009 if (!QRangeModelDetails::isValid(c))
1010 return 0;
1011
1012 if constexpr (QRangeModelDetails::test_size<C>()) {
1013 return int(std::size(c));
1014 } else {
1015 #if defined(__cpp_lib_ranges)
1016 return int(std::ranges::distance(QRangeModelDetails::begin(c),
1017 QRangeModelDetails::end(c)));
1018 #else
1019 return int(std::distance(QRangeModelDetails::begin(c),
1020 QRangeModelDetails::end(c)));
1021 #endif
1022 }
1023 }
1024
1025 using range_features = QRangeModelDetails::range_traits<range_type>;
1026 using wrapped_row_type = QRangeModelDetails::wrapped_t<row_type>;
1027 using row_features = QRangeModelDetails::range_traits<wrapped_row_type>;
1028 using row_traits = QRangeModelDetails::row_traits<std::remove_cv_t<wrapped_row_type>>;
1029 using protocol_traits = QRangeModelDetails::protocol_traits<Range, protocol_type>;
1030
1031 static constexpr bool isMutable()
1032 {
1033 return range_features::is_mutable && row_features::is_mutable
1034 && std::is_reference_v<row_reference>
1035 && Structure::is_mutable_impl;
1036 }
1037
1038 static constexpr int static_row_count = QRangeModelDetails::static_size_v<range_type>;
1039 static constexpr bool rows_are_raw_pointers = std::is_pointer_v<row_type>;
1040 static constexpr bool rows_are_owning_or_raw_pointers =
1041 QRangeModelDetails::is_owning_or_raw_pointer<row_type>();
1042 static constexpr int static_column_count = QRangeModelDetails::static_size_v<row_type>;
1043 static constexpr bool one_dimensional_range = static_column_count == 0;
1044
1045 static constexpr bool dynamicRows() { return isMutable() && static_row_count < 0; }
1046 static constexpr bool dynamicColumns() { return static_column_count < 0; }
1047
1048
1049
1050 using row_ptr = wrapped_row_type *;
1051 using const_row_ptr = const wrapped_row_type *;
1052
1053 template <typename T>
1054 static constexpr bool has_metaobject = QRangeModelDetails::has_metaobject_v<
1055 std::remove_pointer_t<std::remove_reference_t<T>>>;
1056
1057 using ModelData = QRangeModelDetails::ModelData<std::conditional_t<
1058 std::is_pointer_v<Range>,
1059 Range, std::remove_reference_t<Range>
1060 >,
1061 typename row_traits::item_type
1062 >;
1063
1064
1065
1066
1067
1068
1069 struct EmptyRowGenerator
1070 {
1071 using value_type = row_type;
1072 using reference = value_type;
1073 using pointer = value_type *;
1074 using iterator_category = std::input_iterator_tag;
1075 using difference_type = int;
1076
1077 value_type operator*() { return impl->makeEmptyRow(*parent); }
1078 EmptyRowGenerator &operator++() { ++n; return *this; }
1079 friend bool operator==(const EmptyRowGenerator &lhs, const EmptyRowGenerator &rhs) noexcept
1080 { return lhs.n == rhs.n; }
1081 friend bool operator!=(const EmptyRowGenerator &lhs, const EmptyRowGenerator &rhs) noexcept
1082 { return !(lhs == rhs); }
1083
1084 difference_type n = 0;
1085 Structure *impl = nullptr;
1086 const QModelIndex* parent = nullptr;
1087 };
1088
1089
1090
1091 static_assert(static_row_count || range_features::has_insert_range
1092 || std::is_copy_constructible_v<row_type>,
1093 "The range holding a move-only row-type must support insert(pos, start, end)");
1094
1095 public:
1096 explicit QRangeModelImpl(Range &&model, Protocol&& protocol, QRangeModel *itemModel)
1097 : Ancestor(itemModel)
1098 , m_data{std::forward<Range>(model)}
1099 , m_protocol(std::forward<Protocol>(protocol))
1100 {
1101 }
1102
1103
1104
1105
1106 void invalidateCaches() { m_data.invalidateCaches(); }
1107
1108
1109 bool setHeaderData(int , Qt::Orientation , const QVariant &, int ) { return false; }
1110
1111
1112 QModelIndex index(int row, int column, const QModelIndex &parent) const
1113 {
1114 if (row < 0 || column < 0 || column >= columnCount(parent)
1115 || row >= rowCount(parent)) {
1116 return {};
1117 }
1118
1119 return that().indexImpl(row, column, parent);
1120 }
1121
1122 QModelIndex sibling(int row, int column, const QModelIndex &index) const
1123 {
1124 if (row == index.row() && column == index.column())
1125 return index;
1126
1127 if (column < 0 || column >= this->itemModel().columnCount())
1128 return {};
1129
1130 if (row == index.row())
1131 return this->createIndex(row, column, index.constInternalPointer());
1132
1133 const_row_ptr parentRow = static_cast<const_row_ptr>(index.constInternalPointer());
1134 const auto siblingCount = size(that().childrenOf(parentRow));
1135 if (row < 0 || row >= int(siblingCount))
1136 return {};
1137 return this->createIndex(row, column, parentRow);
1138 }
1139
1140 Qt::ItemFlags flags(const QModelIndex &index) const
1141 {
1142 if (!index.isValid())
1143 return Qt::NoItemFlags;
1144
1145 Qt::ItemFlags f = Structure::defaultFlags();
1146
1147 if constexpr (isMutable()) {
1148 if constexpr (row_traits::hasMetaObject) {
1149 if (index.column() < row_traits::fixed_size()) {
1150 const QMetaObject mo = wrapped_row_type::staticMetaObject;
1151 const QMetaProperty prop = mo.property(index.column() + mo.propertyOffset());
1152 if (prop.isWritable())
1153 f |= Qt::ItemIsEditable;
1154 }
1155 } else if constexpr (static_column_count <= 0) {
1156 f |= Qt::ItemIsEditable;
1157 } else if constexpr (std::is_reference_v<row_reference> && !std::is_const_v<row_reference>) {
1158
1159
1160 const_row_reference row = rowData(index);
1161 row_reference mutableRow = const_cast<row_reference>(row);
1162 if (QRangeModelDetails::isValid(mutableRow)) {
1163 QRangeModelImplBase::for_element_at(mutableRow, index.column(), [&f](auto &&ref){
1164 using target_type = decltype(ref);
1165 if constexpr (std::is_const_v<std::remove_reference_t<target_type>>)
1166 f &= ~Qt::ItemIsEditable;
1167 else if constexpr (std::is_lvalue_reference_v<target_type>)
1168 f |= Qt::ItemIsEditable;
1169 });
1170 } else {
1171
1172
1173 f &= ~Qt::ItemIsEditable;
1174 }
1175 }
1176 }
1177 return f;
1178 }
1179
1180 QVariant headerData(int section, Qt::Orientation orientation, int role) const
1181 {
1182 QVariant result;
1183 if (role != Qt::DisplayRole || orientation != Qt::Horizontal
1184 || section < 0 || section >= columnCount({})) {
1185 return this->itemModel().QAbstractItemModel::headerData(section, orientation, role);
1186 }
1187
1188 if constexpr (row_traits::hasMetaObject) {
1189 if (row_traits::fixed_size() == 1) {
1190 const QMetaType metaType = QMetaType::fromType<wrapped_row_type>();
1191 result = QString::fromUtf8(metaType.name());
1192 } else if (section <= row_traits::fixed_size()) {
1193 const QMetaProperty prop = wrapped_row_type::staticMetaObject.property(
1194 section + wrapped_row_type::staticMetaObject.propertyOffset());
1195 result = QString::fromUtf8(prop.name());
1196 }
1197 } else if constexpr (static_column_count >= 1) {
1198 if constexpr (QRangeModelDetails::array_like_v<wrapped_row_type>) {
1199 return section;
1200 } else {
1201 const QMetaType metaType = QRangeModelImplBase::meta_type_at<wrapped_row_type>(section);
1202 if (metaType.isValid())
1203 result = QString::fromUtf8(metaType.name());
1204 }
1205 }
1206 if (!result.isValid())
1207 result = this->itemModel().QAbstractItemModel::headerData(section, orientation, role);
1208 return result;
1209 }
1210
1211 QVariant data(const QModelIndex &index, int role) const
1212 {
1213 QVariant result;
1214 const auto readData = [this, column = index.column(), &result, role](const auto &value) {
1215 Q_UNUSED(this);
1216 using value_type = q20::remove_cvref_t<decltype(value)>;
1217 using multi_role = QRangeModelDetails::is_multi_role<value_type>;
1218 if constexpr (has_metaobject<value_type>) {
1219 if (row_traits::fixed_size() <= 1) {
1220 if (role == Qt::RangeModelDataRole) {
1221 using wrapped_value_type = QRangeModelDetails::wrapped_t<value_type>;
1222
1223
1224
1225 if constexpr (std::is_copy_assignable_v<wrapped_value_type>)
1226 result = QVariant::fromValue(QRangeModelDetails::refTo(value));
1227 else
1228 result = QVariant::fromValue(QRangeModelDetails::pointerTo(value));
1229 } else {
1230 result = readRole(role, QRangeModelDetails::pointerTo(value));
1231 }
1232 } else if (column <= row_traits::fixed_size()
1233 && (role == Qt::DisplayRole || role == Qt::EditRole)) {
1234 result = readProperty(column, QRangeModelDetails::pointerTo(value));
1235 }
1236 } else if constexpr (multi_role::value) {
1237 const auto it = [this, &value, role]{
1238 Q_UNUSED(this);
1239 if constexpr (multi_role::int_key)
1240 return std::as_const(value).find(Qt::ItemDataRole(role));
1241 else
1242 return std::as_const(value).find(this->itemModel().roleNames().value(role));
1243 }();
1244 if (it != QRangeModelDetails::end(value))
1245 result = QRangeModelDetails::value(it);
1246 } else if (role == Qt::DisplayRole || role == Qt::EditRole
1247 || role == Qt::RangeModelDataRole) {
1248 result = read(value);
1249 }
1250 };
1251
1252 if (index.isValid())
1253 readAt(index, readData);
1254
1255 return result;
1256 }
1257
1258 QMap<int, QVariant> itemData(const QModelIndex &index) const
1259 {
1260 QMap<int, QVariant> result;
1261 bool tried = false;
1262 const auto readItemData = [this, &result, &tried](const auto &value){
1263 Q_UNUSED(this);
1264 using value_type = q20::remove_cvref_t<decltype(value)>;
1265 using multi_role = QRangeModelDetails::is_multi_role<value_type>;
1266 if constexpr (multi_role()) {
1267 tried = true;
1268 if constexpr (std::is_convertible_v<value_type, decltype(result)>) {
1269 result = value;
1270 } else {
1271 const auto roleNames = [this]() -> QHash<int, QByteArray> {
1272 Q_UNUSED(this);
1273 if constexpr (!multi_role::int_key)
1274 return this->itemModel().roleNames();
1275 else
1276 return {};
1277 }();
1278 for (auto it = std::begin(value); it != std::end(value); ++it) {
1279 const int role = [&roleNames, key = QRangeModelDetails::key(it)]() {
1280 Q_UNUSED(roleNames);
1281 if constexpr (multi_role::int_key)
1282 return int(key);
1283 else
1284 return roleNames.key(key.toUtf8(), -1);
1285 }();
1286
1287 if (role != -1 && role != Qt::RangeModelDataRole)
1288 result.insert(role, QRangeModelDetails::value(it));
1289 }
1290 }
1291 } else if constexpr (has_metaobject<value_type>) {
1292 if (row_traits::fixed_size() <= 1) {
1293 tried = true;
1294 const auto roleNames = this->itemModel().roleNames();
1295 const auto end = roleNames.keyEnd();
1296 for (auto it = roleNames.keyBegin(); it != end; ++it) {
1297 const int role = *it;
1298 if (role == Qt::RangeModelDataRole)
1299 continue;
1300 QVariant data = readRole(role, QRangeModelDetails::pointerTo(value));
1301 if (data.isValid())
1302 result[role] = std::move(data);
1303 }
1304 }
1305 }
1306 };
1307
1308 if (index.isValid()) {
1309 readAt(index, readItemData);
1310
1311 if (!tried)
1312 result = this->itemModel().QAbstractItemModel::itemData(index);
1313 }
1314 return result;
1315 }
1316
1317 bool setData(const QModelIndex &index, const QVariant &data, int role)
1318 {
1319 if (!index.isValid())
1320 return false;
1321
1322 bool success = false;
1323 if constexpr (isMutable()) {
1324 auto emitDataChanged = qScopeGuard([&success, this, &index, role]{
1325 if (success) {
1326 Q_EMIT this->dataChanged(index, index,
1327 role == Qt::EditRole || role == Qt::RangeModelDataRole
1328 ? QList<int>{} : QList<int>{role});
1329 }
1330 });
1331
1332 const auto writeData = [this, column = index.column(), &data, role](auto &&target) -> bool {
1333 using value_type = q20::remove_cvref_t<decltype(target)>;
1334 using wrapped_value_type = QRangeModelDetails::wrapped_t<value_type>;
1335 using multi_role = QRangeModelDetails::is_multi_role<value_type>;
1336 if constexpr (has_metaobject<value_type>) {
1337 if (role == Qt::RangeModelDataRole) {
1338 auto &targetRef = QRangeModelDetails::refTo(target);
1339 constexpr auto targetMetaType = QMetaType::fromType<value_type>();
1340 const auto dataMetaType = data.metaType();
1341 if constexpr (!std::is_copy_assignable_v<wrapped_value_type>) {
1342
1343
1344
1345
1346 } else if constexpr (QRangeModelDetails::is_wrapped<value_type>()) {
1347 if (QRangeModelDetails::isValid(target)) {
1348
1349
1350 if (const auto mt = QMetaType::fromType<wrapped_value_type>();
1351 data.canConvert(mt)) {
1352 targetRef = data.value<wrapped_value_type>();
1353 return true;
1354 } else if (const auto mtp = QMetaType::fromType<wrapped_value_type *>();
1355 data.canConvert(mtp)) {
1356 targetRef = *data.value<wrapped_value_type *>();
1357 return true;
1358 }
1359 }
1360 } else if (targetMetaType == dataMetaType) {
1361 targetRef = data.value<value_type>();
1362 return true;
1363 } else if (dataMetaType.flags() & QMetaType::PointerToGadget) {
1364 targetRef = *data.value<value_type *>();
1365 return true;
1366 }
1367 #ifndef QT_NO_DEBUG
1368 qCritical("Not able to assign %s to %s",
1369 qPrintable(QDebug::toString(data)), targetMetaType.name());
1370 #endif
1371 return false;
1372 } else if (row_traits::fixed_size() <= 1) {
1373 return writeRole(role, QRangeModelDetails::pointerTo(target), data);
1374 } else if (column <= row_traits::fixed_size()
1375 && (role == Qt::DisplayRole || role == Qt::EditRole)) {
1376 return writeProperty(column, QRangeModelDetails::pointerTo(target), data);
1377 }
1378 } else if constexpr (multi_role::value) {
1379 Qt::ItemDataRole roleToSet = Qt::ItemDataRole(role);
1380
1381
1382 const auto roleNames = [this]() -> QHash<int, QByteArray> {
1383 Q_UNUSED(this);
1384 if constexpr (!multi_role::int_key)
1385 return this->itemModel().roleNames();
1386 else
1387 return {};
1388 }();
1389 if (role == Qt::EditRole) {
1390 if constexpr (multi_role::int_key) {
1391 if (target.find(roleToSet) == target.end())
1392 roleToSet = Qt::DisplayRole;
1393 } else {
1394 if (target.find(roleNames.value(roleToSet)) == target.end())
1395 roleToSet = Qt::DisplayRole;
1396 }
1397 }
1398 if constexpr (multi_role::int_key)
1399 return write(target[roleToSet], data);
1400 else
1401 return write(target[roleNames.value(roleToSet)], data);
1402 } else if (role == Qt::DisplayRole || role == Qt::EditRole
1403 || role == Qt::RangeModelDataRole) {
1404 return write(target, data);
1405 }
1406 return false;
1407 };
1408
1409 success = writeAt(index, writeData);
1410 }
1411 return success;
1412 }
1413
1414 bool setItemData(const QModelIndex &index, const QMap<int, QVariant> &data)
1415 {
1416 if (!index.isValid() || data.isEmpty())
1417 return false;
1418
1419 bool success = false;
1420 if constexpr (isMutable()) {
1421 auto emitDataChanged = qScopeGuard([&success, this, &index, &data]{
1422 if (success)
1423 Q_EMIT this->dataChanged(index, index, data.keys());
1424 });
1425
1426 bool tried = false;
1427 auto writeItemData = [this, &tried, &data](auto &target) -> bool {
1428 Q_UNUSED(this);
1429 using value_type = q20::remove_cvref_t<decltype(target)>;
1430 using multi_role = QRangeModelDetails::is_multi_role<value_type>;
1431 if constexpr (multi_role()) {
1432 using key_type = typename value_type::key_type;
1433 tried = true;
1434 const auto roleName = [map = this->itemModel().roleNames()](int role) {
1435 return map.value(role);
1436 };
1437
1438
1439
1440 if constexpr (!multi_role::int_key)
1441 {
1442 auto invalid = std::find_if(data.keyBegin(), data.keyEnd(),
1443 [&roleName](int role) { return roleName(role).isEmpty(); }
1444 );
1445
1446 if (invalid != data.keyEnd()) {
1447 #ifndef QT_NO_DEBUG
1448 qWarning("No role name set for %d", *invalid);
1449 #endif
1450 return false;
1451 }
1452 }
1453
1454 for (auto &&[role, value] : data.asKeyValueRange()) {
1455 if constexpr (multi_role::int_key)
1456 target[static_cast<key_type>(role)] = value;
1457 else
1458 target[QString::fromUtf8(roleName(role))] = value;
1459 }
1460 return true;
1461 } else if constexpr (has_metaobject<value_type>) {
1462 if (row_traits::fixed_size() <= 1) {
1463 tried = true;
1464 using wrapped_type = QRangeModelDetails::wrapped_t<value_type>;
1465
1466
1467 auto targetCopy = [](auto &&origin) {
1468 if constexpr (!std::is_copy_assignable_v<wrapped_type>)
1469 return QRangeModelDetails::pointerTo(origin);
1470 else if constexpr (std::is_pointer_v<decltype(target)>)
1471 return *origin;
1472 else if constexpr (std::is_copy_assignable_v<value_type>)
1473 return origin;
1474 else
1475 return QRangeModelDetails::pointerTo(origin);
1476 }(target);
1477 const auto roleNames = this->itemModel().roleNames();
1478 for (auto &&[role, value] : data.asKeyValueRange()) {
1479 if (role == Qt::RangeModelDataRole)
1480 continue;
1481 if (!writeRole(role, QRangeModelDetails::pointerTo(targetCopy), value)) {
1482 const QByteArray roleName = roleNames.value(role);
1483 #ifndef QT_NO_DEBUG
1484 qWarning("Failed to write value '%s' to role '%s'",
1485 qPrintable(QDebug::toString(value)), roleName.data());
1486 #endif
1487 return false;
1488 }
1489 }
1490 if constexpr (std::is_pointer_v<decltype(targetCopy)>)
1491 ;
1492 else if constexpr (std::is_pointer_v<decltype(target)>)
1493 qSwap(*target, targetCopy);
1494 else
1495 qSwap(target, targetCopy);
1496 return true;
1497 }
1498 }
1499 return false;
1500 };
1501
1502 success = writeAt(index, writeItemData);
1503
1504 if (!tried) {
1505
1506 Q_ASSERT(!success);
1507 emitDataChanged.dismiss();
1508 success = this->itemModel().QAbstractItemModel::setItemData(index, data);
1509 }
1510 }
1511 return success;
1512 }
1513
1514 bool clearItemData(const QModelIndex &index)
1515 {
1516 if (!index.isValid())
1517 return false;
1518
1519 bool success = false;
1520 if constexpr (isMutable()) {
1521 auto emitDataChanged = qScopeGuard([&success, this, &index]{
1522 if (success)
1523 Q_EMIT this->dataChanged(index, index, {});
1524 });
1525
1526 auto clearData = [column = index.column()](auto &&target) {
1527 if constexpr (row_traits::hasMetaObject) {
1528 if (row_traits::fixed_size() <= 1) {
1529
1530 return resetProperty(-1, QRangeModelDetails::pointerTo(target));
1531 } else if (column <= row_traits::fixed_size()) {
1532 return resetProperty(column, QRangeModelDetails::pointerTo(target));
1533 }
1534 } else {
1535 target = {};
1536 return true;
1537 }
1538 return false;
1539 };
1540
1541 success = writeAt(index, clearData);
1542 }
1543 return success;
1544 }
1545
1546 QHash<int, QByteArray> roleNames() const
1547 {
1548
1549 using item_type = typename row_traits::item_type;
1550 if constexpr (QRangeModelDetails::has_metaobject_v<item_type>) {
1551 return QRangeModelImplBase::roleNamesForMetaObject(this->itemModel(),
1552 QRangeModelDetails::wrapped_t<item_type>::staticMetaObject);
1553 } else if constexpr (std::negation_v<std::disjunction<std::is_void<item_type>,
1554 QRangeModelDetails::is_multi_role<item_type>>>) {
1555 return QRangeModelImplBase::roleNamesForSimpleType();
1556 }
1557
1558 return this->itemModel().QAbstractItemModel::roleNames();
1559 }
1560
1561 bool insertColumns(int column, int count, const QModelIndex &parent)
1562 {
1563 if constexpr (dynamicColumns() && isMutable() && row_features::has_insert) {
1564 if (count == 0)
1565 return false;
1566 range_type * const children = childRange(parent);
1567 if (!children)
1568 return false;
1569
1570 this->beginInsertColumns(parent, column, column + count - 1);
1571 for (auto &child : *children) {
1572 auto it = QRangeModelDetails::pos(child, column);
1573 QRangeModelDetails::refTo(child).insert(it, count, {});
1574 }
1575 this->endInsertColumns();
1576 return true;
1577 }
1578 return false;
1579 }
1580
1581 bool removeColumns(int column, int count, const QModelIndex &parent)
1582 {
1583 if constexpr (dynamicColumns() && isMutable() && row_features::has_erase) {
1584 if (column < 0 || column + count > columnCount(parent))
1585 return false;
1586
1587 range_type * const children = childRange(parent);
1588 if (!children)
1589 return false;
1590
1591 this->beginRemoveColumns(parent, column, column + count - 1);
1592 for (auto &child : *children) {
1593 const auto start = QRangeModelDetails::pos(child, column);
1594 QRangeModelDetails::refTo(child).erase(start, std::next(start, count));
1595 }
1596 this->endRemoveColumns();
1597 return true;
1598 }
1599 return false;
1600 }
1601
1602 bool moveColumns(const QModelIndex &sourceParent, int sourceColumn, int count,
1603 const QModelIndex &destParent, int destColumn)
1604 {
1605
1606 if (sourceParent != destParent)
1607 return false;
1608 if constexpr (isMutable() && row_features::has_rotate) {
1609 if (!Structure::canMoveColumns(sourceParent, destParent))
1610 return false;
1611
1612 if constexpr (dynamicColumns()) {
1613
1614
1615 range_type * const children = childRange(sourceParent);
1616 if (!children)
1617 return false;
1618
1619 if (!this->beginMoveColumns(sourceParent, sourceColumn, sourceColumn + count - 1,
1620 destParent, destColumn)) {
1621 return false;
1622 }
1623
1624 for (auto &child : *children) {
1625 const auto first = QRangeModelDetails::pos(child, sourceColumn);
1626 const auto middle = std::next(first, count);
1627 const auto last = QRangeModelDetails::pos(child, destColumn);
1628
1629 if (sourceColumn < destColumn)
1630 std::rotate(first, middle, last);
1631 else
1632 std::rotate(last, first, middle);
1633 }
1634
1635 this->endMoveColumns();
1636 return true;
1637 }
1638 }
1639 return false;
1640 }
1641
1642 bool insertRows(int row, int count, const QModelIndex &parent)
1643 {
1644 if constexpr (canInsertRows()) {
1645 range_type *children = childRange(parent);
1646 if (!children)
1647 return false;
1648
1649 EmptyRowGenerator generator{0, &that(), &parent};
1650
1651 this->beginInsertRows(parent, row, row + count - 1);
1652
1653 const auto pos = QRangeModelDetails::pos(children, row);
1654 if constexpr (range_features::has_insert_range) {
1655 children->insert(pos, generator, EmptyRowGenerator{count});
1656 } else if constexpr (rows_are_owning_or_raw_pointers) {
1657 auto start = children->insert(pos, count, row_type{});
1658 std::copy(generator, EmptyRowGenerator{count}, start);
1659 } else {
1660 children->insert(pos, count, *generator);
1661 }
1662
1663
1664
1665 that().resetParentInChildren(children);
1666
1667 this->endInsertRows();
1668 return true;
1669 } else {
1670 return false;
1671 }
1672 }
1673
1674 bool removeRows(int row, int count, const QModelIndex &parent = {})
1675 {
1676 if constexpr (canRemoveRows()) {
1677 const int prevRowCount = rowCount(parent);
1678 if (row < 0 || row + count > prevRowCount)
1679 return false;
1680
1681 range_type *children = childRange(parent);
1682 if (!children)
1683 return false;
1684
1685 this->beginRemoveRows(parent, row, row + count - 1);
1686 [[maybe_unused]] bool callEndRemoveColumns = false;
1687 if constexpr (dynamicColumns()) {
1688
1689
1690 if (prevRowCount == count) {
1691 if (const int columns = columnCount(parent)) {
1692 callEndRemoveColumns = true;
1693 this->beginRemoveColumns(parent, 0, columns - 1);
1694 }
1695 }
1696 }
1697 {
1698 const auto begin = QRangeModelDetails::pos(children, row);
1699 const auto end = std::next(begin, count);
1700 that().deleteRemovedRows(begin, end);
1701 children->erase(begin, end);
1702 }
1703
1704
1705 that().resetParentInChildren(children);
1706
1707 if constexpr (dynamicColumns()) {
1708 if (callEndRemoveColumns) {
1709 Q_ASSERT(columnCount(parent) == 0);
1710 this->endRemoveColumns();
1711 }
1712 }
1713 this->endRemoveRows();
1714 return true;
1715 } else {
1716 return false;
1717 }
1718 }
1719
1720 bool moveRows(const QModelIndex &sourceParent, int sourceRow, int count,
1721 const QModelIndex &destParent, int destRow)
1722 {
1723 if constexpr (isMutable() && range_features::has_rotate) {
1724 if (!Structure::canMoveRows(sourceParent, destParent))
1725 return false;
1726
1727 if (sourceParent != destParent) {
1728 return that().moveRowsAcross(sourceParent, sourceRow, count,
1729 destParent, destRow);
1730 }
1731
1732 if (sourceRow == destRow || sourceRow == destRow - 1 || count <= 0
1733 || sourceRow < 0 || sourceRow + count - 1 >= this->itemModel().rowCount(sourceParent)
1734 || destRow < 0 || destRow > this->itemModel().rowCount(destParent)) {
1735 return false;
1736 }
1737
1738 range_type *source = childRange(sourceParent);
1739
1740 if (!this->beginMoveRows(sourceParent, sourceRow, sourceRow + count - 1, destParent, destRow))
1741 return false;
1742
1743 const auto first = QRangeModelDetails::pos(source, sourceRow);
1744 const auto middle = std::next(first, count);
1745 const auto last = QRangeModelDetails::pos(source, destRow);
1746
1747 if (sourceRow < destRow)
1748 std::rotate(first, middle, last);
1749 else
1750 std::rotate(last, first, middle);
1751
1752 that().resetParentInChildren(source);
1753
1754 this->endMoveRows();
1755 return true;
1756 } else {
1757 return false;
1758 }
1759 }
1760
1761 QModelIndex parent(const QModelIndex &child) const { return that().parent(child); }
1762
1763 int rowCount(const QModelIndex &parent) const { return that().rowCount(parent); }
1764
1765 int columnCount(const QModelIndex &parent) const { return that().columnCount(parent); }
1766
1767 void destroy() { delete std::addressof(that()); }
1768
1769 template <typename BaseMethod, typename BaseMethod::template Overridden<Self> overridden>
1770 using Override = typename Ancestor::template Override<BaseMethod, overridden>;
1771
1772 using Destroy = Override<QRangeModelImplBase::Destroy, &Self::destroy>;
1773 using Index = Override<QRangeModelImplBase::Index, &Self::index>;
1774 using Parent = Override<QRangeModelImplBase::Parent, &Self::parent>;
1775 using Sibling = Override<QRangeModelImplBase::Sibling, &Self::sibling>;
1776 using RowCount = Override<QRangeModelImplBase::RowCount, &Self::rowCount>;
1777 using ColumnCount = Override<QRangeModelImplBase::ColumnCount, &Self::columnCount>;
1778 using Flags = Override<QRangeModelImplBase::Flags, &Self::flags>;
1779 using HeaderData = Override<QRangeModelImplBase::HeaderData, &Self::headerData>;
1780
1781 using Data = Override<QRangeModelImplBase::Data, &Self::data>;
1782 using ItemData = Override<QRangeModelImplBase::ItemData, &Self::itemData>;
1783 using RoleNames = Override<QRangeModelImplBase::RoleNames, &Self::roleNames>;
1784 using InvalidateCaches = Override<QRangeModelImplBase::InvalidateCaches, &Self::invalidateCaches>;
1785 using SetHeaderData = Override<QRangeModelImplBase::SetHeaderData, &Self::setHeaderData>;
1786 using SetData = Override<QRangeModelImplBase::SetData, &Self::setData>;
1787 using SetItemData = Override<QRangeModelImplBase::SetItemData, &Self::setItemData>;
1788 using ClearItemData = Override<QRangeModelImplBase::ClearItemData, &Self::clearItemData>;
1789 using InsertColumns = Override<QRangeModelImplBase::InsertColumns, &Self::insertColumns>;
1790 using RemoveColumns = Override<QRangeModelImplBase::RemoveColumns, &Self::removeColumns>;
1791 using MoveColumns = Override<QRangeModelImplBase::MoveColumns, &Self::moveColumns>;
1792 using InsertRows = Override<QRangeModelImplBase::InsertRows, &Self::insertRows>;
1793 using RemoveRows = Override<QRangeModelImplBase::RemoveRows, &Self::removeRows>;
1794 using MoveRows = Override<QRangeModelImplBase::MoveRows, &Self::moveRows>;
1795
1796 protected:
1797 ~QRangeModelImpl()
1798 {
1799
1800
1801
1802
1803
1804
1805
1806
1807 static constexpr bool modelCopied = !QRangeModelDetails::is_wrapped<Range>() &&
1808 (std::is_reference_v<Range> || std::is_const_v<std::remove_reference_t<Range>>);
1809
1810 static constexpr bool modelShared = QRangeModelDetails::is_any_shared_ptr<Range>();
1811
1812 static constexpr bool default_row_deleter = protocol_traits::is_default &&
1813 protocol_traits::has_deleteRow;
1814
1815 static constexpr bool ambiguousRowOwnership = (modelCopied || modelShared) &&
1816 rows_are_raw_pointers && default_row_deleter;
1817
1818 static_assert(!ambiguousRowOwnership,
1819 "Using of copied and shared tree and table models with rows as raw pointers, "
1820 "and the default protocol is not allowed due to ambiguity of rows ownership. "
1821 "Move the model in, use another row type, or implement a custom tree protocol.");
1822
1823 if constexpr (protocol_traits::has_deleteRow && !std::is_pointer_v<Range>
1824 && !QRangeModelDetails::is_any_of<Range, std::reference_wrapper>()) {
1825 const auto begin = QRangeModelDetails::begin(*m_data.model());
1826 const auto end = QRangeModelDetails::end(*m_data.model());
1827 that().deleteRemovedRows(begin, end);
1828 }
1829 }
1830
1831 static constexpr bool canInsertRows()
1832 {
1833 if constexpr (dynamicColumns() && !row_features::has_resize) {
1834
1835
1836 return false;
1837 } else if constexpr (!protocol_traits::has_newRow) {
1838
1839 return false;
1840 } else if constexpr (!range_features::has_insert_range
1841 && !std::is_copy_constructible_v<row_type>) {
1842
1843
1844
1845 return false;
1846 } else {
1847 return Structure::canInsertRowsImpl();
1848 }
1849 }
1850
1851 static constexpr bool canRemoveRows()
1852 {
1853 return Structure::canRemoveRowsImpl();
1854 }
1855
1856 template <typename F>
1857 bool writeAt(const QModelIndex &index, F&& writer)
1858 {
1859 bool result = false;
1860 row_reference row = rowData(index);
1861
1862 if constexpr (one_dimensional_range) {
1863 result = writer(row);
1864 } else if (QRangeModelDetails::isValid(row)) {
1865 if constexpr (dynamicColumns()) {
1866 result = writer(*QRangeModelDetails::pos(row, index.column()));
1867 } else {
1868 QRangeModelImplBase::for_element_at(row, index.column(), [&writer, &result](auto &&target) {
1869 using target_type = decltype(target);
1870
1871 if constexpr (std::is_lvalue_reference_v<target_type>
1872 && !std::is_const_v<std::remove_reference_t<target_type>>) {
1873 result = writer(std::forward<target_type>(target));
1874 }
1875 });
1876 }
1877 }
1878
1879 return result;
1880 }
1881
1882 template <typename F>
1883 void readAt(const QModelIndex &index, F&& reader) const {
1884 const_row_reference row = rowData(index);
1885 if constexpr (one_dimensional_range) {
1886 return reader(row);
1887 } else if (QRangeModelDetails::isValid(row)) {
1888 if constexpr (dynamicColumns())
1889 reader(*QRangeModelDetails::pos(row, index.column()));
1890 else
1891 QRangeModelImplBase::for_element_at(row, index.column(), std::forward<F>(reader));
1892 }
1893 }
1894
1895 template <typename Value>
1896 static QVariant read(const Value &value)
1897 {
1898 if constexpr (std::is_constructible_v<QVariant, Value>)
1899 return QVariant(value);
1900 else
1901 return QVariant::fromValue(value);
1902 }
1903 template <typename Value>
1904 static QVariant read(Value *value)
1905 {
1906 if (value) {
1907 if constexpr (std::is_constructible_v<QVariant, Value *>)
1908 return QVariant(value);
1909 else
1910 return read(*value);
1911 }
1912 return {};
1913 }
1914
1915 template <typename Target>
1916 static bool write(Target &target, const QVariant &value)
1917 {
1918 using Type = std::remove_reference_t<Target>;
1919 if constexpr (std::is_constructible_v<Target, QVariant>) {
1920 target = value;
1921 return true;
1922 } else if (value.canConvert<Type>()) {
1923 target = value.value<Type>();
1924 return true;
1925 }
1926 return false;
1927 }
1928 template <typename Target>
1929 static bool write(Target *target, const QVariant &value)
1930 {
1931 if (target)
1932 return write(*target, value);
1933 return false;
1934 }
1935
1936 template <typename ItemType>
1937 QMetaProperty roleProperty(int role) const
1938 {
1939 struct {
1940 operator QMetaProperty() const {
1941 const QByteArray roleName = that.itemModel().roleNames().value(role);
1942 const QMetaObject &mo = ItemType::staticMetaObject;
1943 if (const int index = mo.indexOfProperty(roleName.data());
1944 index >= 0) {
1945 return mo.property(index);
1946 }
1947 return {};
1948 }
1949 const QRangeModelImpl &that;
1950 const int role;
1951 } findProperty{*this, role};
1952
1953 if constexpr (ModelData::cachesProperties)
1954 return *m_data.properties.tryEmplace(role, findProperty).iterator;
1955 else
1956 return findProperty;
1957 }
1958
1959 template <typename ItemType>
1960 QVariant readRole(int role, ItemType *gadget) const
1961 {
1962 using item_type = std::remove_pointer_t<ItemType>;
1963 QVariant result;
1964 QMetaProperty prop = roleProperty<item_type>(role);
1965 if (!prop.isValid() && role == Qt::EditRole)
1966 prop = roleProperty<item_type>(Qt::DisplayRole);
1967
1968 if (prop.isValid())
1969 result = readProperty(prop, gadget);
1970 return result;
1971 }
1972
1973 template <typename ItemType>
1974 QVariant readRole(int role, const ItemType &gadget) const
1975 {
1976 return readRole(role, &gadget);
1977 }
1978
1979 template <typename ItemType>
1980 static QVariant readProperty(const QMetaProperty &prop, ItemType *gadget)
1981 {
1982 if constexpr (std::is_base_of_v<QObject, ItemType>)
1983 return prop.read(gadget);
1984 else
1985 return prop.readOnGadget(gadget);
1986 }
1987 template <typename ItemType>
1988 static QVariant readProperty(int property, ItemType *gadget)
1989 {
1990 using item_type = std::remove_pointer_t<ItemType>;
1991 const QMetaObject &mo = item_type::staticMetaObject;
1992 const QMetaProperty prop = mo.property(property + mo.propertyOffset());
1993 return readProperty(prop, gadget);
1994 }
1995
1996 template <typename ItemType>
1997 static QVariant readProperty(int property, const ItemType &gadget)
1998 {
1999 return readProperty(property, &gadget);
2000 }
2001
2002 template <typename ItemType>
2003 bool writeRole(int role, ItemType *gadget, const QVariant &data)
2004 {
2005 using item_type = std::remove_pointer_t<ItemType>;
2006 auto prop = roleProperty<item_type>(role);
2007 if (!prop.isValid() && role == Qt::EditRole)
2008 prop = roleProperty<item_type>(Qt::DisplayRole);
2009
2010 return prop.isValid() ? writeProperty(prop, gadget, data) : false;
2011 }
2012
2013 template <typename ItemType>
2014 bool writeRole(int role, ItemType &&gadget, const QVariant &data)
2015 {
2016 return writeRole(role, &gadget, data);
2017 }
2018
2019 template <typename ItemType>
2020 static bool writeProperty(const QMetaProperty &prop, ItemType *gadget, const QVariant &data)
2021 {
2022 if constexpr (std::is_base_of_v<QObject, ItemType>)
2023 return prop.write(gadget, data);
2024 else
2025 return prop.writeOnGadget(gadget, data);
2026 }
2027 template <typename ItemType>
2028 static bool writeProperty(int property, ItemType *gadget, const QVariant &data)
2029 {
2030 using item_type = std::remove_pointer_t<ItemType>;
2031 const QMetaObject &mo = item_type::staticMetaObject;
2032 return writeProperty(mo.property(property + mo.propertyOffset()), gadget, data);
2033 }
2034
2035 template <typename ItemType>
2036 static bool writeProperty(int property, ItemType &&gadget, const QVariant &data)
2037 {
2038 return writeProperty(property, &gadget, data);
2039 }
2040
2041 template <typename ItemType>
2042 static bool resetProperty(int property, ItemType *object)
2043 {
2044 using item_type = std::remove_pointer_t<ItemType>;
2045 const QMetaObject &mo = item_type::staticMetaObject;
2046 bool success = true;
2047 if (property == -1) {
2048
2049 if constexpr (std::is_base_of_v<QObject, item_type>) {
2050 for (int p = mo.propertyOffset(); p < mo.propertyCount(); ++p)
2051 success = writeProperty(mo.property(p), object, {}) && success;
2052 } else {
2053 *object = {};
2054 }
2055 } else {
2056 success = writeProperty(mo.property(property + mo.propertyOffset()), object, {});
2057 }
2058 return success;
2059 }
2060
2061 template <typename ItemType>
2062 static bool resetProperty(int property, ItemType &&object)
2063 {
2064 return resetProperty(property, &object);
2065 }
2066
2067
2068 const_row_reference rowData(const QModelIndex &index) const
2069 {
2070 Q_ASSERT(index.isValid());
2071 return that().rowDataImpl(index);
2072 }
2073
2074 row_reference rowData(const QModelIndex &index)
2075 {
2076 Q_ASSERT(index.isValid());
2077 return that().rowDataImpl(index);
2078 }
2079
2080 const range_type *childRange(const QModelIndex &index) const
2081 {
2082 if (!index.isValid())
2083 return m_data.model();
2084 if (index.column())
2085 return nullptr;
2086 return that().childRangeImpl(index);
2087 }
2088
2089 range_type *childRange(const QModelIndex &index)
2090 {
2091 if (!index.isValid())
2092 return m_data.model();
2093 if (index.column())
2094 return nullptr;
2095 return that().childRangeImpl(index);
2096 }
2097
2098
2099 const protocol_type& protocol() const { return QRangeModelDetails::refTo(m_protocol); }
2100 protocol_type& protocol() { return QRangeModelDetails::refTo(m_protocol); }
2101
2102 ModelData m_data;
2103 Protocol m_protocol;
2104 };
2105
2106
2107
2108
2109 template <typename Range, typename Protocol>
2110 class QGenericTreeItemModelImpl
2111 : public QRangeModelImpl<QGenericTreeItemModelImpl<Range, Protocol>, Range, Protocol>
2112 {
2113 using Base = QRangeModelImpl<QGenericTreeItemModelImpl<Range, Protocol>, Range, Protocol>;
2114 friend class QRangeModelImpl<QGenericTreeItemModelImpl<Range, Protocol>, Range, Protocol>;
2115
2116 using range_type = typename Base::range_type;
2117 using range_features = typename Base::range_features;
2118 using row_type = typename Base::row_type;
2119 using row_ptr = typename Base::row_ptr;
2120 using const_row_ptr = typename Base::const_row_ptr;
2121
2122 using tree_traits = typename Base::protocol_traits;
2123 static constexpr bool is_mutable_impl = tree_traits::has_mutable_childRows;
2124
2125 static constexpr bool rows_are_any_refs_or_pointers = Base::rows_are_raw_pointers ||
2126 QRangeModelDetails::is_smart_ptr<row_type>() ||
2127 QRangeModelDetails::is_any_of<row_type, std::reference_wrapper>();
2128 static_assert(!Base::dynamicColumns(), "A tree must have a static number of columns!");
2129
2130 public:
2131 QGenericTreeItemModelImpl(Range &&model, Protocol &&p, QRangeModel *itemModel)
2132 : Base(std::forward<Range>(model), std::forward<Protocol>(p), itemModel)
2133 {};
2134
2135 protected:
2136 QModelIndex indexImpl(int row, int column, const QModelIndex &parent) const
2137 {
2138 if (!parent.isValid())
2139 return this->createIndex(row, column);
2140
2141 if (parent.column())
2142 return QModelIndex();
2143
2144 const_row_ptr grandParent = static_cast<const_row_ptr>(parent.constInternalPointer());
2145 const auto &parentSiblings = childrenOf(grandParent);
2146 const auto it = QRangeModelDetails::pos(parentSiblings, parent.row());
2147 return this->createIndex(row, column, QRangeModelDetails::pointerTo(*it));
2148 }
2149
2150 QModelIndex parent(const QModelIndex &child) const
2151 {
2152 if (!child.isValid())
2153 return {};
2154
2155
2156 const_row_ptr parentRow = static_cast<const_row_ptr>(child.constInternalPointer());
2157 if (!parentRow)
2158 return {};
2159
2160
2161 auto &&grandParent = this->protocol().parentRow(QRangeModelDetails::refTo(parentRow));
2162 const range_type &parentSiblings = childrenOf(QRangeModelDetails::pointerTo(grandParent));
2163
2164 const auto begin = QRangeModelDetails::begin(parentSiblings);
2165 const auto end = QRangeModelDetails::end(parentSiblings);
2166 const auto it = std::find_if(begin, end, [parentRow](auto &&s){
2167 return QRangeModelDetails::pointerTo(std::forward<decltype(s)>(s)) == parentRow;
2168 });
2169 if (it != end)
2170 return this->createIndex(std::distance(begin, it), 0,
2171 QRangeModelDetails::pointerTo(grandParent));
2172 return {};
2173 }
2174
2175 int rowCount(const QModelIndex &parent) const
2176 {
2177 return Base::size(this->childRange(parent));
2178 }
2179
2180 int columnCount(const QModelIndex &) const
2181 {
2182
2183 if constexpr (Base::one_dimensional_range)
2184 return 1;
2185 else
2186 return Base::static_column_count;
2187 }
2188
2189 static constexpr Qt::ItemFlags defaultFlags()
2190 {
2191 return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
2192 }
2193
2194 static constexpr bool canInsertRowsImpl()
2195 {
2196
2197
2198
2199 return (rows_are_any_refs_or_pointers || tree_traits::has_setParentRow)
2200 && Base::dynamicRows() && range_features::has_insert;
2201 }
2202
2203 static constexpr bool canRemoveRowsImpl()
2204 {
2205
2206
2207
2208 return (rows_are_any_refs_or_pointers || tree_traits::has_setParentRow)
2209 && Base::dynamicRows() && range_features::has_erase;
2210 }
2211
2212 static constexpr bool canMoveColumns(const QModelIndex &, const QModelIndex &)
2213 {
2214 return true;
2215 }
2216
2217 static constexpr bool canMoveRows(const QModelIndex &, const QModelIndex &)
2218 {
2219 return true;
2220 }
2221
2222 bool moveRowsAcross(const QModelIndex &sourceParent, int sourceRow, int count,
2223 const QModelIndex &destParent, int destRow)
2224 {
2225
2226
2227
2228 if constexpr (!rows_are_any_refs_or_pointers && !tree_traits::has_setParentRow) {
2229 return false;
2230 } else if constexpr (!(range_features::has_insert && range_features::has_erase)) {
2231 return false;
2232 } else if (!this->beginMoveRows(sourceParent, sourceRow, sourceRow + count - 1,
2233 destParent, destRow)) {
2234 return false;
2235 }
2236
2237 range_type *source = this->childRange(sourceParent);
2238 range_type *destination = this->childRange(destParent);
2239
2240
2241
2242 const auto destStart = QRangeModelDetails::pos(destination, destRow);
2243 if constexpr (range_features::has_insert_range) {
2244 const auto sourceStart = QRangeModelDetails::pos(*source, sourceRow);
2245 const auto sourceEnd = std::next(sourceStart, count);
2246
2247 destination->insert(destStart, std::move_iterator(sourceStart),
2248 std::move_iterator(sourceEnd));
2249 } else if constexpr (std::is_copy_constructible_v<row_type>) {
2250
2251 destination->insert(destStart, count, row_type{});
2252 }
2253
2254 row_ptr parentRow = destParent.isValid()
2255 ? QRangeModelDetails::pointerTo(this->rowData(destParent))
2256 : nullptr;
2257
2258
2259
2260 if (parentRow == static_cast<row_ptr>(sourceParent.internalPointer())) {
2261 if (sourceParent.row() < destRow) {
2262 source = this->childRange(sourceParent);
2263 } else {
2264
2265 source = this->childRange(this->createIndex(sourceParent.row() + count, 0,
2266 sourceParent.internalPointer()));
2267 }
2268 }
2269
2270
2271 {
2272 const auto writeStart = QRangeModelDetails::pos(destination, destRow);
2273 const auto writeEnd = std::next(writeStart, count);
2274 const auto sourceStart = QRangeModelDetails::pos(source, sourceRow);
2275 const auto sourceEnd = std::next(sourceStart, count);
2276
2277 for (auto write = writeStart, read = sourceStart; write != writeEnd; ++write, ++read) {
2278
2279
2280 if constexpr (!range_features::has_insert_range)
2281 *write = std::move(*read);
2282 this->protocol().setParentRow(QRangeModelDetails::refTo(*write), parentRow);
2283 }
2284
2285 source->erase(sourceStart, sourceEnd);
2286 }
2287
2288
2289
2290
2291
2292 resetParentInChildren(destination);
2293 resetParentInChildren(source);
2294
2295 this->endMoveRows();
2296 return true;
2297 }
2298
2299 auto makeEmptyRow(const QModelIndex &parent)
2300 {
2301
2302
2303 static_assert(tree_traits::has_setParentRow);
2304 row_type empty_row = this->protocol().newRow();
2305 if (QRangeModelDetails::isValid(empty_row) && parent.isValid()) {
2306 this->protocol().setParentRow(QRangeModelDetails::refTo(empty_row),
2307 QRangeModelDetails::pointerTo(this->rowData(parent)));
2308 }
2309 return empty_row;
2310 }
2311
2312 template <typename It, typename Sentinel>
2313 void deleteRemovedRows(It &&begin, Sentinel &&end)
2314 {
2315 if constexpr (tree_traits::has_deleteRow) {
2316 for (auto it = begin; it != end; ++it) {
2317 if constexpr (Base::isMutable()) {
2318 decltype(auto) children = this->protocol().childRows(QRangeModelDetails::refTo(*it));
2319 if (QRangeModelDetails::isValid(children)) {
2320 deleteRemovedRows(QRangeModelDetails::begin(children),
2321 QRangeModelDetails::end(children));
2322 QRangeModelDetails::refTo(children) = range_type{ };
2323 }
2324 }
2325
2326 this->protocol().deleteRow(std::move(*it));
2327 }
2328 }
2329 }
2330
2331 void resetParentInChildren(range_type *children)
2332 {
2333 if constexpr (tree_traits::has_setParentRow && !rows_are_any_refs_or_pointers) {
2334 const auto begin = QRangeModelDetails::begin(*children);
2335 const auto end = QRangeModelDetails::end(*children);
2336 for (auto it = begin; it != end; ++it) {
2337 decltype(auto) maybeChildren = this->protocol().childRows(*it);
2338 if (QRangeModelDetails::isValid(maybeChildren)) {
2339 auto &childrenRef = QRangeModelDetails::refTo(maybeChildren);
2340 QModelIndexList fromIndexes;
2341 QModelIndexList toIndexes;
2342 fromIndexes.reserve(Base::size(childrenRef));
2343 toIndexes.reserve(Base::size(childrenRef));
2344 auto *parentRow = QRangeModelDetails::pointerTo(*it);
2345
2346 int row = 0;
2347 for (auto &child : childrenRef) {
2348 const_row_ptr oldParent = this->protocol().parentRow(child);
2349 if (oldParent != parentRow) {
2350 fromIndexes.append(this->createIndex(row, 0, oldParent));
2351 toIndexes.append(this->createIndex(row, 0, parentRow));
2352 this->protocol().setParentRow(child, parentRow);
2353 }
2354 ++row;
2355 }
2356 this->changePersistentIndexList(fromIndexes, toIndexes);
2357 resetParentInChildren(&childrenRef);
2358 }
2359 }
2360 }
2361 }
2362
2363 decltype(auto) rowDataImpl(const QModelIndex &index) const
2364 {
2365 const_row_ptr parentRow = static_cast<const_row_ptr>(index.constInternalPointer());
2366 const range_type &siblings = childrenOf(parentRow);
2367 Q_ASSERT(index.row() < int(Base::size(siblings)));
2368 return *QRangeModelDetails::pos(siblings, index.row());
2369 }
2370
2371 decltype(auto) rowDataImpl(const QModelIndex &index)
2372 {
2373 row_ptr parentRow = static_cast<row_ptr>(index.internalPointer());
2374 range_type &siblings = childrenOf(parentRow);
2375 Q_ASSERT(index.row() < int(Base::size(siblings)));
2376 return *QRangeModelDetails::pos(siblings, index.row());
2377 }
2378
2379 const range_type *childRangeImpl(const QModelIndex &index) const
2380 {
2381 const auto &row = this->rowData(index);
2382 if (!QRangeModelDetails::isValid(row))
2383 return static_cast<const range_type *>(nullptr);
2384
2385 decltype(auto) children = this->protocol().childRows(QRangeModelDetails::refTo(row));
2386 return QRangeModelDetails::pointerTo(std::forward<decltype(children)>(children));
2387 }
2388
2389 range_type *childRangeImpl(const QModelIndex &index)
2390 {
2391 auto &row = this->rowData(index);
2392 if (!QRangeModelDetails::isValid(row))
2393 return static_cast<range_type *>(nullptr);
2394
2395 decltype(auto) children = this->protocol().childRows(QRangeModelDetails::refTo(row));
2396 using Children = std::remove_reference_t<decltype(children)>;
2397
2398 if constexpr (QRangeModelDetails::is_any_of<Children, std::optional>())
2399 if constexpr (std::is_default_constructible<typename Children::value_type>()) {
2400 if (!children)
2401 children.emplace(range_type{});
2402 }
2403
2404 return QRangeModelDetails::pointerTo(std::forward<decltype(children)>(children));
2405 }
2406
2407 const range_type &childrenOf(const_row_ptr row) const
2408 {
2409 return row ? QRangeModelDetails::refTo(this->protocol().childRows(*row))
2410 : *this->m_data.model();
2411 }
2412
2413 private:
2414 range_type &childrenOf(row_ptr row)
2415 {
2416 return row ? QRangeModelDetails::refTo(this->protocol().childRows(*row))
2417 : *this->m_data.model();
2418 }
2419 };
2420
2421
2422 template <typename Range>
2423 class QGenericTableItemModelImpl
2424 : public QRangeModelImpl<QGenericTableItemModelImpl<Range>, Range>
2425 {
2426 using Base = QRangeModelImpl<QGenericTableItemModelImpl<Range>, Range>;
2427 friend class QRangeModelImpl<QGenericTableItemModelImpl<Range>, Range>;
2428
2429 using range_type = typename Base::range_type;
2430 using range_features = typename Base::range_features;
2431 using row_type = typename Base::row_type;
2432 using const_row_ptr = typename Base::const_row_ptr;
2433 using row_traits = typename Base::row_traits;
2434 using row_features = typename Base::row_features;
2435
2436 static constexpr bool is_mutable_impl = true;
2437
2438 public:
2439 explicit QGenericTableItemModelImpl(Range &&model, QRangeModel *itemModel)
2440 : Base(std::forward<Range>(model), {}, itemModel)
2441 {}
2442
2443 protected:
2444 QModelIndex indexImpl(int row, int column, const QModelIndex &) const
2445 {
2446 if constexpr (Base::dynamicColumns()) {
2447 if (column < int(Base::size(*QRangeModelDetails::pos(*this->m_data.model(), row))))
2448 return this->createIndex(row, column);
2449 #ifndef QT_NO_DEBUG
2450
2451 qCritical("QRangeModel: Column-range at row %d is not large enough!", row);
2452 #endif
2453 return {};
2454 } else {
2455 return this->createIndex(row, column);
2456 }
2457 }
2458
2459 QModelIndex parent(const QModelIndex &) const
2460 {
2461 return {};
2462 }
2463
2464 int rowCount(const QModelIndex &parent) const
2465 {
2466 if (parent.isValid())
2467 return 0;
2468 return int(Base::size(*this->m_data.model()));
2469 }
2470
2471 int columnCount(const QModelIndex &parent) const
2472 {
2473 if (parent.isValid())
2474 return 0;
2475
2476
2477 if constexpr (Base::dynamicColumns()) {
2478 return int(Base::size(*this->m_data.model()) == 0
2479 ? 0
2480 : Base::size(*QRangeModelDetails::begin(*this->m_data.model())));
2481 } else if constexpr (Base::one_dimensional_range) {
2482 return row_traits::fixed_size();
2483 } else {
2484 return Base::static_column_count;
2485 }
2486 }
2487
2488 static constexpr Qt::ItemFlags defaultFlags()
2489 {
2490 return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemNeverHasChildren;
2491 }
2492
2493 static constexpr bool canInsertRowsImpl()
2494 {
2495 return Base::dynamicRows() && range_features::has_insert;
2496 }
2497
2498 static constexpr bool canRemoveRowsImpl()
2499 {
2500 return Base::dynamicRows() && range_features::has_erase;
2501 }
2502
2503 static constexpr bool canMoveColumns(const QModelIndex &source, const QModelIndex &destination)
2504 {
2505 return !source.isValid() && !destination.isValid();
2506 }
2507
2508 static constexpr bool canMoveRows(const QModelIndex &source, const QModelIndex &destination)
2509 {
2510 return !source.isValid() && !destination.isValid();
2511 }
2512
2513 constexpr bool moveRowsAcross(const QModelIndex &, int , int,
2514 const QModelIndex &, int) noexcept
2515 {
2516
2517 return false;
2518 }
2519
2520 auto makeEmptyRow(const QModelIndex &)
2521 {
2522 row_type empty_row = this->protocol().newRow();
2523
2524
2525 if constexpr (Base::dynamicColumns() && row_features::has_resize) {
2526 if (QRangeModelDetails::isValid(empty_row))
2527 QRangeModelDetails::refTo(empty_row).resize(this->itemModel().columnCount());
2528 }
2529
2530 return empty_row;
2531 }
2532
2533 template <typename It, typename Sentinel>
2534 void deleteRemovedRows(It &&begin, Sentinel &&end)
2535 {
2536 if constexpr (Base::protocol_traits::has_deleteRow) {
2537 for (auto it = begin; it != end; ++it)
2538 this->protocol().deleteRow(std::move(*it));
2539 }
2540 }
2541
2542 decltype(auto) rowDataImpl(const QModelIndex &index) const
2543 {
2544 Q_ASSERT(q20::cmp_less(index.row(), Base::size(*this->m_data.model())));
2545 return *QRangeModelDetails::pos(*this->m_data.model(), index.row());
2546 }
2547
2548 decltype(auto) rowDataImpl(const QModelIndex &index)
2549 {
2550 Q_ASSERT(q20::cmp_less(index.row(), Base::size(*this->m_data.model())));
2551 return *QRangeModelDetails::pos(*this->m_data.model(), index.row());
2552 }
2553
2554 const range_type *childRangeImpl(const QModelIndex &) const
2555 {
2556 return nullptr;
2557 }
2558
2559 range_type *childRangeImpl(const QModelIndex &)
2560 {
2561 return nullptr;
2562 }
2563
2564 const range_type &childrenOf(const_row_ptr row) const
2565 {
2566 Q_ASSERT(!row);
2567 return *this->m_data.model();
2568 }
2569
2570 void resetParentInChildren(range_type *)
2571 {
2572 }
2573 };
2574
2575 QT_END_NAMESPACE
2576
2577 #endif
2578
2579 #endif