Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qrangemodel.cpp
Go to the documentation of this file.
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
11
13{
14 Q_DECLARE_PUBLIC(QRangeModel)
15
16public:
20
21private:
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 row item; and the \c{childRows()} function has to return a reference
341 to a const \c{std::optional} that can hold the optional child range.
342
343 These two functions are sufficient for the model to navigate the tree as a
344 read-only data structure. To allow the user to edit data in a view, and the
345 model to implement mutating model APIs such as insertRows(), removeRows(),
346 and moveRows(), we have to implement additional functions for write-access:
347
348 \snippet qrangemodel/main.cpp tree_protocol_3
349
350 The model calls the \c{setParentRow()} function and mutable \c{childRows()}
351 overload to move or insert rows into an existing tree branch, and to update
352 the parent pointer should the old value have become invalid. The non-const
353 overload of \c{childRows()} provides in addition write-access to the row
354 data.
355
356 \note The model performs setting the parent of a row, removing that row
357 from the old parent, and adding it to the list of the new parent's children,
358 as separate steps. This keeps the protocol interface small.
359
360 \dots
361 \snippet qrangemodel/main.cpp tree_protocol_4
362
363 The rest of the class implementation is not relevant for the model, but
364 a \c{addChild()} helper provides us with a convenient way to construct the
365 initial state of the tree.
366
367 \snippet qrangemodel/main.cpp tree_protocol_5
368
369 A QRangeModel instantiated with an instance of such a range will
370 represent the data as a tree.
371
372 \snippet qrangemodel/main.cpp tree_protocol_6
373
374 \section2 Tree traversal protocol in a separate class
375
376 The tree traversal protocol can also be implemented in a separate class.
377
378 \snippet qrangemodel/main.cpp explicit_tree_protocol_0
379
380 Pass an instance of this protocol implementation to the QRangeModel
381 constructor:
382
383 \snippet qrangemodel/main.cpp explicit_tree_protocol_1
384
385 \section2 Tree Rows as pointers or values
386
387 The row type of the data range can be either a value, or a pointer. In
388 the code above we have been using the tree rows as values in a vector,
389 which avoids that we have to deal with explicit memory management. However,
390 a vector as a contiguous block of memory invalidates all iterators and
391 references when it has to reallocate the storage, or when inserting or
392 removing elements. This impacts the pointer to the parent item, which is
393 the location of the parent row within the vector. Making sure that this
394 parent (and QPersistentModelIndex instances referring to items within it)
395 stays valid can incurr substantial performance overhead. The
396 QRangeModel implementation has to assume that all references into the
397 range become invalid when modifying the range.
398
399 Alternatively, we can also use a range of row pointers as the tree type:
400
401 \snippet qrangemodel/main.cpp tree_of_pointers_0
402
403 In this case, we have to allocate all TreeRow instances explicitly using
404 operator \c{new}, and implement the destructor to \c{delete} all items in
405 the vector of children.
406
407 \snippet qrangemodel/main.cpp tree_of_pointers_1
408 \snippet qrangemodel/main.cpp tree_of_pointers_2
409
410 Before we can construct a model that represents this data as a tree, we need
411 to also implement the tree traversal protocol.
412
413 \snippet qrangemodel/main.cpp tree_of_pointers_3
414
415 An explicit protocol implementation for mutable trees of pointers has to
416 provide two additional member functions, \c{newRow()} and
417 \c{deleteRow(RowType *)}.
418
419 \snippet qrangemodel/main.cpp tree_of_pointers_4
420
421 The model will call those functions when creating new rows in insertRows(),
422 and when removing rows in removeRows(). In addition, if the model has
423 ownership of the data, then it will also delete all top-level rows upon
424 destruction. Note how in this example, we move the tree into the model, so
425 we must no longer perform any operations on it. QRangeModel, when
426 constructed by moving tree-data with row-pointers into it, will take
427 ownership of the data, and delete the row pointers in it's destructor.
428
429 Using pointers as rows comes with some memory allocation and management
430 overhead. However, the references to the row items remain stable, even when
431 they are moved around in the range, or when the range reallocates. This can
432 significantly reduce the cost of making modifications to the model's
433 structure when using insertRows(), removeRows(), or moveRows().
434
435 Each choice has different performance and memory overhead trade-offs. The
436 best option depends on the exact use case and data structure used.
437
438 \section2 The C++ tuple protocol
439
440 As seen in the \c{numberNames} example above, the row type can be a tuple,
441 and in fact any type that implements the tuple protocol. This protocol is
442 implemented by specializing \c{std::tuple_size} and \c{std::tuple_element},
443 and overloading the unqualified \c{get} function. Do so for your custom row
444 type to make existing structured data available to the model/view framework
445 in Qt.
446
447 \snippet qrangemodel/main.cpp tuple_protocol
448
449 In the above implementation, the \c{title} and \c{author} values of the
450 \c{Book} type are returned as \c{const}, so the model flags items in those
451 two columns as read-only. The user won't be able to trigger editing, and
452 setData() does nothing and returns false. For \c{summary} and \c{rating}
453 the implementation returns the same value category as the book, so when
454 \c{get} is called with a mutable reference to a \c{Book}, then it will
455 return a mutable reference of the respective variable. The model makes
456 those columns editable, both for the user and for programmatic access.
457
458 \note The implementation of \c{get} above requires C++23.
459
460 \sa {Model/View Programming}
461*/
462
463/*!
464 \class QRangeModel::RowOptions
465 \inmodule QtCore
466 \ingroup model-view
467 \brief The RowOptions template provides a customization point to control
468 how QRangeModel represents types used as rows.
469 \since 6.10
470
471 Specialize this template for the type used in your range, and add the
472 relevant members.
473
474 \table
475 \header
476 \li Member
477 \li Values
478 \row
479 \li static constexpr RowCategory rowCategory
480 \li RowCategory
481 \endtable
482
483 \snippet qrangemodel/main.cpp color_gadget_decl
484 \dots
485 \snippet qrangemodel/main.cpp color_gadget_end
486 \snippet qrangemodel/main.cpp color_gadget_multi_role_gadget
487
488*/
489
490/*!
491 \enum QRangeModel::RowCategory
492
493 This enum describes how QRangeModel should present the elements of the
494 range it was constructed with.
495
496 \value Default
497 QRangeModel decides how to present the rows.
498 \value MultiRoleItem
499 QRangeModel will present items with a meta object as multi-role
500 items, also when used in a one-dimensional range.
501
502 Specialize the RowOptions template for your type, and add a public member
503 variable \c{static constexpr auto rowCategory} with one of the values from
504 this enum.
505
506 \sa RowOptions
507*/
508
509/*!
510 \class QRangeModel::ItemAccess
511 \inmodule QtCore
512 \ingroup model-view
513 \brief The ItemAccess template provides a customization point to control
514 how QRangeModel accesses role data of individual items.
515 \since 6.11
516
517 Specialize this template for the type used in your data structure, and
518 implement \c{readRole()} and \c{writeRole()} members to access the role-
519 specific data of your type.
520
521 \code
522 template <>
523 struct QRangeModel::ItemAccess<ItemType>
524 {
525 static QVariant readRole(const ItemType &item, int role)
526 {
527 switch (role) {
528 // ...
529 }
530 return {};
531 }
532
533 static bool writeRole(ItemType &item, const QVariant &data, int role)
534 {
535 bool ok = false;
536 switch (role) {
537 // ...
538 }
539
540 return ok;
541 }
542 };
543 \endcode
544
545 A specialization of this type will take precedence over any predefined
546 behavior. Do not specialize this template for types you do not own.
547*/
548
549/*!
550 \fn template <typename Range, QRangeModelDetails::if_table_range<Range>> QRangeModel::QRangeModel(Range &&range, QObject *parent)
551 \fn template <typename Range, QRangeModelDetails::if_tree_range<Range>> QRangeModel::QRangeModel(Range &&range, QObject *parent)
552 \fn template <typename Range, typename Protocol, QRangeModelDetails::if_tree_range<Range, Protocol>> QRangeModel::QRangeModel(Range &&range, Protocol &&protocol, QObject *parent)
553
554 Constructs a QRangeModel instance that operates on the data in \a range.
555 The \a range has to be a sequential range for which \c{std::begin} and
556 \c{std::end} are available. If \a protocol is provided, then the model
557 will represent the range as a tree using the protocol implementation. The
558 model instance becomes a child of \a parent.
559
560 The \a range can be a pointer or reference wrapper, in which case mutating
561 model APIs (such as \l{setData()} or \l{insertRow()}) will modify the data
562 in the referenced range instance. If \a range is a value (or moved into the
563 model), then connect to the signals emitted by the model to respond to
564 changes to the data.
565
566 QRangeModel will not access the \a range while being constructed. This
567 makes it legal to pass a pointer or reference to a range object that is not
568 fully constructed yet to this constructor, for example when \l{Subclassing
569 QRangeModel}{subclassing QRangeModel}.
570
571 If the \a range was moved into the model, then the range and all data in it
572 will be destroyed upon destruction of the model.
573
574 \note While the model does not take ownership of the range object otherwise,
575 you must not modify the \a range directly once the model has been constructed
576 and and passed on to a view. Such modifications will not emit signals
577 necessary to keep model users (other models or views) synchronized with the
578 model, resulting in inconsistent results, undefined behavior, and crashes.
579*/
580
581/*!
582 Destroys the QRangeModel.
583
584 The range that the model was constructed from is not accessed, and only
585 destroyed if the model was constructed from a moved-in range.
586*/
587QRangeModel::~QRangeModel() = default;
588
589/*!
590 \reimp
591
592 Returns the index of the model item at \a row and \a column in \a parent.
593
594 Passing a valid parent produces an invalid index for models that operate on
595 list and table ranges.
596
597 \sa parent()
598*/
599QModelIndex QRangeModel::index(int row, int column, const QModelIndex &parent) const
600{
601 Q_D(const QRangeModel);
602 return d->impl->call<QRangeModelImplBase::Index>(row, column, parent);
603}
604
605/*!
606 \reimp
607
608 Returns the parent of the item at the \a child index.
609
610 This function always produces an invalid index for models that operate on
611 list and table ranges. For models operation on a tree, this function
612 returns the index for the row item returned by the parent() implementation
613 of the tree traversal protocol.
614
615 \sa index(), hasChildren()
616*/
617QModelIndex QRangeModel::parent(const QModelIndex &child) const
618{
619 Q_D(const QRangeModel);
620 return d->impl->call<QRangeModelImplBase::Parent>(child);
621}
622
623/*!
624 \reimp
625
626 Returns the sibling at \a row and \a column for the item at \a index, or an
627 invalid QModelIndex if there is no sibling at that location.
628
629 This implementation is significantly faster than going through the parent()
630 of the \a index.
631
632 \sa index(), QModelIndex::row(), QModelIndex::column()
633*/
634QModelIndex QRangeModel::sibling(int row, int column, const QModelIndex &index) const
635{
636 Q_D(const QRangeModel);
637 return d->impl->call<QRangeModelImplBase::Sibling>(row, column, index);
638}
639
640/*!
641 \reimp
642
643 Returns the number of rows under the given \a parent. This is the number of
644 items in the root range for an invalid \a parent index.
645
646 If the \a parent index is valid, then this function always returns 0 for
647 models that operate on list and table ranges. For trees, this returns the
648 size of the range returned by the childRows() implementation of the tree
649 traversal protocol.
650
651 \sa columnCount(), insertRows(), hasChildren()
652*/
653int QRangeModel::rowCount(const QModelIndex &parent) const
654{
655 Q_D(const QRangeModel);
656 return d->impl->call<QRangeModelImplBase::RowCount>(parent);
657}
658
659/*!
660 \reimp
661
662 Returns the number of columns of the model. This function returns the same
663 value for all \a parent indexes.
664
665 For models operating on a statically sized row type, this returned value is
666 always the same throughout the lifetime of the model. For models operating
667 on dynamically sized row type, the model returns the number of items in the
668 first row, or 0 if the model has no rows.
669
670 \sa rowCount, insertColumns()
671*/
672int QRangeModel::columnCount(const QModelIndex &parent) const
673{
674 Q_D(const QRangeModel);
675 return d->impl->call<QRangeModelImplBase::ColumnCount>(parent);
676}
677
678/*!
679 \reimp
680
681 Returns the item flags for the given \a index.
682
683 The implementation returns a combination of flags that enables the item
684 (\c ItemIsEnabled) and allows it to be selected (\c ItemIsSelectable). For
685 models operating on a range with mutable data, it also sets the flag
686 that allows the item to be editable (\c ItemIsEditable).
687
688 \sa Qt::ItemFlags
689*/
690Qt::ItemFlags QRangeModel::flags(const QModelIndex &index) const
691{
692 Q_D(const QRangeModel);
693 return d->impl->call<QRangeModelImplBase::Flags>(index);
694}
695
696/*!
697 \reimp
698
699 Returns the data for the given \a role and \a section in the header with
700 the specified \a orientation.
701
702 For horizontal headers, the section number corresponds to the column
703 number. Similarly, for vertical headers, the section number corresponds to
704 the row number.
705
706 For the horizontal header and the Qt::DisplayRole \a role, models that
707 operate on a range that uses an array as the row type return \a section. If
708 the row type is a tuple, then the implementation returns the name of the
709 type at \a section. For rows that are a gadget or QObject type, this
710 function returns the name of the property at the index of \a section.
711
712 For the vertical header, this function always returns the result of the
713 default implementation in QAbstractItemModel.
714
715 \sa Qt::ItemDataRole, setHeaderData(), QHeaderView
716*/
717QVariant QRangeModel::headerData(int section, Qt::Orientation orientation, int role) const
718{
719 Q_D(const QRangeModel);
720 return d->impl->call<QRangeModelImplBase::HeaderData>(section, orientation, role);
721}
722
723/*!
724 \reimp
725*/
726bool QRangeModel::setHeaderData(int section, Qt::Orientation orientation, const QVariant &data,
727 int role)
728{
729 return QAbstractItemModel::setHeaderData(section, orientation, data, role);
730}
731
732/*!
733 \reimp
734
735 Returns the data stored under the given \a role for the value in the
736 range referred to by the \a index.
737
738 If the item type for that index is an associative container that maps from
739 either \c{int}, Qt::ItemDataRole, or QString to a QVariant, then the role
740 data is looked up in that container and returned.
741
742 If the item is a gadget or QObject, then the implementation returns the
743 value of the item's property matching the \a role entry in the roleNames()
744 mapping.
745
746 Otherwise, the implementation returns a QVariant constructed from the item
747 via \c{QVariant::fromValue()} for \c{Qt::DisplayRole} or \c{Qt::EditRole}.
748 For other roles, the implementation returns an \b invalid
749 (default-constructed) QVariant.
750
751 \sa Qt::ItemDataRole, setData(), headerData()
752*/
753QVariant QRangeModel::data(const QModelIndex &index, int role) const
754{
755 Q_D(const QRangeModel);
756 return d->impl->call<QRangeModelImplBase::Data>(index, role);
757}
758
759/*!
760 \reimp
761
762 Sets the \a role data for the item at \a index to \a data.
763
764 If the item type for that \a index is an associative container that maps
765 from either \c{int}, Qt::ItemDataRole, or QString to a QVariant, then
766 \a data is stored in that container for the key specified by \a role.
767
768 If the item is a gadget or QObject, then \a data is written to the item's
769 property matching the \a role entry in the the roleNames() mapping. The
770 function returns \c{true} if a property was found and if \a data stored a
771 value that could be converted to the required type, otherwise returns
772 \c{false}.
773
774 Otherwise, this implementation assigns the value in \a data to the item at
775 the \a index in the range for \c{Qt::DisplayRole} and \c{Qt::EditRole},
776 and returns \c{true}. For other roles, the implementation returns
777 \c{false}.
778
779//! [read-only-setData]
780 For models operating on a read-only range, or on a read-only column in
781 a row type that implements \l{the C++ tuple protocol}, this implementation
782 returns \c{false} immediately.
783//! [read-only-setData]
784*/
785bool QRangeModel::setData(const QModelIndex &index, const QVariant &data, int role)
786{
787 Q_D(QRangeModel);
788 return d->impl->call<QRangeModelImplBase::SetData>(index, data, role);
789}
790
791/*!
792 \reimp
793
794 Returns a map with values for all predefined roles in the model for the
795 item at the given \a index.
796
797 If the item type for that \a index is an associative container that maps
798 from either \c{int}, Qt::ItemDataRole, or QString to a QVariant, then the
799 data from that container is returned.
800
801 If the item type is a gadget or QObject subclass, then the values of those
802 properties that match a \l{roleNames()}{role name} are returned.
803
804 If the item is not an associative container, gadget, or QObject subclass,
805 then this calls the base class implementation.
806
807 \sa setItemData(), Qt::ItemDataRole, data()
808*/
809QMap<int, QVariant> QRangeModel::itemData(const QModelIndex &index) const
810{
811 Q_D(const QRangeModel);
812 return d->impl->call<QRangeModelImplBase::ItemData>(index);
813}
814
815/*!
816 \reimp
817
818 If the item type for that \a index is an associative container that maps
819 from either \c{int} or Qt::ItemDataRole to a QVariant, then the entries in
820 \a data are stored in that container. If the associative container maps from
821 QString to QVariant, then only those values in \a data are stored for which
822 there is a mapping in the \l{roleNames()}{role names} table.
823
824 If the item type is a gadget or QObject subclass, then those properties that
825 match a \l{roleNames()}{role name} are set to the corresponding value in
826 \a data.
827
828 Roles for which there is no entry in \a data are not modified.
829
830 For item types that can be copied, this implementation is transactional,
831 and returns true if all the entries from \a data could be stored. If any
832 entry could not be updated, then the original container is not modified at
833 all, and the function returns false.
834
835 If the item is not an associative container, gadget, or QObject subclass,
836 then this calls the base class implementation, which calls setData() for
837 each entry in \a data.
838
839 \sa itemData(), setData(), Qt::ItemDataRole
840*/
841bool QRangeModel::setItemData(const QModelIndex &index, const QMap<int, QVariant> &data)
842{
843 Q_D(QRangeModel);
844 return d->impl->call<QRangeModelImplBase::SetItemData>(index, data);
845}
846
847/*!
848 \reimp
849
850 Replaces the value stored in the range at \a index with a default-
851 constructed value.
852
853 \include qrangemodel.cpp read-only-setData
854*/
855bool QRangeModel::clearItemData(const QModelIndex &index)
856{
857 Q_D(QRangeModel);
858 return d->impl->call<QRangeModelImplBase::ClearItemData>(index);
859}
860
861/*
862//! [column-change-requirement]
863 \note A dynamically sized row type needs to provide a \c{\1} member function.
864
865 For models operating on a read-only range, or on a range with a
866 statically sized row type (such as a tuple, array, or struct), this
867 implementation does nothing and returns \c{false} immediately. This is
868 always the case for tree models.
869//! [column-change-requirement]
870*/
871
872/*!
873 \reimp
874
875 Inserts \a count empty columns before the item at \a column in all rows
876 of the range at \a parent. Returns \c{true} if successful; otherwise
877 returns \c{false}.
878
879 \include qrangemodel.cpp {column-change-requirement} {insert(const_iterator, size_t, value_type)}
880*/
881bool QRangeModel::insertColumns(int column, int count, const QModelIndex &parent)
882{
883 Q_D(QRangeModel);
884 return d->impl->call<QRangeModelImplBase::InsertColumns>(column, count, parent);
885}
886
887/*!
888 \reimp
889
890 Removes \a count columns from the item at \a column on in all rows of the
891 range at \a parent. Returns \c{true} if successful, otherwise returns
892 \c{false}.
893
894 \include qrangemodel.cpp {column-change-requirement} {erase(const_iterator, size_t)}
895*/
896bool QRangeModel::removeColumns(int column, int count, const QModelIndex &parent)
897{
898 Q_D(QRangeModel);
899 return d->impl->call<QRangeModelImplBase::RemoveColumns>(column, count, parent);
900}
901
902/*!
903 \reimp
904
905 Moves \a count columns starting with the given \a sourceColumn under parent
906 \a sourceParent to column \a destinationColumn under parent \a destinationParent.
907
908 Returns \c{true} if the columns were successfully moved; otherwise returns
909 \c{false}.
910*/
911bool QRangeModel::moveColumns(const QModelIndex &sourceParent, int sourceColumn, int count,
912 const QModelIndex &destinationParent, int destinationColumn)
913{
914 Q_D(QRangeModel);
915 return d->impl->call<QRangeModelImplBase::MoveColumns>(
916 sourceParent, sourceColumn, count,
917 destinationParent, destinationColumn);
918}
919
920/*
921//! [row-change-requirement]
922 \note The range needs to be dynamically sized and provide a \c{\1}
923 member function.
924
925 For models operating on a read-only or statically-sized range (such as
926 an array), this implementation does nothing and returns \c{false}
927 immediately.
928//! [row-change-requirement]
929*/
930
931/*!
932 \reimp
933
934 Inserts \a count empty rows before the given \a row into the range at
935 \a parent. Returns \c{true} if successful; otherwise returns \c{false}.
936
937 \include qrangemodel.cpp {row-change-requirement} {insert(const_iterator, size_t, value_type)}
938
939 \note For ranges with a dynamically sized column type, the column needs
940 to provide a \c{resize(size_t)} member function.
941*/
942bool QRangeModel::insertRows(int row, int count, const QModelIndex &parent)
943{
944 Q_D(QRangeModel);
945 return d->impl->call<QRangeModelImplBase::InsertRows>(row, count, parent);
946}
947
948/*!
949 \reimp
950
951 Removes \a count rows from the range at \a parent, starting with the
952 given \a row. Returns \c{true} if successful, otherwise returns \c{false}.
953
954 \include qrangemodel.cpp {row-change-requirement} {erase(const_iterator, size_t)}
955*/
956bool QRangeModel::removeRows(int row, int count, const QModelIndex &parent)
957{
958 Q_D(QRangeModel);
959 return d->impl->call<QRangeModelImplBase::RemoveRows>(row, count, parent);
960}
961
962/*!
963 \reimp
964
965 Moves \a count rows starting with the given \a sourceRow under parent
966 \a sourceParent to row \a destinationRow under parent \a destinationParent.
967
968 Returns \c{true} if the rows were successfully moved; otherwise returns
969 \c{false}.
970*/
971bool QRangeModel::moveRows(const QModelIndex &sourceParent, int sourceRow, int count,
972 const QModelIndex &destinationParent, int destinationRow)
973{
974 Q_D(QRangeModel);
975 return d->impl->call<QRangeModelImplBase::MoveRows>(
976 sourceParent, sourceRow, count,
977 destinationParent, destinationRow);
978}
979
980/*!
981 \reimp
982*/
983bool QRangeModel::canFetchMore(const QModelIndex &parent) const
984{
985 return QAbstractItemModel::canFetchMore(parent);
986}
987
988/*!
989 \reimp
990*/
991void QRangeModel::fetchMore(const QModelIndex &parent)
992{
993 QAbstractItemModel::fetchMore(parent);
994}
995
996/*!
997 \reimp
998*/
999bool QRangeModel::hasChildren(const QModelIndex &parent) const
1000{
1001 return QAbstractItemModel::hasChildren(parent);
1002}
1003
1004/*!
1005 \reimp
1006*/
1007QModelIndex QRangeModel::buddy(const QModelIndex &index) const
1008{
1009 return QAbstractItemModel::buddy(index);
1010}
1011
1012/*!
1013 \reimp
1014*/
1015bool QRangeModel::canDropMimeData(const QMimeData *data, Qt::DropAction action,
1016 int row, int column, const QModelIndex &parent) const
1017{
1018 return QAbstractItemModel::canDropMimeData(data, action, row, column, parent);
1019}
1020
1021/*!
1022 \reimp
1023*/
1024bool QRangeModel::dropMimeData(const QMimeData *data, Qt::DropAction action,
1025 int row, int column, const QModelIndex &parent)
1026{
1027 return QAbstractItemModel::dropMimeData(data, action, row, column, parent);
1028}
1029
1030/*!
1031 \reimp
1032*/
1033QMimeData *QRangeModel::mimeData(const QModelIndexList &indexes) const
1034{
1035 return QAbstractItemModel::mimeData(indexes);
1036}
1037
1038/*!
1039 \reimp
1040*/
1041QStringList QRangeModel::mimeTypes() const
1042{
1043 return QAbstractItemModel::mimeTypes();
1044}
1045
1046/*!
1047 \reimp
1048*/
1049QModelIndexList QRangeModel::match(const QModelIndex &start, int role, const QVariant &value,
1050 int hits, Qt::MatchFlags flags) const
1051{
1052 return QAbstractItemModel::match(start, role, value, hits, flags);
1053}
1054
1055/*!
1056 \reimp
1057*/
1058void QRangeModel::multiData(const QModelIndex &index, QModelRoleDataSpan roleDataSpan) const
1059{
1060 Q_D(const QRangeModel);
1061 d->impl->call<QRangeModelImplBase::MultiData>(index, roleDataSpan);
1062}
1063
1064
1065/*!
1066 \property QRangeModel::roleNames
1067 \brief the role names for the model.
1068
1069 If all columns in the range are of the same type, and if that type provides
1070 a meta object (i.e., it is a gadget, or a QObject subclass), then this
1071 property holds the names of the properties of that type, mapped to values of
1072 Qt::ItemDataRole values from Qt::UserRole and up. In addition, a role
1073 "modelData" provides access to the gadget or QObject instance.
1074
1075 Override this default behavior by setting this property explicitly to a non-
1076 empty mapping. Setting this property to an empty mapping, or using
1077 resetRoleNames(), restores the default behavior.
1078
1079 \sa QAbstractItemModel::roleNames()
1080*/
1081
1082QHash<int, QByteArray> QRangeModelImplBase::roleNamesForMetaObject(const QAbstractItemModel &model,
1083 const QMetaObject &metaObject)
1084{
1085 const auto defaults = model.QAbstractItemModel::roleNames();
1086 QHash<int, QByteArray> result = {{Qt::RangeModelDataRole, "modelData"}};
1087 int offset = metaObject.propertyOffset();
1088 for (int i = offset; i < metaObject.propertyCount(); ++i) {
1089 const auto name = metaObject.property(i).name();
1090 const int defaultRole = defaults.key(name, -1);
1091 if (defaultRole != -1) {
1092 ++offset;
1093 result[defaultRole] = name;
1094 } else {
1095 result[Qt::UserRole + i - offset] = name;
1096 }
1097 }
1098 return result;
1099}
1100
1101QHash<int, QByteArray> QRangeModelImplBase::roleNamesForSimpleType()
1102{
1103 // just a plain value
1104 return QHash<int, QByteArray>{
1105 {Qt::DisplayRole, "display"},
1106 {Qt::EditRole, "edit"},
1107 {Qt::RangeModelDataRole, "modelData"},
1108 };
1109}
1110
1111/*!
1112 \reimp
1113
1114 \note Overriding this function in a QRangeModel subclass is possible,
1115 but might break the behavior of the property.
1116*/
1117QHash<int, QByteArray> QRangeModel::roleNames() const
1118{
1119 Q_D(const QRangeModel);
1120 if (d->m_roleNames.isEmpty())
1121 d->m_roleNames = d->impl->call<QRangeModelImplBase::RoleNames>();
1122
1123 return d->m_roleNames;
1124}
1125
1126void QRangeModel::setRoleNames(const QHash<int, QByteArray> &names)
1127{
1128 Q_D(QRangeModel);
1129 if (d->m_roleNames == names)
1130 return;
1131 beginResetModel();
1132 d->impl->call<QRangeModelImplBase::InvalidateCaches>();
1133 d->m_roleNames = names;
1134 endResetModel();
1135 Q_EMIT roleNamesChanged();
1136}
1137
1138void QRangeModel::resetRoleNames()
1139{
1140 setRoleNames({});
1141}
1142
1143/*!
1144 \reimp
1145*/
1146void QRangeModel::sort(int column, Qt::SortOrder order)
1147{
1148 return QAbstractItemModel::sort(column, order);
1149}
1150
1151/*!
1152 \reimp
1153*/
1154QSize QRangeModel::span(const QModelIndex &index) const
1155{
1156 return QAbstractItemModel::span(index);
1157}
1158
1159/*!
1160 \reimp
1161*/
1162Qt::DropActions QRangeModel::supportedDragActions() const
1163{
1164 return QAbstractItemModel::supportedDragActions();
1165}
1166
1167/*!
1168 \reimp
1169*/
1170Qt::DropActions QRangeModel::supportedDropActions() const
1171{
1172 return QAbstractItemModel::supportedDropActions();
1173}
1174
1175/*!
1176 \reimp
1177*/
1178void QRangeModel::resetInternalData()
1179{
1180 QAbstractItemModel::resetInternalData();
1181}
1182
1183/*!
1184 \reimp
1185*/
1186bool QRangeModel::event(QEvent *event)
1187{
1188 return QAbstractItemModel::event(event);
1189}
1190
1191/*!
1192 \reimp
1193*/
1194bool QRangeModel::eventFilter(QObject *object, QEvent *event)
1195{
1196 return QAbstractItemModel::eventFilter(object, event);
1197}
1198
1199QT_END_NAMESPACE
1200
1201#include "moc_qrangemodel.cpp"