1// Copyright (C) 2025 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
5#include "qrangemodel.h"
6#include <QtCore/qsize.h>
7
8#include <QtCore/private/qabstractitemmodel_p.h>
9
10QT_BEGIN_NAMESPACE
11
12class QRangeModelPrivate : QAbstractItemModelPrivate
13{
14 Q_DECLARE_PUBLIC(QRangeModel)
15
16public:
17 explicit QRangeModelPrivate(std::unique_ptr<QRangeModelImplBase, QRangeModelImplBase::Deleter> impl)
18 : impl(std::move(impl))
19 {}
20
21private:
22 std::unique_ptr<QRangeModelImplBase, QRangeModelImplBase::Deleter> impl;
23 mutable QHash<int, QByteArray> m_roleNames;
24};
25
26QRangeModel::QRangeModel(QRangeModelImplBase *impl, QObject *parent)
27 : QAbstractItemModel(*new QRangeModelPrivate({impl, {}}), parent)
28{
29}
30
31/*!
32 \class QRangeModel
33 \inmodule QtCore
34 \since 6.10
35 \ingroup model-view
36 \brief QRangeModel implements QAbstractItemModel for any C++ range.
37 \reentrant
38
39 QRangeModel can make the data in any sequentially iterable C++ type
40 available to the \l{Model/View Programming}{model/view framework} of Qt.
41 This makes it easy to display existing data structures in the Qt Widgets
42 and Qt Quick item views, and to allow the user of the application to
43 manipulate the data using a graphical user interface.
44
45 To use QRangeModel, instantiate it with a C++ range and set it as
46 the model of one or more views:
47
48 \snippet qrangemodel/main.cpp array
49
50 \section1 Constructing the model
51
52 The range can be any C++ type for which the standard methods
53 \c{std::begin} and \c{std::end} are implemented, and for which the
54 returned iterator type satisfies \c{std::forward_iterator}. Certain model
55 operations will perform better if \c{std::size} is available, and if the
56 iterator satisfies \c{std::random_access_iterator}.
57
58 The range must be provided when constructing the model; there is no API to
59 set the range later, and there is no API to retrieve the range from the
60 model. The range can be provided by value, reference wrapper, or pointer.
61 How the model was constructed defines whether changes through the model API
62 will modify the original data.
63
64 When constructed by value, the model makes a copy of the range, and
65 QAbstractItemModel APIs that modify the model, such as setData() or
66 insertRows(), have no impact on the original range.
67
68 \snippet qrangemodel/main.cpp value
69
70 As there is no API to retrieve the range again, constructing the model from
71 a range by value is mostly only useful for displaying read-only data.
72 Changes to the data can be monitored using the signals emitted by the
73 model, such as \l{QAbstractItemModel}{dataChanged()}.
74
75 To make modifications of the model affect the original range, provide the
76 range either by pointer:
77
78 \snippet qrangemodel/main.cpp pointer
79
80 or through a reference wrapper:
81
82 \snippet qrangemodel/main.cpp reference_wrapper
83
84 In this case, QAbstractItemModel APIs that modify the model also modify the
85 range. Methods that modify the structure of the range, such as insertRows()
86 or removeColumns(), use standard C++ container APIs \c{resize()},
87 \c{insert()}, \c{erase()}, in addition to dereferencing a mutating iterator
88 to set or clear the data.
89
90 \note Once the model has been constructed and passed on to a view, the
91 range that the model operates on must no longer be modified directly. Views
92 on the model wouldn't be informed about the changes, and structural changes
93 are likely to corrupt instances of QPersistentModelIndex that the model
94 maintains.
95
96 The caller must make sure that the range's lifetime exceeds the lifetime of
97 the model.
98
99 Use smart pointers to make sure that the range is only deleted when all
100 clients are done with it.
101
102 \snippet qrangemodel/main.cpp smart_pointer
103
104 QRangeModel supports both shared and unique pointers.
105
106 \section2 Read-only or mutable
107
108 For ranges that are const objects, for which access always yields constant
109 values, or where the required container APIs are not available,
110 QRangeModel implements write-access APIs to do nothing and return
111 \c{false}. In the example using \c{std::array}, the model cannot add or
112 remove rows, as the number of entries in a C++ array is fixed. But the
113 values can be changed using setData(), and the user can trigger editing of
114 the values in the list view. By making the array const, the values also
115 become read-only.
116
117 \snippet qrangemodel/main.cpp const_array
118
119 The values are also read-only if the element type is const, like in
120
121 \snippet qrangemodel/main.cpp const_values
122
123 In the above examples using \c{std::vector}, the model can add or remove
124 rows, and the data can be changed. Passing the range as a constant
125 reference will make the model read-only.
126
127 \snippet qrangemodel/main.cpp const_ref
128
129 \note If the values in the range are const, then it's also not possible
130 to remove or insert columns and rows through the QAbstractItemModel API.
131 For more granular control, implement \l{the C++ tuple protocol}.
132
133 \section1 Rows and columns
134
135 The elements in the range are interpreted as rows of the model. Depending
136 on the type of these row elements, QRangeModel exposes the range as a
137 list, a table, or a tree.
138
139 If the row elements are simple values, then the range gets represented as a
140 list.
141
142 \snippet qrangemodel/main.cpp list_of_int
143
144 If the type of the row elements is an iterable range, such as a vector,
145 list, or array, then the range gets represented as a table.
146
147 \snippet qrangemodel/main.cpp grid_of_numbers
148
149 If the row type provides the standard C++ container APIs \c{resize()},
150 \c{insert()}, \c{erase()}, then columns can be added and removed via
151 insertColumns() and removeColumns(). All rows are required to have
152 the same number of columns.
153
154 \section2 Structs and gadgets as rows
155
156 If the row type implements \l{the C++ tuple protocol}, then the range gets
157 represented as a table with a fixed number of columns.
158
159 \snippet qrangemodel/main.cpp pair_int_QString
160
161 An easier and more flexible alternative to implementing the tuple protocol
162 for a C++ type is to use Qt's \l{Meta-Object System}{meta-object system} to
163 declare a type with \l{Qt's Property System}{properties}. This can be a
164 value type that is declared as a \l{Q_GADGET}{gadget}, or a QObject subclass.
165
166 \snippet qrangemodel/main.cpp gadget
167
168 Using QObject subclasses allows properties to be \l{Qt Bindable Properties}
169 {bindable}, or to have change notification signals. However, using QObject
170 instances for items has significant memory overhead.
171
172 Using Qt gadgets or objects is more convenient and can be more flexible
173 than implementing the tuple protocol. Those types are also directly
174 accessible from within QML. However, the access through \l{the property system}
175 comes with some runtime overhead. For performance critical models, consider
176 implementing the tuple protocol for compile-time generation of the access
177 code.
178
179 \section2 Multi-role items
180
181 The type of the items that the implementations of data(), setData(),
182 clearItemData() etc. operate on can be the same across the entire model -
183 like in the \c{gridOfNumbers} example above. But the range can also have
184 different item types for different columns, like in the \c{numberNames}
185 case.
186
187 By default, the value gets used for the Qt::DisplayRole and Qt::EditRole
188 roles. Most views expect the value to be
189 \l{QVariant::canConvert}{convertible to and from a QString} (but a custom
190 delegate might provide more flexibility).
191
192 \section3 Associative containers with multiple roles
193
194 If the item is an associative container that uses \c{int},
195 \l{Qt::ItemDataRole}, or QString as the key type, and QVariant as the
196 mapped type, then QRangeModel interprets that container as the storage
197 of the data for multiple roles. The data() and setData() functions return
198 and modify the mapped value in the container, and setItemData() modifies all
199 provided values, itemData() returns all stored values, and clearItemData()
200 clears the entire container.
201
202 \snippet qrangemodel/main.cpp color_map
203
204 The most efficient data type to use as the key is Qt::ItemDataRole or
205 \c{int}. When using \c{int}, itemData() returns the container as is, and
206 doesn't have to create a copy of the data.
207
208 \section3 Gadgets and Objects as multi-role items
209
210 Gadgets and QObject types can also be represented as multi-role items. The
211 \l{The Property System}{properties} of those items will be used for the
212 role for which the \l{roleNames()}{name of a role} matches. If all items
213 hold the same type of gadget or QObject, then the \l{roleNames()}
214 implementation in QRangeModel will return the list of properties of that
215 type.
216
217 \snippet qrangemodel/main.cpp color_gadget_decl
218 \snippet qrangemodel/main.cpp color_gadget_impl
219 \snippet qrangemodel/main.cpp color_gadget_end
220
221 When used in a table, this is the default representation for gadgets:
222
223 \snippet qrangemodel/main.cpp color_gadget_table
224
225 When used in a list, these types are however by default represented as
226 multi-column rows, with each property represented as a separate column. To
227 force a gadget to be represented as a multi-role item in a list, declare
228 the gadget as a multi-role type by specializing QRoleModel::RowOptions,
229 with a \c{static constexpr auto rowCategory} member variable set to
230 MultiRoleItem.
231
232 \snippet qrangemodel/main.cpp color_gadget_decl
233 \dots
234 \snippet qrangemodel/main.cpp color_gadget_end
235 \snippet qrangemodel/main.cpp color_gadget_multi_role_gadget
236
237 You can also wrap such types into a single-element tuple, turning the list
238 into a table with a single column:
239
240 \snippet qrangemodel/main.cpp color_gadget_single_column
241
242 In this case, note that direct access to the elements in the list data
243 needs to use \c{std::get}:
244
245 \snippet qrangemodel/main.cpp color_gadget_single_column_access_get
246
247 or alternatively a structured binding:
248
249 \snippet qrangemodel/main.cpp color_gadget_single_column_access_sb
250
251 \section2 Rows as values or pointers
252
253 In the examples so far, we have always used QRangeModel with ranges that
254 hold values. QRangeModel can also operate on ranges that hold pointers,
255 including smart pointers. This allows QRangeModel to operate on ranges of
256 polymorph types, such as QObject subclasses.
257
258 \snippet qrangemodel/main.cpp object_0
259 \dots
260 \snippet qrangemodel/main.cpp object_1
261
262 \snippet qrangemodel/main.cpp vector_of_objects_0
263 \dots
264 \snippet qrangemodel/main.cpp vector_of_objects_1
265 \snippet qrangemodel/main.cpp vector_of_objects_2
266
267 As with values, the type of the row defines whether the range is
268 represented as a list, table, or tree. Rows that are QObjects will present
269 each property as a column, unless the QRangeModel::RowOptions template is
270 specialized to declare the type as a multi-role item.
271
272 \snippet qrangemodel/main.cpp vector_of_multirole_objects_0
273 \snippet qrangemodel/main.cpp vector_of_multirole_objects_1
274 \dots
275 \snippet qrangemodel/main.cpp vector_of_multirole_objects_2
276
277 \note If the range holds raw pointers, then you have to construct
278 QRangeModel from a pointer or reference wrapper of the range. Otherwise the
279 ownership of the data becomes ambiguous, and a copy of the range would
280 still be operating on the same actual row data, resulting in unexpected
281 side effects.
282
283 \section2 Subclassing QRangeModel
284
285 Subclassing QRangeModel makes it possible to add convenient APIs that take
286 the data type and structure of the range into account.
287
288 \snippet qrangemodel/main.cpp subclass_header
289
290 When doing so, add the range as a private member, and call the QRangeModel
291 constructor with a reference wrapper or pointer to that member. This
292 properly encapsulates the data and avoids direct access.
293
294 \snippet qrangemodel/main.cpp subclass_API
295
296 Add member functions to provide type-safe access to the data, using the
297 QAbstractItemModel API to perform any operation that modifies the range.
298 Read-only access can directly operate on the data structure.
299
300 \section1 Trees of data
301
302 QRangeModel can represent a data structure as a tree model. Such a
303 tree data structure needs to be homomorphic: on all levels of the tree, the
304 list of child rows needs to use the exact same representation as the tree
305 itself. In addition, the row type needs be of a static size: either a gadget
306 or QObject type, or a type that implements the {C++ tuple protocol}.
307
308 To represent such data as a tree, QRangeModel has to be able to traverse the
309 data structure: for any given row, the model needs to be able to retrieve
310 the parent row, and the optional span of children. These traversal functions
311 can be provided implicitly through the row type, or through an explicit
312 protocol type.
313
314 \section2 Implicit tree traversal protocol
315
316 \snippet qrangemodel/main.cpp tree_protocol_0
317
318 The tree itself is a vector of \c{TreeRow} values. See \l{Tree Rows as
319 pointers or values} for the considerations on whether to use values or
320 pointers of items for the rows.
321
322 \snippet qrangemodel/main.cpp tree_protocol_1
323
324 The row class can be of any fixed-size type described above: a type that
325 implements the tuple protocol, a gadget, or a QObject. In this example, we
326 use a gadget.
327
328 Each row item needs to maintain a pointer to the parent row, as well as an
329 optional range of child rows. That range has to be identical to the range
330 structure used for the tree itself.
331
332 Making the row type default constructible is optional, and allows the model
333 to construct new row data elements, for instance in the insertRow() or
334 moveRows() implementations.
335
336 \snippet qrangemodel/main.cpp tree_protocol_2
337
338 The tree traversal protocol can then be implemented as member functions of
339 the row data type. A const \c{parentRow()} function has to return a pointer
340 to a const row item; and the \c{childRows()} function has to return a
341 reference to a const \c{std::optional} that can hold the optional child
342 range.
343
344 These two functions are sufficient for the model to navigate the tree as a
345 read-only data structure. To allow the user to edit data in a view, and the
346 model to implement mutating model APIs such as insertRows(), removeRows(),
347 and moveRows(), we have to implement additional functions for write-access:
348
349 \snippet qrangemodel/main.cpp tree_protocol_3
350
351 The model calls the \c{setParentRow()} function and mutable \c{childRows()}
352 overload to move or insert rows into an existing tree branch, and to update
353 the parent pointer should the old value have become invalid. The non-const
354 overload of \c{childRows()} provides in addition write-access to the row
355 data.
356
357 \note The model performs setting the parent of a row, removing that row
358 from the old parent, and adding it to the list of the new parent's children,
359 as separate steps. This keeps the protocol interface small.
360
361 \dots
362 \snippet qrangemodel/main.cpp tree_protocol_4
363
364 The rest of the class implementation is not relevant for the model, but
365 a \c{addChild()} helper provides us with a convenient way to construct the
366 initial state of the tree.
367
368 \snippet qrangemodel/main.cpp tree_protocol_5
369
370 A QRangeModel instantiated with an instance of such a range will
371 represent the data as a tree.
372
373 \snippet qrangemodel/main.cpp tree_protocol_6
374
375 \section2 Tree traversal protocol in a separate class
376
377 The tree traversal protocol can also be implemented in a separate class.
378
379 \snippet qrangemodel/main.cpp explicit_tree_protocol_0
380
381 Pass an instance of this protocol implementation to the QRangeModel
382 constructor:
383
384 \snippet qrangemodel/main.cpp explicit_tree_protocol_1
385
386 \section2 Tree Rows as pointers or values
387
388 The row type of the data range can be either a value, or a pointer. In
389 the code above we have been using the tree rows as values in a vector,
390 which avoids that we have to deal with explicit memory management. However,
391 a vector as a contiguous block of memory invalidates all iterators and
392 references when it has to reallocate the storage, or when inserting or
393 removing elements. This impacts the pointer to the parent item, which is
394 the location of the parent row within the vector. Making sure that this
395 parent (and QPersistentModelIndex instances referring to items within it)
396 stays valid can incurr substantial performance overhead. The
397 QRangeModel implementation has to assume that all references into the
398 range become invalid when modifying the range.
399
400 Alternatively, we can also use a range of row pointers as the tree type:
401
402 \snippet qrangemodel/main.cpp tree_of_pointers_0
403
404 In this case, we have to allocate all TreeRow instances explicitly using
405 operator \c{new}, and implement the destructor to \c{delete} all items in
406 the vector of children.
407
408 \snippet qrangemodel/main.cpp tree_of_pointers_1
409 \snippet qrangemodel/main.cpp tree_of_pointers_2
410
411 Before we can construct a model that represents this data as a tree, we need
412 to also implement the tree traversal protocol.
413
414 \snippet qrangemodel/main.cpp tree_of_pointers_3
415
416 An explicit protocol implementation for mutable trees of pointers has to
417 provide two additional member functions, \c{newRow()} and
418 \c{deleteRow(RowType *)}.
419
420 \snippet qrangemodel/main.cpp tree_of_pointers_4
421
422 The model will call those functions when creating new rows in insertRows(),
423 and when removing rows in removeRows(). In addition, if the model has
424 ownership of the data, then it will also delete all top-level rows upon
425 destruction. Note how in this example, we move the tree into the model, so
426 we must no longer perform any operations on it. QRangeModel, when
427 constructed by moving tree-data with row-pointers into it, will take
428 ownership of the data, and delete the row pointers in it's destructor.
429
430 Using pointers as rows comes with some memory allocation and management
431 overhead. However, the references to the row items remain stable, even when
432 they are moved around in the range, or when the range reallocates. This can
433 significantly reduce the cost of making modifications to the model's
434 structure when using insertRows(), removeRows(), or moveRows().
435
436 Each choice has different performance and memory overhead trade-offs. The
437 best option depends on the exact use case and data structure used.
438
439 \section2 The C++ tuple protocol
440
441 As seen in the \c{numberNames} example above, the row type can be a tuple,
442 and in fact any type that implements the tuple protocol. This protocol is
443 implemented by specializing \c{std::tuple_size} and \c{std::tuple_element},
444 and overloading the unqualified \c{get} function. Do so for your custom row
445 type to make existing structured data available to the model/view framework
446 in Qt.
447
448 \snippet qrangemodel/main.cpp tuple_protocol
449
450 In the above implementation, the \c{title} and \c{author} values of the
451 \c{Book} type are returned as \c{const}, so the model flags items in those
452 two columns as read-only. The user won't be able to trigger editing, and
453 setData() does nothing and returns false. For \c{summary} and \c{rating}
454 the implementation returns the same value category as the book, so when
455 \c{get} is called with a mutable reference to a \c{Book}, then it will
456 return a mutable reference of the respective variable. The model makes
457 those columns editable, both for the user and for programmatic access.
458
459 \note The implementation of \c{get} above requires C++23.
460
461 \sa {Model/View Programming}
462*/
463
464/*!
465 \class QRangeModel::RowOptions
466 \inmodule QtCore
467 \ingroup model-view
468 \brief The RowOptions template provides a customization point to control
469 how QRangeModel represents types used as rows.
470 \since 6.10
471
472 Specialize this template for the type used in your range, and add the
473 relevant members.
474
475 \table
476 \header
477 \li Member
478 \li Values
479 \row
480 \li static constexpr RowCategory rowCategory
481 \li RowCategory
482 \endtable
483
484 \snippet qrangemodel/main.cpp color_gadget_decl
485 \dots
486 \snippet qrangemodel/main.cpp color_gadget_end
487 \snippet qrangemodel/main.cpp color_gadget_multi_role_gadget
488
489*/
490
491/*!
492 \enum QRangeModel::RowCategory
493
494 This enum describes how QRangeModel should present the elements of the
495 range it was constructed with.
496
497 \value Default
498 QRangeModel decides how to present the rows.
499 \value MultiRoleItem
500 QRangeModel will present items with a meta object as multi-role
501 items, also when used in a one-dimensional range.
502
503 Specialize the RowOptions template for your type, and add a public member
504 variable \c{static constexpr auto rowCategory} with one of the values from
505 this enum.
506
507 \sa RowOptions
508*/
509
510/*!
511 \fn template <typename Range, QRangeModelDetails::if_table_range<Range>> QRangeModel::QRangeModel(Range &&range, QObject *parent)
512 \fn template <typename Range, QRangeModelDetails::if_tree_range<Range>> QRangeModel::QRangeModel(Range &&range, QObject *parent)
513 \fn template <typename Range, typename Protocol, QRangeModelDetails::if_tree_range<Range, Protocol>> QRangeModel::QRangeModel(Range &&range, Protocol &&protocol, QObject *parent)
514
515 Constructs a QRangeModel instance that operates on the data in \a range.
516 The \a range has to be a sequential range for which \c{std::begin} and
517 \c{std::end} are available. If \a protocol is provided, then the model
518 will represent the range as a tree using the protocol implementation. The
519 model instance becomes a child of \a parent.
520
521 The \a range can be a pointer or reference wrapper, in which case mutating
522 model APIs (such as \l{setData()} or \l{insertRow()}) will modify the data
523 in the referenced range instance. If \a range is a value (or moved into the
524 model), then connect to the signals emitted by the model to respond to
525 changes to the data.
526
527 QRangeModel will not access the \a range while being constructed. This
528 makes it legal to pass a pointer or reference to a range object that is not
529 fully constructed yet to this constructor, for example when \l{Subclassing
530 QRangeModel}{subclassing QRangeModel}.
531
532 If the \a range was moved into the model, then the range and all data in it
533 will be destroyed upon destruction of the model.
534
535 \note While the model does not take ownership of the range object otherwise,
536 you must not modify the \a range directly once the model has been constructed
537 and and passed on to a view. Such modifications will not emit signals
538 necessary to keep model users (other models or views) synchronized with the
539 model, resulting in inconsistent results, undefined behavior, and crashes.
540*/
541
542/*!
543 Destroys the QRangeModel.
544
545 The range that the model was constructed from is not accessed, and only
546 destroyed if the model was constructed from a moved-in range.
547*/
548QRangeModel::~QRangeModel() = default;
549
550/*!
551 \reimp
552
553 Returns the index of the model item at \a row and \a column in \a parent.
554
555 Passing a valid parent produces an invalid index for models that operate on
556 list and table ranges.
557
558 \sa parent()
559*/
560QModelIndex QRangeModel::index(int row, int column, const QModelIndex &parent) const
561{
562 Q_D(const QRangeModel);
563 return d->impl->call<QRangeModelImplBase::Index>(args&: row, args&: column, args: parent);
564}
565
566/*!
567 \reimp
568
569 Returns the parent of the item at the \a child index.
570
571 This function always produces an invalid index for models that operate on
572 list and table ranges. For models operation on a tree, this function
573 returns the index for the row item returned by the parent() implementation
574 of the tree traversal protocol.
575
576 \sa index(), hasChildren()
577*/
578QModelIndex QRangeModel::parent(const QModelIndex &child) const
579{
580 Q_D(const QRangeModel);
581 return d->impl->call<QRangeModelImplBase::Parent>(args: child);
582}
583
584/*!
585 \reimp
586
587 Returns the sibling at \a row and \a column for the item at \a index, or an
588 invalid QModelIndex if there is no sibling at that location.
589
590 This implementation is significantly faster than going through the parent()
591 of the \a index.
592
593 \sa index(), QModelIndex::row(), QModelIndex::column()
594*/
595QModelIndex QRangeModel::sibling(int row, int column, const QModelIndex &index) const
596{
597 Q_D(const QRangeModel);
598 return d->impl->call<QRangeModelImplBase::Sibling>(args&: row, args&: column, args: index);
599}
600
601/*!
602 \reimp
603
604 Returns the number of rows under the given \a parent. This is the number of
605 items in the root range for an invalid \a parent index.
606
607 If the \a parent index is valid, then this function always returns 0 for
608 models that operate on list and table ranges. For trees, this returns the
609 size of the range returned by the childRows() implementation of the tree
610 traversal protocol.
611
612 \sa columnCount(), insertRows(), hasChildren()
613*/
614int QRangeModel::rowCount(const QModelIndex &parent) const
615{
616 Q_D(const QRangeModel);
617 return d->impl->call<QRangeModelImplBase::RowCount>(args: parent);
618}
619
620/*!
621 \reimp
622
623 Returns the number of columns of the model. This function returns the same
624 value for all \a parent indexes.
625
626 For models operating on a statically sized row type, this returned value is
627 always the same throughout the lifetime of the model. For models operating
628 on dynamically sized row type, the model returns the number of items in the
629 first row, or 0 if the model has no rows.
630
631 \sa rowCount, insertColumns()
632*/
633int QRangeModel::columnCount(const QModelIndex &parent) const
634{
635 Q_D(const QRangeModel);
636 return d->impl->call<QRangeModelImplBase::ColumnCount>(args: parent);
637}
638
639/*!
640 \reimp
641
642 Returns the item flags for the given \a index.
643
644 The implementation returns a combination of flags that enables the item
645 (\c ItemIsEnabled) and allows it to be selected (\c ItemIsSelectable). For
646 models operating on a range with mutable data, it also sets the flag
647 that allows the item to be editable (\c ItemIsEditable).
648
649 \sa Qt::ItemFlags
650*/
651Qt::ItemFlags QRangeModel::flags(const QModelIndex &index) const
652{
653 Q_D(const QRangeModel);
654 return d->impl->call<QRangeModelImplBase::Flags>(args: index);
655}
656
657/*!
658 \reimp
659
660 Returns the data for the given \a role and \a section in the header with
661 the specified \a orientation.
662
663 For horizontal headers, the section number corresponds to the column
664 number. Similarly, for vertical headers, the section number corresponds to
665 the row number.
666
667 For the horizontal header and the Qt::DisplayRole \a role, models that
668 operate on a range that uses an array as the row type return \a section. If
669 the row type is a tuple, then the implementation returns the name of the
670 type at \a section. For rows that are a gadget or QObject type, this
671 function returns the name of the property at the index of \a section.
672
673 For the vertical header, this function always returns the result of the
674 default implementation in QAbstractItemModel.
675
676 \sa Qt::ItemDataRole, setHeaderData(), QHeaderView
677*/
678QVariant QRangeModel::headerData(int section, Qt::Orientation orientation, int role) const
679{
680 Q_D(const QRangeModel);
681 return d->impl->call<QRangeModelImplBase::HeaderData>(args&: section, args&: orientation, args&: role);
682}
683
684/*!
685 \reimp
686*/
687bool QRangeModel::setHeaderData(int section, Qt::Orientation orientation, const QVariant &data,
688 int role)
689{
690 return QAbstractItemModel::setHeaderData(section, orientation, value: data, role);
691}
692
693/*!
694 \reimp
695
696 Returns the data stored under the given \a role for the value in the
697 range referred to by the \a index.
698
699 If the item type for that index is an associative container that maps from
700 either \c{int}, Qt::ItemDataRole, or QString to a QVariant, then the role
701 data is looked up in that container and returned.
702
703 If the item is a gadget or QObject, then the implementation returns the
704 value of the item's property matching the \a role entry in the roleNames()
705 mapping.
706
707 Otherwise, the implementation returns a QVariant constructed from the item
708 via \c{QVariant::fromValue()} for \c{Qt::DisplayRole} or \c{Qt::EditRole}.
709 For other roles, the implementation returns an \b invalid
710 (default-constructed) QVariant.
711
712 \sa Qt::ItemDataRole, setData(), headerData()
713*/
714QVariant QRangeModel::data(const QModelIndex &index, int role) const
715{
716 Q_D(const QRangeModel);
717 return d->impl->call<QRangeModelImplBase::Data>(args: index, args&: role);
718}
719
720/*!
721 \reimp
722
723 Sets the \a role data for the item at \a index to \a data.
724
725 If the item type for that \a index is an associative container that maps
726 from either \c{int}, Qt::ItemDataRole, or QString to a QVariant, then
727 \a data is stored in that container for the key specified by \a role.
728
729 If the item is a gadget or QObject, then \a data is written to the item's
730 property matching the \a role entry in the the roleNames() mapping. The
731 function returns \c{true} if a property was found and if \a data stored a
732 value that could be converted to the required type, otherwise returns
733 \c{false}.
734
735 Otherwise, this implementation assigns the value in \a data to the item at
736 the \a index in the range for \c{Qt::DisplayRole} and \c{Qt::EditRole},
737 and returns \c{true}. For other roles, the implementation returns
738 \c{false}.
739
740//! [read-only-setData]
741 For models operating on a read-only range, or on a read-only column in
742 a row type that implements \l{the C++ tuple protocol}, this implementation
743 returns \c{false} immediately.
744//! [read-only-setData]
745*/
746bool QRangeModel::setData(const QModelIndex &index, const QVariant &data, int role)
747{
748 Q_D(QRangeModel);
749 return d->impl->call<QRangeModelImplBase::SetData>(args: index, args: data, args&: role);
750}
751
752/*!
753 \reimp
754
755 Returns a map with values for all predefined roles in the model for the
756 item at the given \a index.
757
758 If the item type for that \a index is an associative container that maps
759 from either \c{int}, Qt::ItemDataRole, or QString to a QVariant, then the
760 data from that container is returned.
761
762 If the item type is a gadget or QObject subclass, then the values of those
763 properties that match a \l{roleNames()}{role name} are returned.
764
765 If the item is not an associative container, gadget, or QObject subclass,
766 then this calls the base class implementation.
767
768 \sa setItemData(), Qt::ItemDataRole, data()
769*/
770QMap<int, QVariant> QRangeModel::itemData(const QModelIndex &index) const
771{
772 Q_D(const QRangeModel);
773 return d->impl->call<QRangeModelImplBase::ItemData>(args: index);
774}
775
776/*!
777 \reimp
778
779 If the item type for that \a index is an associative container that maps
780 from either \c{int} or Qt::ItemDataRole to a QVariant, then the entries in
781 \a data are stored in that container. If the associative container maps from
782 QString to QVariant, then only those values in \a data are stored for which
783 there is a mapping in the \l{roleNames()}{role names} table.
784
785 If the item type is a gadget or QObject subclass, then those properties that
786 match a \l{roleNames()}{role name} are set to the corresponding value in
787 \a data.
788
789 Roles for which there is no entry in \a data are not modified.
790
791 For item types that can be copied, this implementation is transactional,
792 and returns true if all the entries from \a data could be stored. If any
793 entry could not be updated, then the original container is not modified at
794 all, and the function returns false.
795
796 If the item is not an associative container, gadget, or QObject subclass,
797 then this calls the base class implementation, which calls setData() for
798 each entry in \a data.
799
800 \sa itemData(), setData(), Qt::ItemDataRole
801*/
802bool QRangeModel::setItemData(const QModelIndex &index, const QMap<int, QVariant> &data)
803{
804 Q_D(QRangeModel);
805 return d->impl->call<QRangeModelImplBase::SetItemData>(args: index, args: data);
806}
807
808/*!
809 \reimp
810
811 Replaces the value stored in the range at \a index with a default-
812 constructed value.
813
814 \include qrangemodel.cpp read-only-setData
815*/
816bool QRangeModel::clearItemData(const QModelIndex &index)
817{
818 Q_D(QRangeModel);
819 return d->impl->call<QRangeModelImplBase::ClearItemData>(args: index);
820}
821
822/*
823//! [column-change-requirement]
824 \note A dynamically sized row type needs to provide a \c{\1} member function.
825
826 For models operating on a read-only range, or on a range with a
827 statically sized row type (such as a tuple, array, or struct), this
828 implementation does nothing and returns \c{false} immediately. This is
829 always the case for tree models.
830//! [column-change-requirement]
831*/
832
833/*!
834 \reimp
835
836 Inserts \a count empty columns before the item at \a column in all rows
837 of the range at \a parent. Returns \c{true} if successful; otherwise
838 returns \c{false}.
839
840 \include qrangemodel.cpp {column-change-requirement} {insert(const_iterator, size_t, value_type)}
841*/
842bool QRangeModel::insertColumns(int column, int count, const QModelIndex &parent)
843{
844 Q_D(QRangeModel);
845 return d->impl->call<QRangeModelImplBase::InsertColumns>(args&: column, args&: count, args: parent);
846}
847
848/*!
849 \reimp
850
851 Removes \a count columns from the item at \a column on in all rows of the
852 range at \a parent. Returns \c{true} if successful, otherwise returns
853 \c{false}.
854
855 \include qrangemodel.cpp {column-change-requirement} {erase(const_iterator, size_t)}
856*/
857bool QRangeModel::removeColumns(int column, int count, const QModelIndex &parent)
858{
859 Q_D(QRangeModel);
860 return d->impl->call<QRangeModelImplBase::RemoveColumns>(args&: column, args&: count, args: parent);
861}
862
863/*!
864 \reimp
865
866 Moves \a count columns starting with the given \a sourceColumn under parent
867 \a sourceParent to column \a destinationColumn under parent \a destinationParent.
868
869 Returns \c{true} if the columns were successfully moved; otherwise returns
870 \c{false}.
871*/
872bool QRangeModel::moveColumns(const QModelIndex &sourceParent, int sourceColumn, int count,
873 const QModelIndex &destinationParent, int destinationColumn)
874{
875 Q_D(QRangeModel);
876 return d->impl->call<QRangeModelImplBase::MoveColumns>(
877 args: sourceParent, args&: sourceColumn, args&: count,
878 args: destinationParent, args&: destinationColumn);
879}
880
881/*
882//! [row-change-requirement]
883 \note The range needs to be dynamically sized and provide a \c{\1}
884 member function.
885
886 For models operating on a read-only or statically-sized range (such as
887 an array), this implementation does nothing and returns \c{false}
888 immediately.
889//! [row-change-requirement]
890*/
891
892/*!
893 \reimp
894
895 Inserts \a count empty rows before the given \a row into the range at
896 \a parent. Returns \c{true} if successful; otherwise returns \c{false}.
897
898 \include qrangemodel.cpp {row-change-requirement} {insert(const_iterator, size_t, value_type)}
899
900 \note For ranges with a dynamically sized column type, the column needs
901 to provide a \c{resize(size_t)} member function.
902*/
903bool QRangeModel::insertRows(int row, int count, const QModelIndex &parent)
904{
905 Q_D(QRangeModel);
906 return d->impl->call<QRangeModelImplBase::InsertRows>(args&: row, args&: count, args: parent);
907}
908
909/*!
910 \reimp
911
912 Removes \a count rows from the range at \a parent, starting with the
913 given \a row. Returns \c{true} if successful, otherwise returns \c{false}.
914
915 \include qrangemodel.cpp {row-change-requirement} {erase(const_iterator, size_t)}
916*/
917bool QRangeModel::removeRows(int row, int count, const QModelIndex &parent)
918{
919 Q_D(QRangeModel);
920 return d->impl->call<QRangeModelImplBase::RemoveRows>(args&: row, args&: count, args: parent);
921}
922
923/*!
924 \reimp
925
926 Moves \a count rows starting with the given \a sourceRow under parent
927 \a sourceParent to row \a destinationRow under parent \a destinationParent.
928
929 Returns \c{true} if the rows were successfully moved; otherwise returns
930 \c{false}.
931*/
932bool QRangeModel::moveRows(const QModelIndex &sourceParent, int sourceRow, int count,
933 const QModelIndex &destinationParent, int destinationRow)
934{
935 Q_D(QRangeModel);
936 return d->impl->call<QRangeModelImplBase::MoveRows>(
937 args: sourceParent, args&: sourceRow, args&: count,
938 args: destinationParent, args&: destinationRow);
939}
940
941/*!
942 \reimp
943*/
944bool QRangeModel::canFetchMore(const QModelIndex &parent) const
945{
946 return QAbstractItemModel::canFetchMore(parent);
947}
948
949/*!
950 \reimp
951*/
952void QRangeModel::fetchMore(const QModelIndex &parent)
953{
954 QAbstractItemModel::fetchMore(parent);
955}
956
957/*!
958 \reimp
959*/
960bool QRangeModel::hasChildren(const QModelIndex &parent) const
961{
962 return QAbstractItemModel::hasChildren(parent);
963}
964
965/*!
966 \reimp
967*/
968QModelIndex QRangeModel::buddy(const QModelIndex &index) const
969{
970 return QAbstractItemModel::buddy(index);
971}
972
973/*!
974 \reimp
975*/
976bool QRangeModel::canDropMimeData(const QMimeData *data, Qt::DropAction action,
977 int row, int column, const QModelIndex &parent) const
978{
979 return QAbstractItemModel::canDropMimeData(data, action, row, column, parent);
980}
981
982/*!
983 \reimp
984*/
985bool QRangeModel::dropMimeData(const QMimeData *data, Qt::DropAction action,
986 int row, int column, const QModelIndex &parent)
987{
988 return QAbstractItemModel::dropMimeData(data, action, row, column, parent);
989}
990
991/*!
992 \reimp
993*/
994QMimeData *QRangeModel::mimeData(const QModelIndexList &indexes) const
995{
996 return QAbstractItemModel::mimeData(indexes);
997}
998
999/*!
1000 \reimp
1001*/
1002QStringList QRangeModel::mimeTypes() const
1003{
1004 return QAbstractItemModel::mimeTypes();
1005}
1006
1007/*!
1008 \reimp
1009*/
1010QModelIndexList QRangeModel::match(const QModelIndex &start, int role, const QVariant &value,
1011 int hits, Qt::MatchFlags flags) const
1012{
1013 return QAbstractItemModel::match(start, role, value, hits, flags);
1014}
1015
1016/*!
1017 \reimp
1018*/
1019void QRangeModel::multiData(const QModelIndex &index, QModelRoleDataSpan roleDataSpan) const
1020{
1021 QAbstractItemModel::multiData(index, roleDataSpan);
1022}
1023
1024
1025/*!
1026 \property QRangeModel::roleNames
1027 \brief the role names for the model.
1028
1029 If all columns in the range are of the same type, and if that type provides
1030 a meta object (i.e., it is a gadget, or a QObject subclass), then this
1031 property holds the names of the properties of that type, mapped to values of
1032 Qt::ItemDataRole values from Qt::UserRole and up. In addition, a role
1033 "modelData" provides access to the gadget or QObject instance.
1034
1035 Override this default behavior by setting this property explicitly to a non-
1036 empty mapping. Setting this property to an empty mapping, or using
1037 resetRoleNames(), restores the default behavior.
1038
1039 \sa QAbstractItemModel::roleNames()
1040*/
1041
1042QHash<int, QByteArray> QRangeModelImplBase::roleNamesForMetaObject(const QAbstractItemModel &model,
1043 const QMetaObject &metaObject)
1044{
1045 const auto defaults = model.QAbstractItemModel::roleNames();
1046 QHash<int, QByteArray> result = {{Qt::RangeModelDataRole, "modelData"}};
1047 int offset = metaObject.propertyOffset();
1048 for (int i = offset; i < metaObject.propertyCount(); ++i) {
1049 const auto name = metaObject.property(index: i).name();
1050 const int defaultRole = defaults.key(value: name, defaultKey: -1);
1051 if (defaultRole != -1) {
1052 ++offset;
1053 result[defaultRole] = name;
1054 } else {
1055 result[Qt::UserRole + i - offset] = name;
1056 }
1057 }
1058 return result;
1059}
1060
1061QHash<int, QByteArray> QRangeModelImplBase::roleNamesForSimpleType()
1062{
1063 // just a plain value
1064 return QHash<int, QByteArray>{
1065 {Qt::DisplayRole, "display"},
1066 {Qt::EditRole, "edit"},
1067 {Qt::RangeModelDataRole, "modelData"},
1068 };
1069}
1070
1071/*!
1072 \reimp
1073
1074 \note Overriding this function in a QRangeModel subclass is possible,
1075 but might break the behavior of the property.
1076*/
1077QHash<int, QByteArray> QRangeModel::roleNames() const
1078{
1079 Q_D(const QRangeModel);
1080 if (d->m_roleNames.isEmpty())
1081 d->m_roleNames = d->impl->call<QRangeModelImplBase::RoleNames>();
1082
1083 return d->m_roleNames;
1084}
1085
1086void QRangeModel::setRoleNames(const QHash<int, QByteArray> &names)
1087{
1088 Q_D(QRangeModel);
1089 if (d->m_roleNames == names)
1090 return;
1091 beginResetModel();
1092 d->impl->call<QRangeModelImplBase::InvalidateCaches>();
1093 d->m_roleNames = names;
1094 endResetModel();
1095 Q_EMIT roleNamesChanged();
1096}
1097
1098void QRangeModel::resetRoleNames()
1099{
1100 setRoleNames({});
1101}
1102
1103/*!
1104 \reimp
1105*/
1106void QRangeModel::sort(int column, Qt::SortOrder order)
1107{
1108 return QAbstractItemModel::sort(column, order);
1109}
1110
1111/*!
1112 \reimp
1113*/
1114QSize QRangeModel::span(const QModelIndex &index) const
1115{
1116 return QAbstractItemModel::span(index);
1117}
1118
1119/*!
1120 \reimp
1121*/
1122Qt::DropActions QRangeModel::supportedDragActions() const
1123{
1124 return QAbstractItemModel::supportedDragActions();
1125}
1126
1127/*!
1128 \reimp
1129*/
1130Qt::DropActions QRangeModel::supportedDropActions() const
1131{
1132 return QAbstractItemModel::supportedDropActions();
1133}
1134
1135/*!
1136 \reimp
1137*/
1138void QRangeModel::resetInternalData()
1139{
1140 QAbstractItemModel::resetInternalData();
1141}
1142
1143/*!
1144 \reimp
1145*/
1146bool QRangeModel::event(QEvent *event)
1147{
1148 return QAbstractItemModel::event(event);
1149}
1150
1151/*!
1152 \reimp
1153*/
1154bool QRangeModel::eventFilter(QObject *object, QEvent *event)
1155{
1156 return QAbstractItemModel::eventFilter(watched: object, event);
1157}
1158
1159QT_END_NAMESPACE
1160
1161#include "moc_qrangemodel.cpp"
1162

source code of qtbase/src/corelib/itemmodels/qrangemodel.cpp