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