QGIM: Rename to QRangeModel
As per the discussion on the mailing list [1], we want to avoid the word "Generic" in class names. And QGIM is by design not using 'items', so similar to e.g. QAbstractListModel or QSqlQueryModel, we don't need to have "item" in the class name either. It is a "Model", which is a well defined concept in Qt, that operates on any C++ range, which is a well defined concept in C++. QRangeModel is the best name. Future evolutions on this API, e.g. adding a C++ template class that provides an idiomatic C++ range API around the data while also updating the Qt model, are not expected to be problematic by using this name. [1] https://lists.qt-project.org/pipermail/development/2025-May/046322.html Change-Id: Idaa70f8b2a30754cb28da13a0e6b0e22334afa11 Reviewed-by: Artem Dyomin <artem.dyomin@qt.io> Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io> Reviewed-by: Samuel Gaist <samuel.gaist@idiap.ch>
This commit is contained in:
parent
2d0e3c5001
commit
bdbe4c8858
@ -1170,7 +1170,7 @@ qt_internal_extend_target(Core CONDITION QT_FEATURE_itemmodel
|
||||
SOURCES
|
||||
itemmodels/qabstractitemmodel.cpp itemmodels/qabstractitemmodel.h itemmodels/qabstractitemmodel_p.h
|
||||
itemmodels/qitemselectionmodel.cpp itemmodels/qitemselectionmodel.h itemmodels/qitemselectionmodel_p.h
|
||||
itemmodels/qgenericitemmodel.h itemmodels/qgenericitemmodel_impl.h itemmodels/qgenericitemmodel.cpp
|
||||
itemmodels/qrangemodel.h itemmodels/qrangemodel_impl.h itemmodels/qrangemodel.cpp
|
||||
)
|
||||
|
||||
qt_internal_extend_target(Core CONDITION QT_FEATURE_proxymodel
|
||||
|
@ -2,7 +2,7 @@
|
||||
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
add_library(corelib_snippets OBJECT
|
||||
qgenericitemmodel/main.cpp
|
||||
qrangemodel/main.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(corelib_snippets PRIVATE
|
||||
|
@ -1,7 +1,7 @@
|
||||
// Copyright (C) 2025 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
#include <QtCore/qgenericitemmodel.h>
|
||||
#include <QtCore/qrangemodel.h>
|
||||
|
||||
#ifndef QT_NO_WIDGETS
|
||||
|
||||
@ -19,7 +19,7 @@ void array()
|
||||
|
||||
//! [array]
|
||||
std::array<int, 5> numbers = {1, 2, 3, 4, 5};
|
||||
QGenericItemModel model(numbers);
|
||||
QRangeModel model(numbers);
|
||||
listView.setModel(&model);
|
||||
//! [array]
|
||||
}
|
||||
@ -30,26 +30,26 @@ void construct_by()
|
||||
|
||||
{
|
||||
//! [value]
|
||||
QGenericItemModel model(numbers);
|
||||
QRangeModel model(numbers);
|
||||
//! [value]
|
||||
}
|
||||
|
||||
{
|
||||
//! [pointer]
|
||||
QGenericItemModel model(&numbers);
|
||||
QRangeModel model(&numbers);
|
||||
//! [pointer]
|
||||
}
|
||||
|
||||
{
|
||||
//! [reference_wrapper]
|
||||
QGenericItemModel model(std::ref(numbers));
|
||||
QRangeModel model(std::ref(numbers));
|
||||
//! [reference_wrapper]
|
||||
}
|
||||
|
||||
{
|
||||
//! [smart_pointer]
|
||||
auto shared_numbers = std::make_shared<std::vector<int>>(numbers);
|
||||
QGenericItemModel model(shared_numbers);
|
||||
QRangeModel model(shared_numbers);
|
||||
//! [smart_pointer]
|
||||
}
|
||||
}
|
||||
@ -59,7 +59,7 @@ void const_array()
|
||||
//! [const_array]
|
||||
const std::array<int, 5> numbers = {1, 2, 3, 4, 5};
|
||||
//! [const_array]
|
||||
QGenericItemModel model(numbers);
|
||||
QRangeModel model(numbers);
|
||||
}
|
||||
|
||||
void const_values()
|
||||
@ -67,14 +67,14 @@ void const_values()
|
||||
//! [const_values]
|
||||
std::array<const int, 5> numbers = {1, 2, 3, 4, 5};
|
||||
//! [const_values]
|
||||
QGenericItemModel model(numbers);
|
||||
QRangeModel model(numbers);
|
||||
}
|
||||
|
||||
void const_ref()
|
||||
{
|
||||
std::vector<int> numbers = {1, 2, 3, 4, 5};
|
||||
//! [const_ref]
|
||||
QGenericItemModel model(std::cref(numbers));
|
||||
QRangeModel model(std::cref(numbers));
|
||||
//! [const_ref]
|
||||
}
|
||||
|
||||
@ -82,7 +82,7 @@ void list_of_int()
|
||||
{
|
||||
//! [list_of_int]
|
||||
QList<int> numbers = {1, 2, 3, 4, 5};
|
||||
QGenericItemModel model(numbers); // columnCount() == 1
|
||||
QRangeModel model(numbers); // columnCount() == 1
|
||||
QListView listView;
|
||||
listView.setModel(&model);
|
||||
//! [list_of_int]
|
||||
@ -96,7 +96,7 @@ std::vector<std::vector<int>> gridOfNumbers = {
|
||||
{6, 7, 8, 9, 10},
|
||||
{11, 12, 13, 14, 15},
|
||||
};
|
||||
QGenericItemModel model(&gridOfNumbers); // columnCount() == 5
|
||||
QRangeModel model(&gridOfNumbers); // columnCount() == 5
|
||||
QTableView tableView;
|
||||
tableView.setModel(&model);
|
||||
//! [grid_of_numbers]
|
||||
@ -111,7 +111,7 @@ QList<TableRow> numberNames = {
|
||||
{2, "two"},
|
||||
{3, "three"}
|
||||
};
|
||||
QGenericItemModel model(&numberNames); // columnCount() == 2
|
||||
QRangeModel model(&numberNames); // columnCount() == 2
|
||||
QTableView tableView;
|
||||
tableView.setModel(&model);
|
||||
//! [pair_int_QString]
|
||||
@ -220,7 +220,7 @@ public:
|
||||
std::optional<Tree> &childRows() { return m_children; }
|
||||
//! [tree_protocol_3]
|
||||
//! [tree_protocol_4]
|
||||
// Helper to assembly a tree of rows, not used by QGenericItemModel
|
||||
// Helper to assembly a tree of rows, not used by QRangeModel
|
||||
template <typename ...Args>
|
||||
TreeRow &addChild(Args &&...args)
|
||||
{
|
||||
@ -259,7 +259,7 @@ tree[2].addChild("...");
|
||||
{
|
||||
//! [tree_protocol_6]
|
||||
// instantiate the model with a pointer to the tree, not a copy!
|
||||
QGenericItemModel model(&tree);
|
||||
QRangeModel model(&tree);
|
||||
QTreeView view;
|
||||
view.setModel(&model);
|
||||
//! [tree_protocol_6]
|
||||
@ -280,7 +280,7 @@ void explicit_tree_protocol()
|
||||
{
|
||||
Tree tree;
|
||||
//! [explicit_tree_protocol_1]
|
||||
QGenericItemModel model(&tree, TreeTraversal{});
|
||||
QRangeModel model(&tree, TreeTraversal{});
|
||||
//! [explicit_tree_protocol_1]
|
||||
}
|
||||
} // namespace tree_protocol
|
||||
@ -366,7 +366,7 @@ int main(int argc, char **argv)
|
||||
|
||||
Tree tree = make_tree_of_pointers();
|
||||
|
||||
QGenericItemModel model(std::move(tree), TreeTraversal{});
|
||||
QRangeModel model(std::move(tree), TreeTraversal{});
|
||||
QTreeView treeView;
|
||||
treeView.setModel(&model);
|
||||
treeView.show();
|
||||
@ -391,7 +391,7 @@ for (const QString &name : colorNames) {
|
||||
{Qt::DecorationRole, color},
|
||||
{Qt::ToolTipRole, color.name()}};
|
||||
}
|
||||
QGenericItemModel colorModel(colors);
|
||||
QRangeModel colorModel(colors);
|
||||
QListView list;
|
||||
list.setModel(&colorModel);
|
||||
//! [color_map]
|
||||
@ -427,12 +427,12 @@ private:
|
||||
void color_list() {
|
||||
//! [color_gadget_1]
|
||||
const QStringList colorNames = QColor::colorNames();
|
||||
QList<QGenericItemModel::SingleColumn<ColorEntry>> colors;
|
||||
QList<QRangeModel::SingleColumn<ColorEntry>> colors;
|
||||
colors.reserve(colorNames.size());
|
||||
for (const QString &name : colorNames)
|
||||
colors << ColorEntry{name};
|
||||
|
||||
QGenericItemModel colorModel(colors);
|
||||
QRangeModel colorModel(colors);
|
||||
QListView list;
|
||||
list.setModel(&colorModel);
|
||||
//! [color_gadget_1]
|
@ -1,29 +1,29 @@
|
||||
// Copyright (C) 2025 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
||||
|
||||
#include "qgenericitemmodel.h"
|
||||
#include "qrangemodel.h"
|
||||
#include <QtCore/qsize.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
/*!
|
||||
\class QGenericItemModel
|
||||
\class QRangeModel
|
||||
\inmodule QtCore
|
||||
\since 6.10
|
||||
\ingroup model-view
|
||||
\brief QGenericItemModel implements QAbstractItemModel for any C++ range.
|
||||
\brief QRangeModel implements QAbstractItemModel for any C++ range.
|
||||
\reentrant
|
||||
|
||||
QGenericItemModel can make the data in any sequentially iterable C++ type
|
||||
QRangeModel can make the data in any sequentially iterable C++ type
|
||||
available to the \l{Model/View Programming}{model/view framework} of Qt.
|
||||
This makes it easy to display existing data structures in the Qt Widgets
|
||||
and Qt Quick item views, and to allow the user of the application to
|
||||
manipulate the data using a graphical user interface.
|
||||
|
||||
To use QGenericItemModel, instantiate it with a C++ range and set it as
|
||||
To use QRangeModel, instantiate it with a C++ range and set it as
|
||||
the model of one or more views:
|
||||
|
||||
\snippet qgenericitemmodel/main.cpp array
|
||||
\snippet qrangemodel/main.cpp array
|
||||
|
||||
The range can be any C++ type for which the standard methods
|
||||
\c{std::cbegin} and \c{std::cend} are implemented, and for which the
|
||||
@ -43,7 +43,7 @@ QT_BEGIN_NAMESPACE
|
||||
QAbstractItemModel APIs that modify the model, such as setData() or
|
||||
insertRows(), have no impact on the original range.
|
||||
|
||||
\snippet qgenericitemmodel/main.cpp value
|
||||
\snippet qrangemodel/main.cpp value
|
||||
|
||||
As there is no API to retrieve the range again, constructing the model from
|
||||
a range by value is mostly only useful for displaying read-only data.
|
||||
@ -58,8 +58,8 @@ QT_BEGIN_NAMESPACE
|
||||
To make modifications of the model affect the original range, provide the
|
||||
range either by reference wrapper or by pointer.
|
||||
|
||||
\snippet qgenericitemmodel/main.cpp pointer
|
||||
\snippet qgenericitemmodel/main.cpp reference_wrapper
|
||||
\snippet qrangemodel/main.cpp pointer
|
||||
\snippet qrangemodel/main.cpp reference_wrapper
|
||||
|
||||
In this case, QAbstractItemModel APIs that modify the model also modify the
|
||||
range. Methods that modify the structure of the range, such as insertRows()
|
||||
@ -78,32 +78,32 @@ QT_BEGIN_NAMESPACE
|
||||
Use smart pointers to make sure that the range is only deleted when all
|
||||
clients are done with it.
|
||||
|
||||
\snippet qgenericitemmodel/main.cpp smart_pointer
|
||||
\snippet qrangemodel/main.cpp smart_pointer
|
||||
|
||||
QGenericItemModel supports both shared and unique pointers.
|
||||
QRangeModel supports both shared and unique pointers.
|
||||
|
||||
\section2 Read-only or mutable
|
||||
|
||||
For ranges that are const objects, for which access always yields constant
|
||||
values, or where the required container APIs are not available,
|
||||
QGenericItemModel implements write-access APIs to do nothing and return
|
||||
QRangeModel implements write-access APIs to do nothing and return
|
||||
\c{false}. In the example using \c{std::array}, the model cannot add or
|
||||
remove rows, as the number of entries in a C++ array is fixed. But the
|
||||
values can be changed using setData(), and the user can trigger editing of
|
||||
the values in the list view. By making the array const, the values also
|
||||
become read-only.
|
||||
|
||||
\snippet qgenericitemmodel/main.cpp const_array
|
||||
\snippet qrangemodel/main.cpp const_array
|
||||
|
||||
The values are also read-only if the element type is const, like in
|
||||
|
||||
\snippet qgenericitemmodel/main.cpp const_values
|
||||
\snippet qrangemodel/main.cpp const_values
|
||||
|
||||
In the above examples using \c{std::vector}, the model can add or remove
|
||||
rows, and the data can be changed. Passing the range as a constant
|
||||
reference will make the model read-only.
|
||||
|
||||
\snippet qgenericitemmodel/main.cpp const_ref
|
||||
\snippet qrangemodel/main.cpp const_ref
|
||||
|
||||
\note If the values in the range are const, then it's also not possible
|
||||
to remove or insert columns and rows through the QAbstractItemModel API.
|
||||
@ -112,18 +112,18 @@ QT_BEGIN_NAMESPACE
|
||||
\section1 Rows and columns
|
||||
|
||||
The elements in the range are interpreted as rows of the model. Depending
|
||||
on the type of these row elements, QGenericItemModel exposes the range as a
|
||||
on the type of these row elements, QRangeModel exposes the range as a
|
||||
list, a table, or a tree.
|
||||
|
||||
If the row elements are simple values, then the range gets represented as a
|
||||
list.
|
||||
|
||||
\snippet qgenericitemmodel/main.cpp list_of_int
|
||||
\snippet qrangemodel/main.cpp list_of_int
|
||||
|
||||
If the type of the row elements is an iterable range, such as a vector,
|
||||
list, or array, then the range gets represented as a table.
|
||||
|
||||
\snippet qgenericitemmodel/main.cpp grid_of_numbers
|
||||
\snippet qrangemodel/main.cpp grid_of_numbers
|
||||
|
||||
If the row type provides the standard C++ container APIs \c{resize()},
|
||||
\c{insert()}, \c{erase()}, then columns can be added and removed via
|
||||
@ -135,14 +135,14 @@ QT_BEGIN_NAMESPACE
|
||||
If the row type implements \l{the C++ tuple protocol}, then the range gets
|
||||
represented as a table with a fixed number of columns.
|
||||
|
||||
\snippet qgenericitemmodel/main.cpp pair_int_QString
|
||||
\snippet qrangemodel/main.cpp pair_int_QString
|
||||
|
||||
An easier and more flexible alternative to implementing the tuple protocol
|
||||
for a C++ type is to use Qt's \l{Meta-Object System}{meta-object system} to
|
||||
declare a type with \l{Qt's Property System}{properties}. This can be a
|
||||
value type that is declared as a \l{Q_GADGET}{gadget}, or a QObject subclass.
|
||||
|
||||
\snippet qgenericitemmodel/main.cpp gadget
|
||||
\snippet qrangemodel/main.cpp gadget
|
||||
|
||||
Using QObject subclasses allows properties to be \l{Qt Bindable Properties}
|
||||
{bindable}, or to have change notification signals. However, using QObject
|
||||
@ -170,13 +170,13 @@ QT_BEGIN_NAMESPACE
|
||||
|
||||
If the item is an associative container that uses \c{int},
|
||||
\l{Qt::ItemDataRole}, or QString as the key type, and QVariant as the
|
||||
mapped type, then QGenericItemModel interprets that container as the storage
|
||||
mapped type, then QRangeModel interprets that container as the storage
|
||||
of the data for multiple roles. The data() and setData() functions return
|
||||
and modify the mapped value in the container, and setItemData() modifies all
|
||||
provided values, itemData() returns all stored values, and clearItemData()
|
||||
clears the entire container.
|
||||
|
||||
\snippet qgenericitemmodel/main.cpp color_map
|
||||
\snippet qrangemodel/main.cpp color_map
|
||||
|
||||
The most efficient data type to use as the key is Qt::ItemDataRole or
|
||||
\c{int}. When using \c{int}, itemData() returns the container as is, and
|
||||
@ -186,36 +186,36 @@ QT_BEGIN_NAMESPACE
|
||||
are the item type in a table. The names of the properties have to match the
|
||||
names of the roles.
|
||||
|
||||
\snippet qgenericitemmodel/main.cpp color_gadget_0
|
||||
\snippet qrangemodel/main.cpp color_gadget_0
|
||||
|
||||
When used in a list, these types are ambiguous: they can be represented as
|
||||
multi-column rows, with each property represented as a separate column. Or
|
||||
they can be single items with each property being a role. To disambiguate,
|
||||
use the QGenericItemModel::SingleColumn and QGenericItemModel::MultiColumn
|
||||
use the QRangeModel::SingleColumn and QRangeModel::MultiColumn
|
||||
wrappers.
|
||||
|
||||
\snippet qgenericitemmodel/main.cpp color_gadget_1
|
||||
\snippet qrangemodel/main.cpp color_gadget_1
|
||||
|
||||
\section1 Trees of data
|
||||
|
||||
QGenericItemModel can represent a data structure as a tree model. Such a
|
||||
QRangeModel can represent a data structure as a tree model. Such a
|
||||
tree data structure needs to be homomorphic: on all levels of the tree, the
|
||||
list of child rows needs to use the exact same representation as the tree
|
||||
itself. In addition, the row type needs be of a static size: either a gadget
|
||||
or QObject type, or a type that implements the {C++ tuple protocol}.
|
||||
|
||||
To represent such data as a tree, the row type has to implement a traversal
|
||||
protocol that allows QGenericItemModel to navigate up and down the tree.
|
||||
protocol that allows QRangeModel to navigate up and down the tree.
|
||||
For any given row, the model needs to be able to retrieve the parent row,
|
||||
and the span of children for any given row.
|
||||
|
||||
\snippet qgenericitemmodel/main.cpp tree_protocol_0
|
||||
\snippet qrangemodel/main.cpp tree_protocol_0
|
||||
|
||||
The tree itself is a vector of \c{TreeRow} values. See \l{Rows as pointers
|
||||
or values} for the considerations on whether to use values or pointers of
|
||||
items for the rows.
|
||||
|
||||
\snippet qgenericitemmodel/main.cpp tree_protocol_1
|
||||
\snippet qrangemodel/main.cpp tree_protocol_1
|
||||
|
||||
The row class can be of any fixed-size type described above: a type that
|
||||
implements the tuple protocol, a gadget, or a QObject. In this example, we
|
||||
@ -229,7 +229,7 @@ QT_BEGIN_NAMESPACE
|
||||
to construct new row data elements, for instance in the insertRow() or
|
||||
moveRows() implementations.
|
||||
|
||||
\snippet qgenericitemmodel/main.cpp tree_protocol_2
|
||||
\snippet qrangemodel/main.cpp tree_protocol_2
|
||||
|
||||
The tree traversal protocol can then be implemented as member functions of
|
||||
the row data type. A const \c{parentRow()} function has to return a pointer
|
||||
@ -242,7 +242,7 @@ QT_BEGIN_NAMESPACE
|
||||
model to implement mutating model APIs such as insertRows(), removeRows(),
|
||||
and moveRows(), we have to implement additional functions for write-access:
|
||||
|
||||
\snippet qgenericitemmodel/main.cpp tree_protocol_3
|
||||
\snippet qrangemodel/main.cpp tree_protocol_3
|
||||
|
||||
The model calls the \c{setParentRow()} function and mutable \c{childRows()}
|
||||
overload to move or insert rows into an existing tree branch, and to update
|
||||
@ -255,29 +255,29 @@ QT_BEGIN_NAMESPACE
|
||||
as separate steps. This keeps the protocol interface small.
|
||||
|
||||
\dots
|
||||
\snippet qgenericitemmodel/main.cpp tree_protocol_4
|
||||
\snippet qrangemodel/main.cpp tree_protocol_4
|
||||
|
||||
The rest of the class implementation is not relevant for the model, but
|
||||
a \c{addChild()} helper provides us with a convenient way to construct the
|
||||
initial state of the tree.
|
||||
|
||||
\snippet qgenericitemmodel/main.cpp tree_protocol_5
|
||||
\snippet qrangemodel/main.cpp tree_protocol_5
|
||||
|
||||
A QGenericItemModel instantiated with an instance of such a range will
|
||||
A QRangeModel instantiated with an instance of such a range will
|
||||
represent the data as a tree.
|
||||
|
||||
\snippet qgenericitemmodel/main.cpp tree_protocol_6
|
||||
\snippet qrangemodel/main.cpp tree_protocol_6
|
||||
|
||||
\section3 Tree traversal protocol in a separate class
|
||||
|
||||
The tree traversal protocol can also be implemented in a separate class.
|
||||
|
||||
\snippet qgenericitemmodel/main.cpp explicit_tree_protocol_0
|
||||
\snippet qrangemodel/main.cpp explicit_tree_protocol_0
|
||||
|
||||
Pass an instance of this protocol implementation to the QGenericItemModel
|
||||
Pass an instance of this protocol implementation to the QRangeModel
|
||||
constructor:
|
||||
|
||||
\snippet qgenericitemmodel/main.cpp explicit_tree_protocol_1
|
||||
\snippet qrangemodel/main.cpp explicit_tree_protocol_1
|
||||
|
||||
\section2 Rows as pointers or values
|
||||
|
||||
@ -290,41 +290,41 @@ QT_BEGIN_NAMESPACE
|
||||
the location of the parent row within the vector. Making sure that this
|
||||
parent (and QPersistentModelIndex instances referring to items within it)
|
||||
stays valid can incurr substantial performance overhead. The
|
||||
QGenericItemModel implementation has to assume that all references into the
|
||||
QRangeModel implementation has to assume that all references into the
|
||||
range become invalid when modifying the range.
|
||||
|
||||
Alternatively, we can also use a range of row pointers as the tree type:
|
||||
|
||||
\snippet qgenericitemmodel/main.cpp tree_of_pointers_0
|
||||
\snippet qrangemodel/main.cpp tree_of_pointers_0
|
||||
|
||||
In this case, we have to allocate all TreeRow instances explicitly using
|
||||
operator \c{new}, and implement the destructor to \c{delete} all items in
|
||||
the vector of children.
|
||||
|
||||
\snippet qgenericitemmodel/main.cpp tree_of_pointers_1
|
||||
\snippet qgenericitemmodel/main.cpp tree_of_pointers_2
|
||||
\snippet qrangemodel/main.cpp tree_of_pointers_1
|
||||
\snippet qrangemodel/main.cpp tree_of_pointers_2
|
||||
|
||||
Before we can construct a model that represents this data as a tree, we need
|
||||
to also implement the tree traversal protocol.
|
||||
|
||||
\snippet qgenericitemmodel/main.cpp tree_of_pointers_3
|
||||
\snippet qrangemodel/main.cpp tree_of_pointers_3
|
||||
|
||||
An explicit protocol implementation for mutable trees of pointers has to
|
||||
provide two additional member functions, \c{newRow()} and
|
||||
\c{deleteRow(RowType *)}.
|
||||
|
||||
\snippet qgenericitemmodel/main.cpp tree_of_pointers_4
|
||||
\snippet qrangemodel/main.cpp tree_of_pointers_4
|
||||
|
||||
The model will call those functions when creating new rows in insertRows(),
|
||||
and when removing rows in removeRows(). In addition, if the model has
|
||||
ownership of the data, then it will also delete all top-level rows upon
|
||||
destruction. Note how in this example, we move the tree into the model, so
|
||||
we must no longer perform any operations on it. QGenericItemModel, when
|
||||
we must no longer perform any operations on it. QRangeModel, when
|
||||
constructed by moving tree-data with row-pointers into it, will take
|
||||
ownership of the data, and delete the row pointers in it's destructor.
|
||||
|
||||
\note This is not the case for tables and lists that use pointers as their
|
||||
row type. QGenericItemModel will never allocate new rows in lists and tables
|
||||
row type. QRangeModel will never allocate new rows in lists and tables
|
||||
using operator new, and will never free any rows.
|
||||
|
||||
Using pointers at rows comes with some memory allocation and management
|
||||
@ -346,7 +346,7 @@ QT_BEGIN_NAMESPACE
|
||||
type to make existing structured data available to the model/view framework
|
||||
in Qt.
|
||||
|
||||
\snippet qgenericitemmodel/main.cpp tuple_protocol
|
||||
\snippet qrangemodel/main.cpp tuple_protocol
|
||||
|
||||
In the above implementation, the \c{title} and \c{author} values of the
|
||||
\c{Book} type are returned as \c{const}, so the model flags items in those
|
||||
@ -358,25 +358,25 @@ QT_BEGIN_NAMESPACE
|
||||
those columns editable, both for the user and for programmatic access.
|
||||
|
||||
\note The implementation of \c{get} above requires C++23. A C++17 compliant
|
||||
implementation can be found in the unit test code for QGenericItemModel.
|
||||
implementation can be found in the unit test code for QRangeModel.
|
||||
|
||||
Types that have a meta objects, and implement the C++ tuple protocol, also
|
||||
can cause compile-time ambiguity when used as the row type, as the framework
|
||||
won't know which API to use to access the individual values. Use the
|
||||
QGenericItemModel::SingleColumn and QGenericItemModel::MultiColumns wrapper
|
||||
QRangeModel::SingleColumn and QRangeModel::MultiColumns wrapper
|
||||
to disambiguate.
|
||||
|
||||
\sa {Model/View Programming}
|
||||
*/
|
||||
|
||||
/*!
|
||||
\typedef QGenericItemModel::SingleColumn
|
||||
\typedef QRangeModel::SingleColumn
|
||||
|
||||
Use this type to disambiguate when using the type \c{T} as the row type in
|
||||
the range. If \c{T} provides a metaobject, then the framework will by
|
||||
default represent the type as multiple columns, resulting in a table model.
|
||||
|
||||
\snippet qgenericitemmodel/main.cpp color_gadget_0
|
||||
\snippet qrangemodel/main.cpp color_gadget_0
|
||||
|
||||
When stored in a sequential range, this type will be interpreted as
|
||||
multi-column rows with each property being one column. The range will be
|
||||
@ -386,25 +386,25 @@ QT_BEGIN_NAMESPACE
|
||||
QList<ColorEntry> colors = {
|
||||
// ...
|
||||
};
|
||||
QGenericItemModel tableModel(colors); // columnCount() == 3
|
||||
QRangeModel tableModel(colors); // columnCount() == 3
|
||||
\endcode
|
||||
|
||||
When wrapped into QGenericItemModel::SingleColumn, the model will be a list,
|
||||
When wrapped into QRangeModel::SingleColumn, the model will be a list,
|
||||
with each instance of \c{T} represented as an item with multiple roles.
|
||||
|
||||
\code
|
||||
QList<QGenericItemModel::SingleColumn<ColorEntry>> colors = {
|
||||
QList<QRangeModel::SingleColumn<ColorEntry>> colors = {
|
||||
// ...
|
||||
};
|
||||
QGenericItemModel listModel(colors); // columnCount() == 1
|
||||
QRangeModel listModel(colors); // columnCount() == 1
|
||||
\endcode
|
||||
|
||||
\sa QGenericItemModel::MultiColumn
|
||||
\sa QRangeModel::MultiColumn
|
||||
*/
|
||||
|
||||
/*!
|
||||
\class QGenericItemModel::MultiColumn
|
||||
\brief Represents the wrapped type \c{T} as multiple columns in a QGenericItemModel.
|
||||
\class QRangeModel::MultiColumn
|
||||
\brief Represents the wrapped type \c{T} as multiple columns in a QRangeModel.
|
||||
\inmodule QtCore
|
||||
\ingroup model-view
|
||||
\since 6.10
|
||||
@ -414,29 +414,29 @@ QT_BEGIN_NAMESPACE
|
||||
multiple columns, and the individual values will be accessed through the
|
||||
tuple protocol.
|
||||
|
||||
\snippet qgenericitemmodel/main.cpp color_gadget_0
|
||||
\snippet qrangemodel/main.cpp color_gadget_0
|
||||
\code
|
||||
namespace std {
|
||||
template <> struct tuple_size<ColorEntry> : integral_constant<size_t, 3> {};
|
||||
// ...
|
||||
}
|
||||
|
||||
QList<QGenericItemModel::MultiColumn<ColorEntry>> colors = {
|
||||
QList<QRangeModel::MultiColumn<ColorEntry>> colors = {
|
||||
// ...
|
||||
};
|
||||
QGenericItemModel colorList(colors);
|
||||
QRangeModel colorList(colors);
|
||||
\endcode
|
||||
|
||||
To represent the type a single column value with multiple roles, use
|
||||
QGenericItemModel::SingleColumn instead.
|
||||
QRangeModel::SingleColumn instead.
|
||||
|
||||
\sa QGenericItemModel::SingleColumn
|
||||
\sa QRangeModel::SingleColumn
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn template <typename Range, QGenericItemModelDetails::if_is_table_range<Range>> QGenericItemModel::QGenericItemModel(Range &&range, QObject *parent)
|
||||
\fn template <typename Range, QGenericItemModelDetails::if_is_tree_range<Range>> QGenericItemModel::QGenericItemModel(Range &&range, QObject *parent)
|
||||
\fn template <typename Range, typename Protocol, QGenericItemModelDetails::if_is_tree_range<Range, Protocol>> QGenericItemModel::QGenericItemModel(Range &&range, Protocol &&protocol, QObject *parent)
|
||||
\fn template <typename Range, QRangeModelDetails::if_is_table_range<Range>> QRangeModel::QRangeModel(Range &&range, QObject *parent)
|
||||
\fn template <typename Range, QRangeModelDetails::if_is_tree_range<Range>> QRangeModel::QRangeModel(Range &&range, QObject *parent)
|
||||
\fn template <typename Range, typename Protocol, QRangeModelDetails::if_is_tree_range<Range, Protocol>> QRangeModel::QRangeModel(Range &&range, Protocol &&protocol, QObject *parent)
|
||||
|
||||
Constructs a generic item model instance that operates on the data in \a
|
||||
range. The \a range has to be a sequential range for which \c{std::cbegin}
|
||||
@ -461,7 +461,7 @@ QT_BEGIN_NAMESPACE
|
||||
|
||||
The range that the model was constructed from is not destroyed.
|
||||
*/
|
||||
QGenericItemModel::~QGenericItemModel() = default;
|
||||
QRangeModel::~QRangeModel() = default;
|
||||
|
||||
/*!
|
||||
\reimp
|
||||
@ -473,9 +473,9 @@ QGenericItemModel::~QGenericItemModel() = default;
|
||||
|
||||
\sa parent()
|
||||
*/
|
||||
QModelIndex QGenericItemModel::index(int row, int column, const QModelIndex &parent) const
|
||||
QModelIndex QRangeModel::index(int row, int column, const QModelIndex &parent) const
|
||||
{
|
||||
return impl->callConst<QModelIndex>(QGenericItemModelImplBase::Index, row, column, parent);
|
||||
return impl->callConst<QModelIndex>(QRangeModelImplBase::Index, row, column, parent);
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -490,9 +490,9 @@ QModelIndex QGenericItemModel::index(int row, int column, const QModelIndex &par
|
||||
|
||||
\sa index(), hasChildren()
|
||||
*/
|
||||
QModelIndex QGenericItemModel::parent(const QModelIndex &child) const
|
||||
QModelIndex QRangeModel::parent(const QModelIndex &child) const
|
||||
{
|
||||
return impl->callConst<QModelIndex>(QGenericItemModelImplBase::Parent, child);
|
||||
return impl->callConst<QModelIndex>(QRangeModelImplBase::Parent, child);
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -506,9 +506,9 @@ QModelIndex QGenericItemModel::parent(const QModelIndex &child) const
|
||||
|
||||
\sa index(), QModelIndex::row(), QModelIndex::column()
|
||||
*/
|
||||
QModelIndex QGenericItemModel::sibling(int row, int column, const QModelIndex &index) const
|
||||
QModelIndex QRangeModel::sibling(int row, int column, const QModelIndex &index) const
|
||||
{
|
||||
return impl->callConst<QModelIndex>(QGenericItemModelImplBase::Sibling, row, column, index);
|
||||
return impl->callConst<QModelIndex>(QRangeModelImplBase::Sibling, row, column, index);
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -524,9 +524,9 @@ QModelIndex QGenericItemModel::sibling(int row, int column, const QModelIndex &i
|
||||
|
||||
\sa columnCount(), insertRows(), hasChildren()
|
||||
*/
|
||||
int QGenericItemModel::rowCount(const QModelIndex &parent) const
|
||||
int QRangeModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
return impl->callConst<int>(QGenericItemModelImplBase::RowCount, parent);
|
||||
return impl->callConst<int>(QRangeModelImplBase::RowCount, parent);
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -542,9 +542,9 @@ int QGenericItemModel::rowCount(const QModelIndex &parent) const
|
||||
|
||||
\sa rowCount, insertColumns()
|
||||
*/
|
||||
int QGenericItemModel::columnCount(const QModelIndex &parent) const
|
||||
int QRangeModel::columnCount(const QModelIndex &parent) const
|
||||
{
|
||||
return impl->callConst<int>(QGenericItemModelImplBase::ColumnCount, parent);
|
||||
return impl->callConst<int>(QRangeModelImplBase::ColumnCount, parent);
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -559,9 +559,9 @@ int QGenericItemModel::columnCount(const QModelIndex &parent) const
|
||||
|
||||
\sa Qt::ItemFlags
|
||||
*/
|
||||
Qt::ItemFlags QGenericItemModel::flags(const QModelIndex &index) const
|
||||
Qt::ItemFlags QRangeModel::flags(const QModelIndex &index) const
|
||||
{
|
||||
return impl->callConst<Qt::ItemFlags>(QGenericItemModelImplBase::Flags, index);
|
||||
return impl->callConst<Qt::ItemFlags>(QRangeModelImplBase::Flags, index);
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -576,9 +576,9 @@ Qt::ItemFlags QGenericItemModel::flags(const QModelIndex &index) const
|
||||
|
||||
\sa Qt::ItemDataRole, setHeaderData(), QHeaderView
|
||||
*/
|
||||
QVariant QGenericItemModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
QVariant QRangeModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
return impl->callConst<QVariant>(QGenericItemModelImplBase::HeaderData,
|
||||
return impl->callConst<QVariant>(QRangeModelImplBase::HeaderData,
|
||||
section, orientation, role);
|
||||
}
|
||||
|
||||
@ -599,9 +599,9 @@ QVariant QGenericItemModel::headerData(int section, Qt::Orientation orientation,
|
||||
|
||||
\sa Qt::ItemDataRole, setData(), headerData()
|
||||
*/
|
||||
QVariant QGenericItemModel::data(const QModelIndex &index, int role) const
|
||||
QVariant QRangeModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
return impl->callConst<QVariant>(QGenericItemModelImplBase::Data, index, role);
|
||||
return impl->callConst<QVariant>(QRangeModelImplBase::Data, index, role);
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -624,9 +624,9 @@ QVariant QGenericItemModel::data(const QModelIndex &index, int role) const
|
||||
returns \c{false} immediately.
|
||||
//! [read-only-setData]
|
||||
*/
|
||||
bool QGenericItemModel::setData(const QModelIndex &index, const QVariant &data, int role)
|
||||
bool QRangeModel::setData(const QModelIndex &index, const QVariant &data, int role)
|
||||
{
|
||||
return impl->call<bool>(QGenericItemModelImplBase::SetData, index, data, role);
|
||||
return impl->call<bool>(QRangeModelImplBase::SetData, index, data, role);
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -647,9 +647,9 @@ bool QGenericItemModel::setData(const QModelIndex &index, const QVariant &data,
|
||||
|
||||
\sa setItemData(), Qt::ItemDataRole, data()
|
||||
*/
|
||||
QMap<int, QVariant> QGenericItemModel::itemData(const QModelIndex &index) const
|
||||
QMap<int, QVariant> QRangeModel::itemData(const QModelIndex &index) const
|
||||
{
|
||||
return impl->callConst<QMap<int, QVariant>>(QGenericItemModelImplBase::ItemData, index);
|
||||
return impl->callConst<QMap<int, QVariant>>(QRangeModelImplBase::ItemData, index);
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -678,9 +678,9 @@ QMap<int, QVariant> QGenericItemModel::itemData(const QModelIndex &index) const
|
||||
|
||||
\sa itemData(), setData(), Qt::ItemDataRole
|
||||
*/
|
||||
bool QGenericItemModel::setItemData(const QModelIndex &index, const QMap<int, QVariant> &data)
|
||||
bool QRangeModel::setItemData(const QModelIndex &index, const QMap<int, QVariant> &data)
|
||||
{
|
||||
return impl->call<bool>(QGenericItemModelImplBase::SetItemData, index, data);
|
||||
return impl->call<bool>(QRangeModelImplBase::SetItemData, index, data);
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -689,11 +689,11 @@ bool QGenericItemModel::setItemData(const QModelIndex &index, const QMap<int, QV
|
||||
Replaces the value stored in the range at \a index with a default-
|
||||
constructed value.
|
||||
|
||||
\include qgenericitemmodel.cpp read-only-setData
|
||||
\include qrangemodel.cpp read-only-setData
|
||||
*/
|
||||
bool QGenericItemModel::clearItemData(const QModelIndex &index)
|
||||
bool QRangeModel::clearItemData(const QModelIndex &index)
|
||||
{
|
||||
return impl->call<bool>(QGenericItemModelImplBase::ClearItemData, index);
|
||||
return impl->call<bool>(QRangeModelImplBase::ClearItemData, index);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -714,11 +714,11 @@ bool QGenericItemModel::clearItemData(const QModelIndex &index)
|
||||
of the range at \a parent. Returns \c{true} if successful; otherwise
|
||||
returns \c{false}.
|
||||
|
||||
\include qgenericitemmodel.cpp {column-change-requirement} {insert(const_iterator, size_t, value_type)}
|
||||
\include qrangemodel.cpp {column-change-requirement} {insert(const_iterator, size_t, value_type)}
|
||||
*/
|
||||
bool QGenericItemModel::insertColumns(int column, int count, const QModelIndex &parent)
|
||||
bool QRangeModel::insertColumns(int column, int count, const QModelIndex &parent)
|
||||
{
|
||||
return impl->call<bool>(QGenericItemModelImplBase::InsertColumns, column, count, parent);
|
||||
return impl->call<bool>(QRangeModelImplBase::InsertColumns, column, count, parent);
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -728,11 +728,11 @@ bool QGenericItemModel::insertColumns(int column, int count, const QModelIndex &
|
||||
range at \a parent. Returns \c{true} if successful, otherwise returns
|
||||
\c{false}.
|
||||
|
||||
\include qgenericitemmodel.cpp {column-change-requirement} {erase(const_iterator, size_t)}
|
||||
\include qrangemodel.cpp {column-change-requirement} {erase(const_iterator, size_t)}
|
||||
*/
|
||||
bool QGenericItemModel::removeColumns(int column, int count, const QModelIndex &parent)
|
||||
bool QRangeModel::removeColumns(int column, int count, const QModelIndex &parent)
|
||||
{
|
||||
return impl->call<bool>(QGenericItemModelImplBase::RemoveColumns, column, count, parent);
|
||||
return impl->call<bool>(QRangeModelImplBase::RemoveColumns, column, count, parent);
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -744,10 +744,10 @@ bool QGenericItemModel::removeColumns(int column, int count, const QModelIndex &
|
||||
Returns \c{true} if the columns were successfully moved; otherwise returns
|
||||
\c{false}.
|
||||
*/
|
||||
bool QGenericItemModel::moveColumns(const QModelIndex &sourceParent, int sourceColumn, int count,
|
||||
bool QRangeModel::moveColumns(const QModelIndex &sourceParent, int sourceColumn, int count,
|
||||
const QModelIndex &destinationParent, int destinationColumn)
|
||||
{
|
||||
return impl->call<bool>(QGenericItemModelImplBase::MoveColumns,
|
||||
return impl->call<bool>(QRangeModelImplBase::MoveColumns,
|
||||
sourceParent, sourceColumn, count,
|
||||
destinationParent, destinationColumn);
|
||||
}
|
||||
@ -769,14 +769,14 @@ bool QGenericItemModel::moveColumns(const QModelIndex &sourceParent, int sourceC
|
||||
Inserts \a count empty rows before the given \a row into the range at
|
||||
\a parent. Returns \c{true} if successful; otherwise returns \c{false}.
|
||||
|
||||
\include qgenericitemmodel.cpp {row-change-requirement} {insert(const_iterator, size_t, value_type)}
|
||||
\include qrangemodel.cpp {row-change-requirement} {insert(const_iterator, size_t, value_type)}
|
||||
|
||||
\note For ranges with a dynamically sized column type, the column needs
|
||||
to provide a \c{resize(size_t)} member function.
|
||||
*/
|
||||
bool QGenericItemModel::insertRows(int row, int count, const QModelIndex &parent)
|
||||
bool QRangeModel::insertRows(int row, int count, const QModelIndex &parent)
|
||||
{
|
||||
return impl->call<bool>(QGenericItemModelImplBase::InsertRows, row, count, parent);
|
||||
return impl->call<bool>(QRangeModelImplBase::InsertRows, row, count, parent);
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -785,11 +785,11 @@ bool QGenericItemModel::insertRows(int row, int count, const QModelIndex &parent
|
||||
Removes \a count rows from the range at \a parent, starting with the
|
||||
given \a row. Returns \c{true} if successful, otherwise returns \c{false}.
|
||||
|
||||
\include qgenericitemmodel.cpp {row-change-requirement} {erase(const_iterator, size_t)}
|
||||
\include qrangemodel.cpp {row-change-requirement} {erase(const_iterator, size_t)}
|
||||
*/
|
||||
bool QGenericItemModel::removeRows(int row, int count, const QModelIndex &parent)
|
||||
bool QRangeModel::removeRows(int row, int count, const QModelIndex &parent)
|
||||
{
|
||||
return impl->call<bool>(QGenericItemModelImplBase::RemoveRows, row, count, parent);
|
||||
return impl->call<bool>(QRangeModelImplBase::RemoveRows, row, count, parent);
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -801,10 +801,10 @@ bool QGenericItemModel::removeRows(int row, int count, const QModelIndex &parent
|
||||
Returns \c{true} if the rows were successfully moved; otherwise returns
|
||||
\c{false}.
|
||||
*/
|
||||
bool QGenericItemModel::moveRows(const QModelIndex &sourceParent, int sourceRow, int count,
|
||||
bool QRangeModel::moveRows(const QModelIndex &sourceParent, int sourceRow, int count,
|
||||
const QModelIndex &destinationParent, int destinationRow)
|
||||
{
|
||||
return impl->call<bool>(QGenericItemModelImplBase::MoveRows,
|
||||
return impl->call<bool>(QRangeModelImplBase::MoveRows,
|
||||
sourceParent, sourceRow, count,
|
||||
destinationParent, destinationRow);
|
||||
}
|
||||
@ -812,7 +812,7 @@ bool QGenericItemModel::moveRows(const QModelIndex &sourceParent, int sourceRow,
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
bool QGenericItemModel::canFetchMore(const QModelIndex &parent) const
|
||||
bool QRangeModel::canFetchMore(const QModelIndex &parent) const
|
||||
{
|
||||
return QAbstractItemModel::canFetchMore(parent);
|
||||
}
|
||||
@ -820,7 +820,7 @@ bool QGenericItemModel::canFetchMore(const QModelIndex &parent) const
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
void QGenericItemModel::fetchMore(const QModelIndex &parent)
|
||||
void QRangeModel::fetchMore(const QModelIndex &parent)
|
||||
{
|
||||
QAbstractItemModel::fetchMore(parent);
|
||||
}
|
||||
@ -828,7 +828,7 @@ void QGenericItemModel::fetchMore(const QModelIndex &parent)
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
bool QGenericItemModel::hasChildren(const QModelIndex &parent) const
|
||||
bool QRangeModel::hasChildren(const QModelIndex &parent) const
|
||||
{
|
||||
return QAbstractItemModel::hasChildren(parent);
|
||||
}
|
||||
@ -836,7 +836,7 @@ bool QGenericItemModel::hasChildren(const QModelIndex &parent) const
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
QModelIndex QGenericItemModel::buddy(const QModelIndex &index) const
|
||||
QModelIndex QRangeModel::buddy(const QModelIndex &index) const
|
||||
{
|
||||
return QAbstractItemModel::buddy(index);
|
||||
}
|
||||
@ -844,7 +844,7 @@ QModelIndex QGenericItemModel::buddy(const QModelIndex &index) const
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
bool QGenericItemModel::canDropMimeData(const QMimeData *data, Qt::DropAction action,
|
||||
bool QRangeModel::canDropMimeData(const QMimeData *data, Qt::DropAction action,
|
||||
int row, int column, const QModelIndex &parent) const
|
||||
{
|
||||
return QAbstractItemModel::canDropMimeData(data, action, row, column, parent);
|
||||
@ -853,7 +853,7 @@ bool QGenericItemModel::canDropMimeData(const QMimeData *data, Qt::DropAction ac
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
bool QGenericItemModel::dropMimeData(const QMimeData *data, Qt::DropAction action,
|
||||
bool QRangeModel::dropMimeData(const QMimeData *data, Qt::DropAction action,
|
||||
int row, int column, const QModelIndex &parent)
|
||||
{
|
||||
return QAbstractItemModel::dropMimeData(data, action, row, column, parent);
|
||||
@ -862,7 +862,7 @@ bool QGenericItemModel::dropMimeData(const QMimeData *data, Qt::DropAction actio
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
QMimeData *QGenericItemModel::mimeData(const QModelIndexList &indexes) const
|
||||
QMimeData *QRangeModel::mimeData(const QModelIndexList &indexes) const
|
||||
{
|
||||
return QAbstractItemModel::mimeData(indexes);
|
||||
}
|
||||
@ -870,7 +870,7 @@ QMimeData *QGenericItemModel::mimeData(const QModelIndexList &indexes) const
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
QStringList QGenericItemModel::mimeTypes() const
|
||||
QStringList QRangeModel::mimeTypes() const
|
||||
{
|
||||
return QAbstractItemModel::mimeTypes();
|
||||
}
|
||||
@ -878,7 +878,7 @@ QStringList QGenericItemModel::mimeTypes() const
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
QModelIndexList QGenericItemModel::match(const QModelIndex &start, int role, const QVariant &value,
|
||||
QModelIndexList QRangeModel::match(const QModelIndex &start, int role, const QVariant &value,
|
||||
int hits, Qt::MatchFlags flags) const
|
||||
{
|
||||
return QAbstractItemModel::match(start, role, value, hits, flags);
|
||||
@ -887,7 +887,7 @@ QModelIndexList QGenericItemModel::match(const QModelIndex &start, int role, con
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
void QGenericItemModel::multiData(const QModelIndex &index, QModelRoleDataSpan roleDataSpan) const
|
||||
void QRangeModel::multiData(const QModelIndex &index, QModelRoleDataSpan roleDataSpan) const
|
||||
{
|
||||
QAbstractItemModel::multiData(index, roleDataSpan);
|
||||
}
|
||||
@ -895,7 +895,7 @@ void QGenericItemModel::multiData(const QModelIndex &index, QModelRoleDataSpan r
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
QHash<int, QByteArray> QGenericItemModel::roleNames() const
|
||||
QHash<int, QByteArray> QRangeModel::roleNames() const
|
||||
{
|
||||
return QAbstractItemModel::roleNames();
|
||||
}
|
||||
@ -903,7 +903,7 @@ QHash<int, QByteArray> QGenericItemModel::roleNames() const
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
void QGenericItemModel::sort(int column, Qt::SortOrder order)
|
||||
void QRangeModel::sort(int column, Qt::SortOrder order)
|
||||
{
|
||||
return QAbstractItemModel::sort(column, order);
|
||||
}
|
||||
@ -911,7 +911,7 @@ void QGenericItemModel::sort(int column, Qt::SortOrder order)
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
QSize QGenericItemModel::span(const QModelIndex &index) const
|
||||
QSize QRangeModel::span(const QModelIndex &index) const
|
||||
{
|
||||
return QAbstractItemModel::span(index);
|
||||
}
|
||||
@ -919,7 +919,7 @@ QSize QGenericItemModel::span(const QModelIndex &index) const
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
Qt::DropActions QGenericItemModel::supportedDragActions() const
|
||||
Qt::DropActions QRangeModel::supportedDragActions() const
|
||||
{
|
||||
return QAbstractItemModel::supportedDragActions();
|
||||
}
|
||||
@ -927,7 +927,7 @@ Qt::DropActions QGenericItemModel::supportedDragActions() const
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
Qt::DropActions QGenericItemModel::supportedDropActions() const
|
||||
Qt::DropActions QRangeModel::supportedDropActions() const
|
||||
{
|
||||
return QAbstractItemModel::supportedDropActions();
|
||||
}
|
||||
@ -935,7 +935,7 @@ Qt::DropActions QGenericItemModel::supportedDropActions() const
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
void QGenericItemModel::resetInternalData()
|
||||
void QRangeModel::resetInternalData()
|
||||
{
|
||||
QAbstractItemModel::resetInternalData();
|
||||
}
|
||||
@ -943,7 +943,7 @@ void QGenericItemModel::resetInternalData()
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
bool QGenericItemModel::event(QEvent *event)
|
||||
bool QRangeModel::event(QEvent *event)
|
||||
{
|
||||
return QAbstractItemModel::event(event);
|
||||
}
|
||||
@ -951,11 +951,11 @@ bool QGenericItemModel::event(QEvent *event)
|
||||
/*!
|
||||
\reimp
|
||||
*/
|
||||
bool QGenericItemModel::eventFilter(QObject *object, QEvent *event)
|
||||
bool QRangeModel::eventFilter(QObject *object, QEvent *event)
|
||||
{
|
||||
return QAbstractItemModel::eventFilter(object, event);
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#include "moc_qgenericitemmodel.cpp"
|
||||
#include "moc_qrangemodel.cpp"
|
@ -1,14 +1,14 @@
|
||||
// Copyright (C) 2025 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
||||
|
||||
#ifndef QGENERICITEMMODEL_H
|
||||
#define QGENERICITEMMODEL_H
|
||||
#ifndef QRANGEMODEL_H
|
||||
#define QRANGEMODEL_H
|
||||
|
||||
#include <QtCore/qgenericitemmodel_impl.h>
|
||||
#include <QtCore/qrangemodel_impl.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class Q_CORE_EXPORT QGenericItemModel : public QAbstractItemModel
|
||||
class Q_CORE_EXPORT QRangeModel : public QAbstractItemModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
@ -25,7 +25,7 @@ public:
|
||||
MultiColumn<T>>, bool>;
|
||||
|
||||
template <typename V = T,
|
||||
std::enable_if_t<QGenericItemModelDetails::is_validatable<V>::value, bool> = true>
|
||||
std::enable_if_t<QRangeModelDetails::is_validatable<V>::value, bool> = true>
|
||||
constexpr explicit operator bool() const noexcept { return bool(data); }
|
||||
|
||||
// unconstrained on size_t I, gcc internal error #3280
|
||||
@ -33,23 +33,23 @@ public:
|
||||
friend inline decltype(auto) get(V &&multiColumn)
|
||||
{
|
||||
static_assert(I < std::tuple_size_v<type>, "Index out of bounds for wrapped type");
|
||||
return get<I>(QGenericItemModelDetails::refTo(q23::forward_like<V>(multiColumn.data)));
|
||||
return get<I>(QRangeModelDetails::refTo(q23::forward_like<V>(multiColumn.data)));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Range,
|
||||
QGenericItemModelDetails::if_is_table_range<Range> = true>
|
||||
explicit QGenericItemModel(Range &&range, QObject *parent = nullptr);
|
||||
QRangeModelDetails::if_is_table_range<Range> = true>
|
||||
explicit QRangeModel(Range &&range, QObject *parent = nullptr);
|
||||
|
||||
template <typename Range,
|
||||
QGenericItemModelDetails::if_is_tree_range<Range> = true>
|
||||
explicit QGenericItemModel(Range &&range, QObject *parent = nullptr);
|
||||
QRangeModelDetails::if_is_tree_range<Range> = true>
|
||||
explicit QRangeModel(Range &&range, QObject *parent = nullptr);
|
||||
|
||||
template <typename Range, typename Protocol,
|
||||
QGenericItemModelDetails::if_is_tree_range<Range, Protocol> = true>
|
||||
explicit QGenericItemModel(Range &&range, Protocol &&protocol, QObject *parent = nullptr);
|
||||
QRangeModelDetails::if_is_tree_range<Range, Protocol> = true>
|
||||
explicit QRangeModel(Range &&range, Protocol &&protocol, QObject *parent = nullptr);
|
||||
|
||||
~QGenericItemModel() override;
|
||||
~QRangeModel() override;
|
||||
|
||||
QModelIndex index(int row, int column, const QModelIndex &parent = {}) const override;
|
||||
QModelIndex parent(const QModelIndex &child) const override;
|
||||
@ -100,112 +100,112 @@ protected:
|
||||
bool eventFilter(QObject *, QEvent *) override;
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY_MOVE(QGenericItemModel)
|
||||
Q_DISABLE_COPY_MOVE(QRangeModel)
|
||||
|
||||
friend class QGenericItemModelImplBase;
|
||||
struct Deleter { void operator()(QGenericItemModelImplBase *that) { that->destroy(); } };
|
||||
std::unique_ptr<QGenericItemModelImplBase, Deleter> impl;
|
||||
friend class QRangeModelImplBase;
|
||||
struct Deleter { void operator()(QRangeModelImplBase *that) { that->destroy(); } };
|
||||
std::unique_ptr<QRangeModelImplBase, Deleter> impl;
|
||||
};
|
||||
|
||||
// implementation of forwarders
|
||||
QModelIndex QGenericItemModelImplBase::createIndex(int row, int column, const void *ptr) const
|
||||
QModelIndex QRangeModelImplBase::createIndex(int row, int column, const void *ptr) const
|
||||
{
|
||||
return m_itemModel->createIndex(row, column, ptr);
|
||||
return m_rangeModel->createIndex(row, column, ptr);
|
||||
}
|
||||
void QGenericItemModelImplBase::changePersistentIndexList(const QModelIndexList &from,
|
||||
void QRangeModelImplBase::changePersistentIndexList(const QModelIndexList &from,
|
||||
const QModelIndexList &to)
|
||||
{
|
||||
m_itemModel->changePersistentIndexList(from, to);
|
||||
m_rangeModel->changePersistentIndexList(from, to);
|
||||
}
|
||||
QHash<int, QByteArray> QGenericItemModelImplBase::roleNames() const
|
||||
QHash<int, QByteArray> QRangeModelImplBase::roleNames() const
|
||||
{
|
||||
return m_itemModel->roleNames();
|
||||
return m_rangeModel->roleNames();
|
||||
}
|
||||
void QGenericItemModelImplBase::dataChanged(const QModelIndex &from, const QModelIndex &to,
|
||||
void QRangeModelImplBase::dataChanged(const QModelIndex &from, const QModelIndex &to,
|
||||
const QList<int> &roles)
|
||||
{
|
||||
m_itemModel->dataChanged(from, to, roles);
|
||||
m_rangeModel->dataChanged(from, to, roles);
|
||||
}
|
||||
void QGenericItemModelImplBase::beginInsertColumns(const QModelIndex &parent, int start, int count)
|
||||
void QRangeModelImplBase::beginInsertColumns(const QModelIndex &parent, int start, int count)
|
||||
{
|
||||
m_itemModel->beginInsertColumns(parent, start, count);
|
||||
m_rangeModel->beginInsertColumns(parent, start, count);
|
||||
}
|
||||
void QGenericItemModelImplBase::endInsertColumns()
|
||||
void QRangeModelImplBase::endInsertColumns()
|
||||
{
|
||||
m_itemModel->endInsertColumns();
|
||||
m_rangeModel->endInsertColumns();
|
||||
}
|
||||
void QGenericItemModelImplBase::beginRemoveColumns(const QModelIndex &parent, int start, int count)
|
||||
void QRangeModelImplBase::beginRemoveColumns(const QModelIndex &parent, int start, int count)
|
||||
{
|
||||
m_itemModel->beginRemoveColumns(parent, start, count);
|
||||
m_rangeModel->beginRemoveColumns(parent, start, count);
|
||||
}
|
||||
void QGenericItemModelImplBase::endRemoveColumns()
|
||||
void QRangeModelImplBase::endRemoveColumns()
|
||||
{
|
||||
m_itemModel->endRemoveColumns();
|
||||
m_rangeModel->endRemoveColumns();
|
||||
}
|
||||
bool QGenericItemModelImplBase::beginMoveColumns(const QModelIndex &sourceParent, int sourceFirst,
|
||||
bool QRangeModelImplBase::beginMoveColumns(const QModelIndex &sourceParent, int sourceFirst,
|
||||
int sourceLast, const QModelIndex &destParent,
|
||||
int destColumn)
|
||||
{
|
||||
return m_itemModel->beginMoveColumns(sourceParent, sourceFirst, sourceLast,
|
||||
return m_rangeModel->beginMoveColumns(sourceParent, sourceFirst, sourceLast,
|
||||
destParent, destColumn);
|
||||
}
|
||||
void QGenericItemModelImplBase::endMoveColumns()
|
||||
void QRangeModelImplBase::endMoveColumns()
|
||||
{
|
||||
m_itemModel->endMoveColumns();
|
||||
m_rangeModel->endMoveColumns();
|
||||
}
|
||||
|
||||
void QGenericItemModelImplBase::beginInsertRows(const QModelIndex &parent, int start, int count)
|
||||
void QRangeModelImplBase::beginInsertRows(const QModelIndex &parent, int start, int count)
|
||||
{
|
||||
m_itemModel->beginInsertRows(parent, start, count);
|
||||
m_rangeModel->beginInsertRows(parent, start, count);
|
||||
}
|
||||
void QGenericItemModelImplBase::endInsertRows()
|
||||
void QRangeModelImplBase::endInsertRows()
|
||||
{
|
||||
m_itemModel->endInsertRows();
|
||||
m_rangeModel->endInsertRows();
|
||||
}
|
||||
void QGenericItemModelImplBase::beginRemoveRows(const QModelIndex &parent, int start, int count)
|
||||
void QRangeModelImplBase::beginRemoveRows(const QModelIndex &parent, int start, int count)
|
||||
{
|
||||
m_itemModel->beginRemoveRows(parent, start, count);
|
||||
m_rangeModel->beginRemoveRows(parent, start, count);
|
||||
}
|
||||
void QGenericItemModelImplBase::endRemoveRows()
|
||||
void QRangeModelImplBase::endRemoveRows()
|
||||
{
|
||||
m_itemModel->endRemoveRows();
|
||||
m_rangeModel->endRemoveRows();
|
||||
}
|
||||
bool QGenericItemModelImplBase::beginMoveRows(const QModelIndex &sourceParent, int sourceFirst,
|
||||
bool QRangeModelImplBase::beginMoveRows(const QModelIndex &sourceParent, int sourceFirst,
|
||||
int sourceLast,
|
||||
const QModelIndex &destParent, int destRow)
|
||||
{
|
||||
return m_itemModel->beginMoveRows(sourceParent, sourceFirst, sourceLast, destParent, destRow);
|
||||
return m_rangeModel->beginMoveRows(sourceParent, sourceFirst, sourceLast, destParent, destRow);
|
||||
}
|
||||
void QGenericItemModelImplBase::endMoveRows()
|
||||
void QRangeModelImplBase::endMoveRows()
|
||||
{
|
||||
m_itemModel->endMoveRows();
|
||||
m_rangeModel->endMoveRows();
|
||||
}
|
||||
QAbstractItemModel &QGenericItemModelImplBase::itemModel()
|
||||
QAbstractItemModel &QRangeModelImplBase::itemModel()
|
||||
{
|
||||
return *m_itemModel;
|
||||
return *m_rangeModel;
|
||||
}
|
||||
const QAbstractItemModel &QGenericItemModelImplBase::itemModel() const
|
||||
const QAbstractItemModel &QRangeModelImplBase::itemModel() const
|
||||
{
|
||||
return *m_itemModel;
|
||||
return *m_rangeModel;
|
||||
}
|
||||
|
||||
template <typename Range,
|
||||
QGenericItemModelDetails::if_is_table_range<Range>>
|
||||
QGenericItemModel::QGenericItemModel(Range &&range, QObject *parent)
|
||||
QRangeModelDetails::if_is_table_range<Range>>
|
||||
QRangeModel::QRangeModel(Range &&range, QObject *parent)
|
||||
: QAbstractItemModel(parent)
|
||||
, impl(new QGenericTableItemModelImpl<Range>(std::forward<Range>(range), this))
|
||||
{}
|
||||
|
||||
template <typename Range,
|
||||
QGenericItemModelDetails::if_is_tree_range<Range>>
|
||||
QGenericItemModel::QGenericItemModel(Range &&range, QObject *parent)
|
||||
: QGenericItemModel(std::forward<Range>(range),
|
||||
QGenericItemModelDetails::DefaultTreeProtocol<Range>{}, parent)
|
||||
QRangeModelDetails::if_is_tree_range<Range>>
|
||||
QRangeModel::QRangeModel(Range &&range, QObject *parent)
|
||||
: QRangeModel(std::forward<Range>(range),
|
||||
QRangeModelDetails::DefaultTreeProtocol<Range>{}, parent)
|
||||
{}
|
||||
|
||||
template <typename Range, typename Protocol,
|
||||
QGenericItemModelDetails::if_is_tree_range<Range, Protocol>>
|
||||
QGenericItemModel::QGenericItemModel(Range &&range, Protocol &&protocol, QObject *parent)
|
||||
QRangeModelDetails::if_is_tree_range<Range, Protocol>>
|
||||
QRangeModel::QRangeModel(Range &&range, Protocol &&protocol, QObject *parent)
|
||||
: QAbstractItemModel(parent)
|
||||
, impl(new QGenericTreeItemModelImpl<Range, Protocol>(std::forward<Range>(range),
|
||||
std::forward<Protocol>(protocol), this))
|
||||
@ -215,13 +215,13 @@ QT_END_NAMESPACE
|
||||
|
||||
namespace std {
|
||||
template <typename T>
|
||||
struct tuple_size<QT_PREPEND_NAMESPACE(QGenericItemModel)::MultiColumn<T>>
|
||||
: tuple_size<typename QT_PREPEND_NAMESPACE(QGenericItemModel)::MultiColumn<T>::type>
|
||||
struct tuple_size<QT_PREPEND_NAMESPACE(QRangeModel)::MultiColumn<T>>
|
||||
: tuple_size<typename QT_PREPEND_NAMESPACE(QRangeModel)::MultiColumn<T>::type>
|
||||
{};
|
||||
template <std::size_t I, typename T>
|
||||
struct tuple_element<I, QT_PREPEND_NAMESPACE(QGenericItemModel)::MultiColumn<T>>
|
||||
: tuple_element<I, typename QT_PREPEND_NAMESPACE(QGenericItemModel)::MultiColumn<T>::type>
|
||||
struct tuple_element<I, QT_PREPEND_NAMESPACE(QRangeModel)::MultiColumn<T>>
|
||||
: tuple_element<I, typename QT_PREPEND_NAMESPACE(QRangeModel)::MultiColumn<T>::type>
|
||||
{};
|
||||
}
|
||||
|
||||
#endif // QGENERICITEMMODEL_H
|
||||
#endif // QRANGEMODEL_H
|
@ -1,13 +1,13 @@
|
||||
// Copyright (C) 2025 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
||||
|
||||
#ifndef QGENERICITEMMODEL_IMPL_H
|
||||
#define QGENERICITEMMODEL_IMPL_H
|
||||
#ifndef QRANGEMODEL_IMPL_H
|
||||
#define QRANGEMODEL_IMPL_H
|
||||
|
||||
#ifndef Q_QDOC
|
||||
|
||||
#ifndef QGENERICITEMMODEL_H
|
||||
#error Do not include qgenericitemmodel_impl.h directly
|
||||
#ifndef QRANGEMODEL_H
|
||||
#error Do not include qrangemodel_impl.h directly
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
@ -30,7 +30,7 @@
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
namespace QGenericItemModelDetails
|
||||
namespace QRangeModelDetails
|
||||
{
|
||||
template <typename T, template <typename...> typename... Templates>
|
||||
struct is_any_of_impl : std::false_type {};
|
||||
@ -145,10 +145,10 @@ namespace QGenericItemModelDetails
|
||||
{ return std::cend(refTo(std::forward<C>(c))); }
|
||||
template <typename C>
|
||||
static auto pos(C &&c, int i)
|
||||
{ return std::next(QGenericItemModelDetails::begin(std::forward<C>(c)), i); }
|
||||
{ return std::next(QRangeModelDetails::begin(std::forward<C>(c)), i); }
|
||||
template <typename C>
|
||||
static auto cpos(C &&c, int i)
|
||||
{ return std::next(QGenericItemModelDetails::cbegin(std::forward<C>(c)), i); }
|
||||
{ return std::next(QRangeModelDetails::cbegin(std::forward<C>(c)), i); }
|
||||
|
||||
// Test if a type is a range, and whether we can modify it using the
|
||||
// standard C++ container member functions insert, erase, and resize.
|
||||
@ -501,26 +501,26 @@ namespace QGenericItemModelDetails
|
||||
};
|
||||
}
|
||||
|
||||
class QGenericItemModel;
|
||||
class QRangeModel;
|
||||
|
||||
class QGenericItemModelImplBase
|
||||
class QRangeModelImplBase
|
||||
{
|
||||
Q_DISABLE_COPY_MOVE(QGenericItemModelImplBase)
|
||||
Q_DISABLE_COPY_MOVE(QRangeModelImplBase)
|
||||
protected:
|
||||
// Helpers for calling a lambda with the tuple element at a runtime index.
|
||||
template <typename Tuple, typename F, size_t ...Is>
|
||||
static void call_at(Tuple &&tuple, size_t idx, std::index_sequence<Is...>, F &&function)
|
||||
{
|
||||
if (QGenericItemModelDetails::isValid(tuple))
|
||||
if (QRangeModelDetails::isValid(tuple))
|
||||
((Is == idx ? static_cast<void>(function(get<Is>(
|
||||
QGenericItemModelDetails::refTo(std::forward<Tuple>(tuple)))))
|
||||
QRangeModelDetails::refTo(std::forward<Tuple>(tuple)))))
|
||||
: static_cast<void>(0)), ...);
|
||||
}
|
||||
|
||||
template <typename T, typename F>
|
||||
static auto for_element_at(T &&tuple, size_t idx, F &&function)
|
||||
{
|
||||
using type = QGenericItemModelDetails::wrapped_t<T>;
|
||||
using type = QRangeModelDetails::wrapped_t<T>;
|
||||
constexpr size_t size = std::tuple_size_v<type>;
|
||||
Q_ASSERT(idx < size);
|
||||
return call_at(std::forward<T>(tuple), idx, std::make_index_sequence<size>{},
|
||||
@ -537,7 +537,7 @@ protected:
|
||||
template <typename T>
|
||||
static constexpr QMetaType meta_type_at(size_t idx)
|
||||
{
|
||||
using type = QGenericItemModelDetails::wrapped_t<T>;
|
||||
using type = QRangeModelDetails::wrapped_t<T>;
|
||||
constexpr auto size = std::tuple_size_v<type>;
|
||||
Q_ASSERT(idx < size);
|
||||
return makeMetaTypes<type>(std::make_index_sequence<size>{}).at(idx);
|
||||
@ -550,7 +550,7 @@ protected:
|
||||
return std::invoke(fn, obj, std::get<I>(tuple)...);
|
||||
}
|
||||
template <typename Ret, typename Class, typename ...Args>
|
||||
static void makeCall(QGenericItemModelImplBase *obj, Ret(Class::* &&fn)(Args...),
|
||||
static void makeCall(QRangeModelImplBase *obj, Ret(Class::* &&fn)(Args...),
|
||||
void *ret, const void *args)
|
||||
{
|
||||
const auto &tuple = *static_cast<const std::tuple<Args&...> *>(args);
|
||||
@ -558,7 +558,7 @@ protected:
|
||||
static_cast<Class *>(obj), fn, tuple);
|
||||
}
|
||||
template <typename Ret, typename Class, typename ...Args>
|
||||
static void makeCall(const QGenericItemModelImplBase *obj, Ret(Class::* &&fn)(Args...) const,
|
||||
static void makeCall(const QRangeModelImplBase *obj, Ret(Class::* &&fn)(Args...) const,
|
||||
void *ret, const void *args)
|
||||
{
|
||||
const auto &tuple = *static_cast<const std::tuple<Args&...> *>(args);
|
||||
@ -599,22 +599,22 @@ public:
|
||||
|
||||
private:
|
||||
// prototypes
|
||||
static void callConst(ConstOp, const QGenericItemModelImplBase *, void *, const void *);
|
||||
static void call(Op, QGenericItemModelImplBase *, void *, const void *);
|
||||
static void callConst(ConstOp, const QRangeModelImplBase *, void *, const void *);
|
||||
static void call(Op, QRangeModelImplBase *, void *, const void *);
|
||||
|
||||
using CallConstFN = decltype(callConst);
|
||||
using CallTupleFN = decltype(call);
|
||||
|
||||
CallConstFN *callConst_fn;
|
||||
CallTupleFN *call_fn;
|
||||
QGenericItemModel *m_itemModel;
|
||||
QRangeModel *m_rangeModel;
|
||||
|
||||
protected:
|
||||
template <typename Impl> // type deduction
|
||||
explicit QGenericItemModelImplBase(QGenericItemModel *itemModel, const Impl *)
|
||||
: callConst_fn(&Impl::callConst), call_fn(&Impl::call), m_itemModel(itemModel)
|
||||
explicit QRangeModelImplBase(QRangeModel *itemModel, const Impl *)
|
||||
: callConst_fn(&Impl::callConst), call_fn(&Impl::call), m_rangeModel(itemModel)
|
||||
{}
|
||||
~QGenericItemModelImplBase() = default;
|
||||
~QRangeModelImplBase() = default;
|
||||
|
||||
inline QModelIndex createIndex(int row, int column, const void *ptr = nullptr) const;
|
||||
inline void changePersistentIndexList(const QModelIndexList &from, const QModelIndexList &to);
|
||||
@ -659,52 +659,52 @@ public:
|
||||
};
|
||||
|
||||
template <typename Structure, typename Range,
|
||||
typename Protocol = QGenericItemModelDetails::table_protocol_t<Range>>
|
||||
class QGenericItemModelImpl : public QGenericItemModelImplBase
|
||||
typename Protocol = QRangeModelDetails::table_protocol_t<Range>>
|
||||
class QRangeModelImpl : public QRangeModelImplBase
|
||||
{
|
||||
Q_DISABLE_COPY_MOVE(QGenericItemModelImpl)
|
||||
Q_DISABLE_COPY_MOVE(QRangeModelImpl)
|
||||
public:
|
||||
using range_type = QGenericItemModelDetails::wrapped_t<Range>;
|
||||
using row_reference = decltype(*QGenericItemModelDetails::begin(std::declval<range_type&>()));
|
||||
using const_row_reference = decltype(*QGenericItemModelDetails::cbegin(std::declval<range_type&>()));
|
||||
using range_type = QRangeModelDetails::wrapped_t<Range>;
|
||||
using row_reference = decltype(*QRangeModelDetails::begin(std::declval<range_type&>()));
|
||||
using const_row_reference = decltype(*QRangeModelDetails::cbegin(std::declval<range_type&>()));
|
||||
using row_type = std::remove_reference_t<row_reference>;
|
||||
using protocol_type = QGenericItemModelDetails::wrapped_t<Protocol>;
|
||||
using protocol_type = QRangeModelDetails::wrapped_t<Protocol>;
|
||||
|
||||
static_assert(!QGenericItemModelDetails::is_any_of<range_type, std::optional>() &&
|
||||
!QGenericItemModelDetails::is_any_of<row_type, std::optional>(),
|
||||
static_assert(!QRangeModelDetails::is_any_of<range_type, std::optional>() &&
|
||||
!QRangeModelDetails::is_any_of<row_type, std::optional>(),
|
||||
"Currently, std::optional is not supported for ranges and rows, as "
|
||||
"it has range semantics in c++26. Once the required behavior is clarified, "
|
||||
"std::optional for ranges and rows will be supported.");
|
||||
|
||||
protected:
|
||||
using Self = QGenericItemModelImpl<Structure, Range, Protocol>;
|
||||
using Self = QRangeModelImpl<Structure, Range, Protocol>;
|
||||
Structure& that() { return static_cast<Structure &>(*this); }
|
||||
const Structure& that() const { return static_cast<const Structure &>(*this); }
|
||||
|
||||
template <typename C>
|
||||
static constexpr int size(const C &c)
|
||||
{
|
||||
if (!QGenericItemModelDetails::isValid(c))
|
||||
if (!QRangeModelDetails::isValid(c))
|
||||
return 0;
|
||||
|
||||
if constexpr (QGenericItemModelDetails::test_size<C>()) {
|
||||
if constexpr (QRangeModelDetails::test_size<C>()) {
|
||||
return int(std::size(c));
|
||||
} else {
|
||||
#if defined(__cpp_lib_ranges)
|
||||
return int(std::ranges::distance(QGenericItemModelDetails::begin(c),
|
||||
QGenericItemModelDetails::end(c)));
|
||||
return int(std::ranges::distance(QRangeModelDetails::begin(c),
|
||||
QRangeModelDetails::end(c)));
|
||||
#else
|
||||
return int(std::distance(QGenericItemModelDetails::begin(c),
|
||||
QGenericItemModelDetails::end(c)));
|
||||
return int(std::distance(QRangeModelDetails::begin(c),
|
||||
QRangeModelDetails::end(c)));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
using range_features = QGenericItemModelDetails::range_traits<range_type>;
|
||||
using wrapped_row_type = QGenericItemModelDetails::wrapped_t<row_type>;
|
||||
using row_features = QGenericItemModelDetails::range_traits<wrapped_row_type>;
|
||||
using row_traits = QGenericItemModelDetails::row_traits<std::remove_cv_t<wrapped_row_type>>;
|
||||
using protocol_traits = QGenericItemModelDetails::protocol_traits<Range, protocol_type>;
|
||||
using range_features = QRangeModelDetails::range_traits<range_type>;
|
||||
using wrapped_row_type = QRangeModelDetails::wrapped_t<row_type>;
|
||||
using row_features = QRangeModelDetails::range_traits<wrapped_row_type>;
|
||||
using row_traits = QRangeModelDetails::row_traits<std::remove_cv_t<wrapped_row_type>>;
|
||||
using protocol_traits = QRangeModelDetails::protocol_traits<Range, protocol_type>;
|
||||
|
||||
static constexpr bool isMutable()
|
||||
{
|
||||
@ -713,11 +713,11 @@ protected:
|
||||
&& Structure::is_mutable_impl;
|
||||
}
|
||||
|
||||
static constexpr int static_row_count = QGenericItemModelDetails::static_size_v<range_type>;
|
||||
static constexpr int static_row_count = QRangeModelDetails::static_size_v<range_type>;
|
||||
static constexpr bool rows_are_raw_pointers = std::is_pointer_v<row_type>;
|
||||
static constexpr bool rows_are_owning_or_raw_pointers =
|
||||
QGenericItemModelDetails::is_owning_or_raw_pointer<row_type>();
|
||||
static constexpr int static_column_count = QGenericItemModelDetails::static_size_v<row_type>;
|
||||
QRangeModelDetails::is_owning_or_raw_pointer<row_type>();
|
||||
static constexpr int static_column_count = QRangeModelDetails::static_size_v<row_type>;
|
||||
static constexpr bool one_dimensional_range = static_column_count == 0;
|
||||
|
||||
static constexpr bool dynamicRows() { return isMutable() && static_row_count < 0; }
|
||||
@ -729,10 +729,10 @@ protected:
|
||||
using const_row_ptr = const wrapped_row_type *;
|
||||
|
||||
template <typename T>
|
||||
static constexpr bool has_metaobject = QGenericItemModelDetails::has_metaobject_v<
|
||||
static constexpr bool has_metaobject = QRangeModelDetails::has_metaobject_v<
|
||||
std::remove_pointer_t<std::remove_reference_t<T>>>;
|
||||
|
||||
using ModelData = QGenericItemModelDetails::ModelData<std::conditional_t<
|
||||
using ModelData = QRangeModelDetails::ModelData<std::conditional_t<
|
||||
std::is_pointer_v<Range>,
|
||||
Range, std::remove_reference_t<Range>>
|
||||
>;
|
||||
@ -769,15 +769,15 @@ protected:
|
||||
"The range holding a move-only row-type must support insert(pos, start, end)");
|
||||
|
||||
public:
|
||||
explicit QGenericItemModelImpl(Range &&model, Protocol&& protocol, QGenericItemModel *itemModel)
|
||||
: QGenericItemModelImplBase(itemModel, static_cast<const Self*>(nullptr))
|
||||
explicit QRangeModelImpl(Range &&model, Protocol&& protocol, QRangeModel *itemModel)
|
||||
: QRangeModelImplBase(itemModel, static_cast<const Self*>(nullptr))
|
||||
, m_data{std::forward<Range>(model)}
|
||||
, m_protocol(std::forward<Protocol>(protocol))
|
||||
{
|
||||
}
|
||||
|
||||
// static interface, called by QGenericItemModelImplBase
|
||||
static void callConst(ConstOp op, const QGenericItemModelImplBase *that, void *r, const void *args)
|
||||
// static interface, called by QRangeModelImplBase
|
||||
static void callConst(ConstOp op, const QRangeModelImplBase *that, void *r, const void *args)
|
||||
{
|
||||
switch (op) {
|
||||
case Index: makeCall(that, &Self::index, r, args);
|
||||
@ -801,7 +801,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
static void call(Op op, QGenericItemModelImplBase *that, void *r, const void *args)
|
||||
static void call(Op op, QRangeModelImplBase *that, void *r, const void *args)
|
||||
{
|
||||
switch (op) {
|
||||
case Destroy: delete static_cast<Structure *>(that);
|
||||
@ -878,7 +878,7 @@ public:
|
||||
// we didn't remove the const of the range first.
|
||||
const_row_reference row = rowData(index);
|
||||
row_reference mutableRow = const_cast<row_reference>(row);
|
||||
if (QGenericItemModelDetails::isValid(mutableRow)) {
|
||||
if (QRangeModelDetails::isValid(mutableRow)) {
|
||||
for_element_at(mutableRow, index.column(), [&f](auto &&ref){
|
||||
using target_type = decltype(ref);
|
||||
if constexpr (std::is_const_v<std::remove_reference_t<target_type>>)
|
||||
@ -928,13 +928,13 @@ public:
|
||||
const auto readData = [this, column = index.column(), &result, role](const auto &value) {
|
||||
Q_UNUSED(this);
|
||||
using value_type = q20::remove_cvref_t<decltype(value)>;
|
||||
using multi_role = QGenericItemModelDetails::is_multi_role<value_type>;
|
||||
using multi_role = QRangeModelDetails::is_multi_role<value_type>;
|
||||
if constexpr (has_metaobject<value_type>) {
|
||||
if (row_traits::fixed_size() <= 1) {
|
||||
result = readRole(role, QGenericItemModelDetails::pointerTo(value));
|
||||
result = readRole(role, QRangeModelDetails::pointerTo(value));
|
||||
} else if (column <= row_traits::fixed_size()
|
||||
&& (role == Qt::DisplayRole || role == Qt::EditRole)) {
|
||||
result = readProperty(column, QGenericItemModelDetails::pointerTo(value));
|
||||
result = readProperty(column, QRangeModelDetails::pointerTo(value));
|
||||
}
|
||||
} else if constexpr (multi_role::value) {
|
||||
const auto it = [this, &value, role]{
|
||||
@ -945,7 +945,7 @@ public:
|
||||
return std::as_const(value).find(roleNames().value(role));
|
||||
}();
|
||||
if (it != value.cend()) {
|
||||
result = QGenericItemModelDetails::value(it);
|
||||
result = QRangeModelDetails::value(it);
|
||||
}
|
||||
} else if (role == Qt::DisplayRole || role == Qt::EditRole) {
|
||||
result = read(value);
|
||||
@ -965,14 +965,14 @@ public:
|
||||
const auto readItemData = [this, &result, &tried](auto &&value){
|
||||
Q_UNUSED(this);
|
||||
using value_type = q20::remove_cvref_t<decltype(value)>;
|
||||
using multi_role = QGenericItemModelDetails::is_multi_role<value_type>;
|
||||
using multi_role = QRangeModelDetails::is_multi_role<value_type>;
|
||||
if constexpr (multi_role()) {
|
||||
tried = true;
|
||||
if constexpr (std::is_convertible_v<value_type, decltype(result)>) {
|
||||
result = value;
|
||||
} else {
|
||||
for (auto it = std::cbegin(value); it != std::cend(value); ++it) {
|
||||
int role = [this, key = QGenericItemModelDetails::key(it)]() {
|
||||
int role = [this, key = QRangeModelDetails::key(it)]() {
|
||||
Q_UNUSED(this);
|
||||
if constexpr (multi_role::int_key)
|
||||
return int(key);
|
||||
@ -981,13 +981,13 @@ public:
|
||||
}();
|
||||
|
||||
if (role != -1)
|
||||
result.insert(role, QGenericItemModelDetails::value(it));
|
||||
result.insert(role, QRangeModelDetails::value(it));
|
||||
}
|
||||
}
|
||||
} else if constexpr (has_metaobject<value_type>) {
|
||||
if (row_traits::fixed_size() <= 1) {
|
||||
tried = true;
|
||||
using meta_type = QGenericItemModelDetails::wrapped_t<value_type>;
|
||||
using meta_type = QRangeModelDetails::wrapped_t<value_type>;
|
||||
const QMetaObject &mo = meta_type::staticMetaObject;
|
||||
for (auto &&[role, roleName] : roleNames().asKeyValueRange()) {
|
||||
QVariant data;
|
||||
@ -999,7 +999,7 @@ public:
|
||||
if (pi >= 0) {
|
||||
const QMetaProperty prop = mo.property(pi);
|
||||
if (prop.isValid())
|
||||
data = prop.readOnGadget(QGenericItemModelDetails::pointerTo(value));
|
||||
data = prop.readOnGadget(QRangeModelDetails::pointerTo(value));
|
||||
}
|
||||
}
|
||||
if (data.isValid())
|
||||
@ -1034,7 +1034,7 @@ public:
|
||||
|
||||
const auto writeData = [this, column = index.column(), &data, role](auto &&target) -> bool {
|
||||
using value_type = q20::remove_cvref_t<decltype(target)>;
|
||||
using multi_role = QGenericItemModelDetails::is_multi_role<value_type>;
|
||||
using multi_role = QRangeModelDetails::is_multi_role<value_type>;
|
||||
if constexpr (has_metaobject<value_type>) {
|
||||
if (QMetaType::fromType<value_type>() == data.metaType()) {
|
||||
if constexpr (std::is_copy_assignable_v<value_type>) {
|
||||
@ -1045,10 +1045,10 @@ public:
|
||||
return false;
|
||||
}
|
||||
} else if (row_traits::fixed_size() <= 1) {
|
||||
return writeRole(role, QGenericItemModelDetails::pointerTo(target), data);
|
||||
return writeRole(role, QRangeModelDetails::pointerTo(target), data);
|
||||
} else if (column <= row_traits::fixed_size()
|
||||
&& (role == Qt::DisplayRole || role == Qt::EditRole)) {
|
||||
return writeProperty(column, QGenericItemModelDetails::pointerTo(target), data);
|
||||
return writeProperty(column, QRangeModelDetails::pointerTo(target), data);
|
||||
}
|
||||
} else if constexpr (multi_role::value) {
|
||||
Qt::ItemDataRole roleToSet = Qt::ItemDataRole(role);
|
||||
@ -1094,7 +1094,7 @@ public:
|
||||
auto writeItemData = [this, &tried, &data](auto &target) -> bool {
|
||||
Q_UNUSED(this);
|
||||
using value_type = q20::remove_cvref_t<decltype(target)>;
|
||||
using multi_role = QGenericItemModelDetails::is_multi_role<value_type>;
|
||||
using multi_role = QRangeModelDetails::is_multi_role<value_type>;
|
||||
if constexpr (multi_role()) {
|
||||
using key_type = typename value_type::key_type;
|
||||
tried = true;
|
||||
@ -1124,7 +1124,7 @@ public:
|
||||
} else if constexpr (has_metaobject<value_type>) {
|
||||
if (row_traits::fixed_size() <= 1) {
|
||||
tried = true;
|
||||
using meta_type = QGenericItemModelDetails::wrapped_t<value_type>;
|
||||
using meta_type = QRangeModelDetails::wrapped_t<value_type>;
|
||||
const QMetaObject &mo = meta_type::staticMetaObject;
|
||||
// transactional: if possible, modify a copy and only
|
||||
// update target if all values from data could be stored.
|
||||
@ -1149,7 +1149,7 @@ public:
|
||||
if (pi >= 0) {
|
||||
const QMetaProperty prop = mo.property(pi);
|
||||
if (prop.isValid())
|
||||
written = prop.writeOnGadget(QGenericItemModelDetails::pointerTo(targetCopy), value);
|
||||
written = prop.writeOnGadget(QRangeModelDetails::pointerTo(targetCopy), value);
|
||||
}
|
||||
}
|
||||
if (!written) {
|
||||
@ -1199,9 +1199,9 @@ public:
|
||||
if constexpr (has_metaobject<row_type>) {
|
||||
if (row_traits::fixed_size() <= 1) {
|
||||
// multi-role object/gadget: reset all properties
|
||||
return resetProperty(-1, QGenericItemModelDetails::pointerTo(target));
|
||||
return resetProperty(-1, QRangeModelDetails::pointerTo(target));
|
||||
} else if (column <= row_traits::fixed_size()) {
|
||||
return resetProperty(column, QGenericItemModelDetails::pointerTo(target));
|
||||
return resetProperty(column, QRangeModelDetails::pointerTo(target));
|
||||
}
|
||||
} else { // normal structs, values, associative containers
|
||||
target = {};
|
||||
@ -1226,8 +1226,8 @@ public:
|
||||
|
||||
beginInsertColumns(parent, column, column + count - 1);
|
||||
for (auto &child : *children) {
|
||||
auto it = QGenericItemModelDetails::pos(child, column);
|
||||
QGenericItemModelDetails::refTo(child).insert(it, count, {});
|
||||
auto it = QRangeModelDetails::pos(child, column);
|
||||
QRangeModelDetails::refTo(child).insert(it, count, {});
|
||||
}
|
||||
endInsertColumns();
|
||||
return true;
|
||||
@ -1247,8 +1247,8 @@ public:
|
||||
|
||||
beginRemoveColumns(parent, column, column + count - 1);
|
||||
for (auto &child : *children) {
|
||||
const auto start = QGenericItemModelDetails::pos(child, column);
|
||||
QGenericItemModelDetails::refTo(child).erase(start, std::next(start, count));
|
||||
const auto start = QRangeModelDetails::pos(child, column);
|
||||
QRangeModelDetails::refTo(child).erase(start, std::next(start, count));
|
||||
}
|
||||
endRemoveColumns();
|
||||
return true;
|
||||
@ -1279,9 +1279,9 @@ public:
|
||||
}
|
||||
|
||||
for (auto &child : *children) {
|
||||
const auto first = QGenericItemModelDetails::pos(child, sourceColumn);
|
||||
const auto first = QRangeModelDetails::pos(child, sourceColumn);
|
||||
const auto middle = std::next(first, count);
|
||||
const auto last = QGenericItemModelDetails::pos(child, destColumn);
|
||||
const auto last = QRangeModelDetails::pos(child, destColumn);
|
||||
|
||||
if (sourceColumn < destColumn) // moving right
|
||||
std::rotate(first, middle, last);
|
||||
@ -1307,7 +1307,7 @@ public:
|
||||
|
||||
beginInsertRows(parent, row, row + count - 1);
|
||||
|
||||
const auto pos = QGenericItemModelDetails::pos(children, row);
|
||||
const auto pos = QRangeModelDetails::pos(children, row);
|
||||
if constexpr (range_features::has_insert_range) {
|
||||
children->insert(pos, generator, EmptyRowGenerator{count});
|
||||
} else if constexpr (rows_are_owning_or_raw_pointers) {
|
||||
@ -1352,7 +1352,7 @@ public:
|
||||
}
|
||||
}
|
||||
{ // erase invalidates iterators
|
||||
const auto begin = QGenericItemModelDetails::pos(children, row);
|
||||
const auto begin = QRangeModelDetails::pos(children, row);
|
||||
const auto end = std::next(begin, count);
|
||||
that().deleteRemovedRows(begin, end);
|
||||
children->erase(begin, end);
|
||||
@ -1397,9 +1397,9 @@ public:
|
||||
if (!beginMoveRows(sourceParent, sourceRow, sourceRow + count - 1, destParent, destRow))
|
||||
return false;
|
||||
|
||||
const auto first = QGenericItemModelDetails::pos(source, sourceRow);
|
||||
const auto first = QRangeModelDetails::pos(source, sourceRow);
|
||||
const auto middle = std::next(first, count);
|
||||
const auto last = QGenericItemModelDetails::pos(source, destRow);
|
||||
const auto last = QRangeModelDetails::pos(source, destRow);
|
||||
|
||||
if (sourceRow < destRow) // moving down
|
||||
std::rotate(first, middle, last);
|
||||
@ -1416,7 +1416,7 @@ public:
|
||||
}
|
||||
|
||||
protected:
|
||||
~QGenericItemModelImpl()
|
||||
~QRangeModelImpl()
|
||||
{
|
||||
// We delete row objects if we are not operating on a reference or pointer
|
||||
// to a range, as in that case, the owner of the referenced/pointed to
|
||||
@ -1426,9 +1426,9 @@ protected:
|
||||
// client can never delete those. But copied rows will be the same pointer,
|
||||
// which we must not delete (as we didn't create them).
|
||||
if constexpr (protocol_traits::has_deleteRow && !std::is_pointer_v<Range>
|
||||
&& !QGenericItemModelDetails::is_any_of<Range, std::reference_wrapper>()) {
|
||||
const auto begin = QGenericItemModelDetails::begin(*m_data.model());
|
||||
const auto end = QGenericItemModelDetails::end(*m_data.model());
|
||||
&& !QRangeModelDetails::is_any_of<Range, std::reference_wrapper>()) {
|
||||
const auto begin = QRangeModelDetails::begin(*m_data.model());
|
||||
const auto end = QRangeModelDetails::end(*m_data.model());
|
||||
that().deleteRemovedRows(begin, end);
|
||||
}
|
||||
}
|
||||
@ -1461,9 +1461,9 @@ protected:
|
||||
|
||||
if constexpr (one_dimensional_range) {
|
||||
result = writer(row);
|
||||
} else if (QGenericItemModelDetails::isValid(row)) {
|
||||
} else if (QRangeModelDetails::isValid(row)) {
|
||||
if constexpr (dynamicColumns()) {
|
||||
result = writer(*QGenericItemModelDetails::pos(row, index.column()));
|
||||
result = writer(*QRangeModelDetails::pos(row, index.column()));
|
||||
} else {
|
||||
for_element_at(row, index.column(), [&writer, &result](auto &&target) {
|
||||
using target_type = decltype(target);
|
||||
@ -1484,9 +1484,9 @@ protected:
|
||||
const_row_reference row = rowData(index);
|
||||
if constexpr (one_dimensional_range) {
|
||||
return reader(row);
|
||||
} else if (QGenericItemModelDetails::isValid(row)) {
|
||||
} else if (QRangeModelDetails::isValid(row)) {
|
||||
if constexpr (dynamicColumns())
|
||||
reader(*QGenericItemModelDetails::cpos(row, index.column()));
|
||||
reader(*QRangeModelDetails::cpos(row, index.column()));
|
||||
else
|
||||
for_element_at(row, index.column(), std::forward<F>(reader));
|
||||
}
|
||||
@ -1683,8 +1683,8 @@ protected:
|
||||
}
|
||||
|
||||
|
||||
const protocol_type& protocol() const { return QGenericItemModelDetails::refTo(m_protocol); }
|
||||
protocol_type& protocol() { return QGenericItemModelDetails::refTo(m_protocol); }
|
||||
const protocol_type& protocol() const { return QRangeModelDetails::refTo(m_protocol); }
|
||||
protocol_type& protocol() { return QRangeModelDetails::refTo(m_protocol); }
|
||||
|
||||
ModelData m_data;
|
||||
Protocol m_protocol;
|
||||
@ -1695,10 +1695,10 @@ protected:
|
||||
// support through a protocol type.
|
||||
template <typename Range, typename Protocol>
|
||||
class QGenericTreeItemModelImpl
|
||||
: public QGenericItemModelImpl<QGenericTreeItemModelImpl<Range, Protocol>, Range, Protocol>
|
||||
: public QRangeModelImpl<QGenericTreeItemModelImpl<Range, Protocol>, Range, Protocol>
|
||||
{
|
||||
using Base = QGenericItemModelImpl<QGenericTreeItemModelImpl<Range, Protocol>, Range, Protocol>;
|
||||
friend class QGenericItemModelImpl<QGenericTreeItemModelImpl<Range, Protocol>, Range, Protocol>;
|
||||
using Base = QRangeModelImpl<QGenericTreeItemModelImpl<Range, Protocol>, Range, Protocol>;
|
||||
friend class QRangeModelImpl<QGenericTreeItemModelImpl<Range, Protocol>, Range, Protocol>;
|
||||
|
||||
using range_type = typename Base::range_type;
|
||||
using range_features = typename Base::range_features;
|
||||
@ -1710,12 +1710,12 @@ class QGenericTreeItemModelImpl
|
||||
static constexpr bool is_mutable_impl = tree_traits::has_mutable_childRows;
|
||||
|
||||
static constexpr bool rows_are_any_refs_or_pointers = Base::rows_are_raw_pointers ||
|
||||
QGenericItemModelDetails::is_smart_ptr<row_type>() ||
|
||||
QGenericItemModelDetails::is_any_of<row_type, std::reference_wrapper>();
|
||||
QRangeModelDetails::is_smart_ptr<row_type>() ||
|
||||
QRangeModelDetails::is_any_of<row_type, std::reference_wrapper>();
|
||||
static_assert(!Base::dynamicColumns(), "A tree must have a static number of columns!");
|
||||
|
||||
public:
|
||||
QGenericTreeItemModelImpl(Range &&model, Protocol &&p, QGenericItemModel *itemModel)
|
||||
QGenericTreeItemModelImpl(Range &&model, Protocol &&p, QRangeModel *itemModel)
|
||||
: Base(std::forward<Range>(model), std::forward<Protocol>(p), itemModel)
|
||||
{};
|
||||
|
||||
@ -1730,8 +1730,8 @@ protected:
|
||||
|
||||
const_row_ptr grandParent = static_cast<const_row_ptr>(parent.constInternalPointer());
|
||||
const auto &parentSiblings = childrenOf(grandParent);
|
||||
const auto it = QGenericItemModelDetails::cpos(parentSiblings, parent.row());
|
||||
return this->createIndex(row, column, QGenericItemModelDetails::pointerTo(*it));
|
||||
const auto it = QRangeModelDetails::cpos(parentSiblings, parent.row());
|
||||
return this->createIndex(row, column, QRangeModelDetails::pointerTo(*it));
|
||||
}
|
||||
|
||||
QModelIndex parent(const QModelIndex &child) const
|
||||
@ -1745,17 +1745,17 @@ protected:
|
||||
return {};
|
||||
|
||||
// get the siblings of the parent via the grand parent
|
||||
decltype(auto) grandParent = this->protocol().parentRow(QGenericItemModelDetails::refTo(parentRow));
|
||||
const range_type &parentSiblings = childrenOf(QGenericItemModelDetails::pointerTo(grandParent));
|
||||
decltype(auto) grandParent = this->protocol().parentRow(QRangeModelDetails::refTo(parentRow));
|
||||
const range_type &parentSiblings = childrenOf(QRangeModelDetails::pointerTo(grandParent));
|
||||
// find the index of parentRow
|
||||
const auto begin = QGenericItemModelDetails::cbegin(parentSiblings);
|
||||
const auto end = QGenericItemModelDetails::cend(parentSiblings);
|
||||
const auto begin = QRangeModelDetails::cbegin(parentSiblings);
|
||||
const auto end = QRangeModelDetails::cend(parentSiblings);
|
||||
const auto it = std::find_if(begin, end, [parentRow](auto &&s){
|
||||
return QGenericItemModelDetails::pointerTo(s) == parentRow;
|
||||
return QRangeModelDetails::pointerTo(s) == parentRow;
|
||||
});
|
||||
if (it != end)
|
||||
return this->createIndex(std::distance(begin, it), 0,
|
||||
QGenericItemModelDetails::pointerTo(grandParent));
|
||||
QRangeModelDetails::pointerTo(grandParent));
|
||||
return {};
|
||||
}
|
||||
|
||||
@ -1826,9 +1826,9 @@ protected:
|
||||
|
||||
// If we can insert data from another range into, then
|
||||
// use that to move the old data over.
|
||||
const auto destStart = QGenericItemModelDetails::pos(destination, destRow);
|
||||
const auto destStart = QRangeModelDetails::pos(destination, destRow);
|
||||
if constexpr (range_features::has_insert_range) {
|
||||
const auto sourceStart = QGenericItemModelDetails::pos(*source, sourceRow);
|
||||
const auto sourceStart = QRangeModelDetails::pos(*source, sourceRow);
|
||||
const auto sourceEnd = std::next(sourceStart, count);
|
||||
|
||||
destination->insert(destStart, std::move_iterator(sourceStart),
|
||||
@ -1839,7 +1839,7 @@ protected:
|
||||
}
|
||||
|
||||
row_ptr parentRow = destParent.isValid()
|
||||
? QGenericItemModelDetails::pointerTo(this->rowData(destParent))
|
||||
? QRangeModelDetails::pointerTo(this->rowData(destParent))
|
||||
: nullptr;
|
||||
|
||||
// if the source's parent was already inside the new parent row,
|
||||
@ -1856,9 +1856,9 @@ protected:
|
||||
|
||||
// move the data over and update the parent pointer
|
||||
{
|
||||
const auto writeStart = QGenericItemModelDetails::pos(destination, destRow);
|
||||
const auto writeStart = QRangeModelDetails::pos(destination, destRow);
|
||||
const auto writeEnd = std::next(writeStart, count);
|
||||
const auto sourceStart = QGenericItemModelDetails::pos(source, sourceRow);
|
||||
const auto sourceStart = QRangeModelDetails::pos(source, sourceRow);
|
||||
const auto sourceEnd = std::next(sourceStart, count);
|
||||
|
||||
for (auto write = writeStart, read = sourceStart; write != writeEnd; ++write, ++read) {
|
||||
@ -1866,7 +1866,7 @@ protected:
|
||||
// only fix the parent pointer
|
||||
if constexpr (!range_features::has_insert_range)
|
||||
*write = std::move(*read);
|
||||
this->protocol().setParentRow(QGenericItemModelDetails::refTo(*write), parentRow);
|
||||
this->protocol().setParentRow(QRangeModelDetails::refTo(*write), parentRow);
|
||||
}
|
||||
// remove the old rows from the source parent
|
||||
source->erase(sourceStart, sourceEnd);
|
||||
@ -1889,9 +1889,9 @@ protected:
|
||||
// to change the parent of a row.
|
||||
static_assert(tree_traits::has_setParentRow);
|
||||
row_type empty_row = this->protocol().newRow();
|
||||
if (QGenericItemModelDetails::isValid(empty_row) && parent.isValid()) {
|
||||
this->protocol().setParentRow(QGenericItemModelDetails::refTo(empty_row),
|
||||
QGenericItemModelDetails::pointerTo(this->rowData(parent)));
|
||||
if (QRangeModelDetails::isValid(empty_row) && parent.isValid()) {
|
||||
this->protocol().setParentRow(QRangeModelDetails::refTo(empty_row),
|
||||
QRangeModelDetails::pointerTo(this->rowData(parent)));
|
||||
}
|
||||
return empty_row;
|
||||
}
|
||||
@ -1908,15 +1908,15 @@ protected:
|
||||
void resetParentInChildren(range_type *children)
|
||||
{
|
||||
if constexpr (tree_traits::has_setParentRow && !rows_are_any_refs_or_pointers) {
|
||||
const auto begin = QGenericItemModelDetails::begin(*children);
|
||||
const auto end = QGenericItemModelDetails::end(*children);
|
||||
const auto begin = QRangeModelDetails::begin(*children);
|
||||
const auto end = QRangeModelDetails::end(*children);
|
||||
for (auto it = begin; it != end; ++it) {
|
||||
if (auto &maybeChildren = this->protocol().childRows(*it)) {
|
||||
QModelIndexList fromIndexes;
|
||||
QModelIndexList toIndexes;
|
||||
fromIndexes.reserve(Base::size(*maybeChildren));
|
||||
toIndexes.reserve(Base::size(*maybeChildren));
|
||||
auto *parentRow = QGenericItemModelDetails::pointerTo(*it);
|
||||
auto *parentRow = QRangeModelDetails::pointerTo(*it);
|
||||
|
||||
int row = 0;
|
||||
for (auto &child : *maybeChildren) {
|
||||
@ -1929,7 +1929,7 @@ protected:
|
||||
++row;
|
||||
}
|
||||
this->changePersistentIndexList(fromIndexes, toIndexes);
|
||||
resetParentInChildren(QGenericItemModelDetails::pointerTo(*maybeChildren));
|
||||
resetParentInChildren(QRangeModelDetails::pointerTo(*maybeChildren));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1940,7 +1940,7 @@ protected:
|
||||
const_row_ptr parentRow = static_cast<const_row_ptr>(index.constInternalPointer());
|
||||
const range_type &siblings = childrenOf(parentRow);
|
||||
Q_ASSERT(index.row() < int(Base::size(siblings)));
|
||||
return *QGenericItemModelDetails::cpos(siblings, index.row());
|
||||
return *QRangeModelDetails::cpos(siblings, index.row());
|
||||
}
|
||||
|
||||
decltype(auto) rowDataImpl(const QModelIndex &index)
|
||||
@ -1948,47 +1948,47 @@ protected:
|
||||
row_ptr parentRow = static_cast<row_ptr>(index.internalPointer());
|
||||
range_type &siblings = childrenOf(parentRow);
|
||||
Q_ASSERT(index.row() < int(Base::size(siblings)));
|
||||
return *QGenericItemModelDetails::pos(siblings, index.row());
|
||||
return *QRangeModelDetails::pos(siblings, index.row());
|
||||
}
|
||||
|
||||
const range_type *childRangeImpl(const QModelIndex &index) const
|
||||
{
|
||||
const auto &row = this->rowData(index);
|
||||
if (!QGenericItemModelDetails::isValid(row))
|
||||
if (!QRangeModelDetails::isValid(row))
|
||||
return static_cast<const range_type *>(nullptr);
|
||||
|
||||
decltype(auto) children = this->protocol().childRows(QGenericItemModelDetails::refTo(row));
|
||||
return QGenericItemModelDetails::pointerTo(std::forward<decltype(children)>(children));
|
||||
decltype(auto) children = this->protocol().childRows(QRangeModelDetails::refTo(row));
|
||||
return QRangeModelDetails::pointerTo(std::forward<decltype(children)>(children));
|
||||
}
|
||||
|
||||
range_type *childRangeImpl(const QModelIndex &index)
|
||||
{
|
||||
auto &row = this->rowData(index);
|
||||
if (!QGenericItemModelDetails::isValid(row))
|
||||
if (!QRangeModelDetails::isValid(row))
|
||||
return static_cast<range_type *>(nullptr);
|
||||
|
||||
decltype(auto) children = this->protocol().childRows(QGenericItemModelDetails::refTo(row));
|
||||
decltype(auto) children = this->protocol().childRows(QRangeModelDetails::refTo(row));
|
||||
using Children = std::remove_reference_t<decltype(children)>;
|
||||
|
||||
if constexpr (QGenericItemModelDetails::is_any_of<Children, std::optional>()
|
||||
if constexpr (QRangeModelDetails::is_any_of<Children, std::optional>()
|
||||
&& std::is_default_constructible<typename Children::value_type>()) {
|
||||
if (!children)
|
||||
children.emplace(range_type{});
|
||||
}
|
||||
|
||||
return QGenericItemModelDetails::pointerTo(std::forward<decltype(children)>(children));
|
||||
return QRangeModelDetails::pointerTo(std::forward<decltype(children)>(children));
|
||||
}
|
||||
|
||||
const range_type &childrenOf(const_row_ptr row) const
|
||||
{
|
||||
return row ? QGenericItemModelDetails::refTo(this->protocol().childRows(*row))
|
||||
return row ? QRangeModelDetails::refTo(this->protocol().childRows(*row))
|
||||
: *this->m_data.model();
|
||||
}
|
||||
|
||||
private:
|
||||
range_type &childrenOf(row_ptr row)
|
||||
{
|
||||
return row ? QGenericItemModelDetails::refTo(this->protocol().childRows(*row))
|
||||
return row ? QRangeModelDetails::refTo(this->protocol().childRows(*row))
|
||||
: *this->m_data.model();
|
||||
}
|
||||
};
|
||||
@ -1996,10 +1996,10 @@ private:
|
||||
// specialization for flat models without protocol
|
||||
template <typename Range>
|
||||
class QGenericTableItemModelImpl
|
||||
: public QGenericItemModelImpl<QGenericTableItemModelImpl<Range>, Range>
|
||||
: public QRangeModelImpl<QGenericTableItemModelImpl<Range>, Range>
|
||||
{
|
||||
using Base = QGenericItemModelImpl<QGenericTableItemModelImpl<Range>, Range>;
|
||||
friend class QGenericItemModelImpl<QGenericTableItemModelImpl<Range>, Range>;
|
||||
using Base = QRangeModelImpl<QGenericTableItemModelImpl<Range>, Range>;
|
||||
friend class QRangeModelImpl<QGenericTableItemModelImpl<Range>, Range>;
|
||||
|
||||
using range_type = typename Base::range_type;
|
||||
using range_features = typename Base::range_features;
|
||||
@ -2011,7 +2011,7 @@ class QGenericTableItemModelImpl
|
||||
static constexpr bool is_mutable_impl = true;
|
||||
|
||||
public:
|
||||
explicit QGenericTableItemModelImpl(Range &&model, QGenericItemModel *itemModel)
|
||||
explicit QGenericTableItemModelImpl(Range &&model, QRangeModel *itemModel)
|
||||
: Base(std::forward<Range>(model), {}, itemModel)
|
||||
{}
|
||||
|
||||
@ -2019,10 +2019,10 @@ protected:
|
||||
QModelIndex indexImpl(int row, int column, const QModelIndex &) const
|
||||
{
|
||||
if constexpr (Base::dynamicColumns()) {
|
||||
if (column < int(Base::size(*QGenericItemModelDetails::cpos(*this->m_data.model(), row))))
|
||||
if (column < int(Base::size(*QRangeModelDetails::cpos(*this->m_data.model(), row))))
|
||||
return this->createIndex(row, column);
|
||||
// if we got here, then column < columnCount(), but this row is to short
|
||||
qCritical("QGenericItemModel: Column-range at row %d is not large enough!", row);
|
||||
qCritical("QRangeModel: Column-range at row %d is not large enough!", row);
|
||||
return {};
|
||||
} else {
|
||||
return this->createIndex(row, column);
|
||||
@ -2050,7 +2050,7 @@ protected:
|
||||
if constexpr (Base::dynamicColumns()) {
|
||||
return int(Base::size(*this->m_data.model()) == 0
|
||||
? 0
|
||||
: Base::size(*QGenericItemModelDetails::cbegin(*this->m_data.model())));
|
||||
: Base::size(*QRangeModelDetails::cbegin(*this->m_data.model())));
|
||||
} else if constexpr (Base::one_dimensional_range) {
|
||||
return row_traits::fixed_size();
|
||||
} else {
|
||||
@ -2096,8 +2096,8 @@ protected:
|
||||
|
||||
// dynamically sized rows all have to have the same column count
|
||||
if constexpr (Base::dynamicColumns() && row_features::has_resize) {
|
||||
if (QGenericItemModelDetails::isValid(empty_row))
|
||||
QGenericItemModelDetails::refTo(empty_row).resize(this->itemModel().columnCount());
|
||||
if (QRangeModelDetails::isValid(empty_row))
|
||||
QRangeModelDetails::refTo(empty_row).resize(this->itemModel().columnCount());
|
||||
}
|
||||
|
||||
return empty_row;
|
||||
@ -2115,13 +2115,13 @@ protected:
|
||||
decltype(auto) rowDataImpl(const QModelIndex &index) const
|
||||
{
|
||||
Q_ASSERT(index.row() < int(Base::size(*this->m_data.model())));
|
||||
return *QGenericItemModelDetails::cpos(*this->m_data.model(), index.row());
|
||||
return *QRangeModelDetails::cpos(*this->m_data.model(), index.row());
|
||||
}
|
||||
|
||||
decltype(auto) rowDataImpl(const QModelIndex &index)
|
||||
{
|
||||
Q_ASSERT(index.row() < int(Base::size(*this->m_data.model())));
|
||||
return *QGenericItemModelDetails::pos(*this->m_data.model(), index.row());
|
||||
return *QRangeModelDetails::pos(*this->m_data.model(), index.row());
|
||||
}
|
||||
|
||||
auto childRangeImpl(const QModelIndex &) const
|
||||
@ -2149,4 +2149,4 @@ QT_END_NAMESPACE
|
||||
|
||||
#endif // Q_QDOC
|
||||
|
||||
#endif // QGENERICITEMMODEL_IMPL_H
|
||||
#endif // QRANGEMODEL_IMPL_H
|
@ -2,7 +2,7 @@
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
add_subdirectory(qstringlistmodel)
|
||||
add_subdirectory(qgenericitemmodel)
|
||||
add_subdirectory(qrangemodel)
|
||||
if(TARGET Qt::Gui)
|
||||
add_subdirectory(qabstractitemmodel)
|
||||
if(QT_FEATURE_proxymodel)
|
||||
|
@ -2,18 +2,18 @@
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
#####################################################################
|
||||
## tst_qgenericitemmodel Test:
|
||||
## tst_qrangemodel Test:
|
||||
#####################################################################
|
||||
|
||||
if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
project(tst_qgenericitemmodel LANGUAGES CXX)
|
||||
project(tst_qrangemodel LANGUAGES CXX)
|
||||
find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
|
||||
endif()
|
||||
|
||||
qt_internal_add_test(tst_qgenericitemmodel
|
||||
qt_internal_add_test(tst_qrangemodel
|
||||
SOURCES
|
||||
tst_qgenericitemmodel.cpp
|
||||
tst_qrangemodel.cpp
|
||||
LIBRARIES
|
||||
Qt::Gui
|
||||
)
|
||||
@ -24,6 +24,6 @@ if (
|
||||
# gcc 10.2.0 chokes in a standard library header
|
||||
(NOT CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 10.2.0))
|
||||
if ("${CMAKE_CXX_COMPILE_FEATURES}" MATCHES "cxx_std_20")
|
||||
set_property(TARGET tst_qgenericitemmodel PROPERTY CXX_STANDARD 20)
|
||||
set_property(TARGET tst_qrangemodel PROPERTY CXX_STANDARD 20)
|
||||
endif()
|
||||
endif()
|
@ -2,7 +2,7 @@
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
|
||||
|
||||
#include <QTest>
|
||||
#include <QtCore/qgenericitemmodel.h>
|
||||
#include <QtCore/qrangemodel.h>
|
||||
#include <QtCore/qjsondocument.h>
|
||||
#include <QtCore/qjsonarray.h>
|
||||
|
||||
@ -273,7 +273,7 @@ namespace std {
|
||||
{ using type = decltype(get<I>(std::declval<tree_row>())); };
|
||||
}
|
||||
|
||||
class tst_QGenericItemModel : public QObject
|
||||
class tst_QRangeModel : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
@ -459,7 +459,7 @@ private:
|
||||
{"green", Qt::green, "0x00ff00"},
|
||||
{"blue", Qt::blue, "0x0000ff"},
|
||||
};
|
||||
std::vector<QGenericItemModel::SingleColumn<Item>> listOfGadgets = {
|
||||
std::vector<QRangeModel::SingleColumn<Item>> listOfGadgets = {
|
||||
{{"red", Qt::red, "0xff0000"}},
|
||||
{{"green", Qt::green, "0x00ff00"}},
|
||||
{{"blue", Qt::blue, "0x0000ff"}},
|
||||
@ -480,7 +480,7 @@ private:
|
||||
MetaObjectTuple mot1;
|
||||
MetaObjectTuple mot2;
|
||||
MetaObjectTuple mot3;
|
||||
std::vector<QGenericItemModel::SingleColumn<MetaObjectTuple *>> listOfMetaObjectTuple = {
|
||||
std::vector<QRangeModel::SingleColumn<MetaObjectTuple *>> listOfMetaObjectTuple = {
|
||||
&mot1,
|
||||
&mot2,
|
||||
&mot3,
|
||||
@ -488,7 +488,7 @@ private:
|
||||
MetaObjectTuple mot4;
|
||||
MetaObjectTuple mot5;
|
||||
MetaObjectTuple mot6;
|
||||
std::vector<QGenericItemModel::MultiColumn<MetaObjectTuple *>> tableOfMetaObjectTuple = {
|
||||
std::vector<QRangeModel::MultiColumn<MetaObjectTuple *>> tableOfMetaObjectTuple = {
|
||||
{&mot4},
|
||||
{&mot5},
|
||||
{&mot6},
|
||||
@ -613,7 +613,7 @@ public:
|
||||
Q_DECLARE_FLAGS(ChangeActions, ChangeAction);
|
||||
};
|
||||
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(tst_QGenericItemModel::ChangeActions)
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(tst_QRangeModel::ChangeActions)
|
||||
|
||||
using Factory = std::function<std::unique_ptr<QAbstractItemModel>()>;
|
||||
|
||||
@ -629,7 +629,7 @@ void createBackup(QObject* object, T& model) {
|
||||
template <typename T, std::enable_if_t<!std::is_copy_assignable_v<T>, bool> = true>
|
||||
void createBackup(QObject* , T& ) {}
|
||||
|
||||
void tst_QGenericItemModel::createTestData()
|
||||
void tst_QRangeModel::createTestData()
|
||||
{
|
||||
m_data.reset(new Data);
|
||||
|
||||
@ -643,7 +643,7 @@ void tst_QGenericItemModel::createTestData()
|
||||
#define ADD_HELPER(Model, Tag, Policy, ColumnCount, Actions) \
|
||||
{ \
|
||||
Factory factory = [this]() -> std::unique_ptr<QAbstractItemModel> { \
|
||||
auto result = std::make_unique<QGenericItemModel>(Policy(m_data->Model)); \
|
||||
auto result = std::make_unique<QRangeModel>(Policy(m_data->Model)); \
|
||||
createBackup(result.get(), m_data->Model); \
|
||||
return result; \
|
||||
}; \
|
||||
@ -735,7 +735,7 @@ void tst_QGenericItemModel::createTestData()
|
||||
{"2/0", "2/1", "2/2", "2/3"},
|
||||
{"3/0", "3/1", "3/2", "3/3"},
|
||||
};
|
||||
return std::unique_ptr<QAbstractItemModel>(new QGenericItemModel(std::move(movedTable)));
|
||||
return std::unique_ptr<QAbstractItemModel>(new QRangeModel(std::move(movedTable)));
|
||||
}) << 4 << 4 << ChangeActions(ChangeAction::All);
|
||||
|
||||
// moved list of pointers -> model takes ownership
|
||||
@ -746,25 +746,25 @@ void tst_QGenericItemModel::createTestData()
|
||||
};
|
||||
|
||||
return std::unique_ptr<QAbstractItemModel>(
|
||||
new QGenericItemModel(std::move(movedListOfObjects))
|
||||
new QRangeModel(std::move(movedListOfObjects))
|
||||
);
|
||||
}) << 6 << 2 << (ChangeAction::ChangeRows | ChangeAction::SetData);
|
||||
|
||||
// special case: tree
|
||||
QTest::addRow("value tree (ref)") << Factory([this]{
|
||||
return std::unique_ptr<QAbstractItemModel>(new QGenericItemModel(std::ref(*m_data->m_tree)));
|
||||
return std::unique_ptr<QAbstractItemModel>(new QRangeModel(std::ref(*m_data->m_tree)));
|
||||
}) << int(std::size(*m_data->m_tree.get())) << int(std::tuple_size_v<tree_row>)
|
||||
<< (ChangeAction::ChangeRows | ChangeAction::SetData);
|
||||
|
||||
QTest::addRow("pointer tree") << Factory([this]{
|
||||
return std::unique_ptr<QAbstractItemModel>(
|
||||
new QGenericItemModel(m_data->m_pointer_tree.get(), tree_row::ProtocolPointerImpl{})
|
||||
new QRangeModel(m_data->m_pointer_tree.get(), tree_row::ProtocolPointerImpl{})
|
||||
);
|
||||
}) << int(std::size(*m_data->m_pointer_tree.get())) << int(std::tuple_size_v<tree_row>)
|
||||
<< (ChangeAction::ChangeRows | ChangeAction::SetData);
|
||||
}
|
||||
|
||||
void tst_QGenericItemModel::basics()
|
||||
void tst_QRangeModel::basics()
|
||||
{
|
||||
#if QT_CONFIG(itemmodeltester)
|
||||
QFETCH(Factory, factory);
|
||||
@ -778,25 +778,25 @@ void tst_QGenericItemModel::basics()
|
||||
|
||||
using ModelFromData = std::function<std::unique_ptr<QAbstractItemModel>(std::vector<int> &)>;
|
||||
|
||||
void tst_QGenericItemModel::modifies_data()
|
||||
void tst_QRangeModel::modifies_data()
|
||||
{
|
||||
QTest::addColumn<ModelFromData>("modelFromData");
|
||||
QTest::addColumn<bool>("modifiesOriginal");
|
||||
|
||||
QTest::newRow("copy") << ModelFromData([](std::vector<int> &numbers){
|
||||
return std::unique_ptr<QAbstractItemModel>(new QGenericItemModel(numbers));
|
||||
return std::unique_ptr<QAbstractItemModel>(new QRangeModel(numbers));
|
||||
}) << false;
|
||||
|
||||
QTest::newRow("reference_wrapper") << ModelFromData([](std::vector<int> &numbers){
|
||||
return std::unique_ptr<QAbstractItemModel>(new QGenericItemModel(std::ref(numbers)));
|
||||
return std::unique_ptr<QAbstractItemModel>(new QRangeModel(std::ref(numbers)));
|
||||
}) << true;
|
||||
|
||||
QTest::newRow("pointer") << ModelFromData([](std::vector<int> &numbers){
|
||||
return std::unique_ptr<QAbstractItemModel>(new QGenericItemModel(&numbers));
|
||||
return std::unique_ptr<QAbstractItemModel>(new QRangeModel(&numbers));
|
||||
}) << true;
|
||||
}
|
||||
|
||||
void tst_QGenericItemModel::modifies()
|
||||
void tst_QRangeModel::modifies()
|
||||
{
|
||||
QFETCH(ModelFromData, modelFromData);
|
||||
QFETCH(bool, modifiesOriginal);
|
||||
@ -824,7 +824,7 @@ void tst_QGenericItemModel::modifies()
|
||||
}
|
||||
}
|
||||
|
||||
void tst_QGenericItemModel::minimalIterator()
|
||||
void tst_QRangeModel::minimalIterator()
|
||||
{
|
||||
struct Minimal
|
||||
{
|
||||
@ -861,7 +861,7 @@ void tst_QGenericItemModel::minimalIterator()
|
||||
int m_size;
|
||||
} minimal{100};
|
||||
|
||||
QGenericItemModel model(minimal);
|
||||
QRangeModel model(minimal);
|
||||
QCOMPARE(model.rowCount(), minimal.m_size);
|
||||
for (int row = model.rowCount() - 1; row >= 0; --row) {
|
||||
const QModelIndex index = model.index(row, 0);
|
||||
@ -870,12 +870,12 @@ void tst_QGenericItemModel::minimalIterator()
|
||||
}
|
||||
}
|
||||
|
||||
void tst_QGenericItemModel::ranges()
|
||||
void tst_QRangeModel::ranges()
|
||||
{
|
||||
#if defined(__cpp_lib_ranges)
|
||||
const int lowest = 1;
|
||||
const int highest = 10;
|
||||
QGenericItemModel model(std::views::iota(lowest, highest));
|
||||
QRangeModel model(std::views::iota(lowest, highest));
|
||||
QCOMPARE(model.rowCount(), highest - lowest);
|
||||
QCOMPARE(model.columnCount(), 1);
|
||||
#else
|
||||
@ -883,18 +883,18 @@ void tst_QGenericItemModel::ranges()
|
||||
#endif
|
||||
}
|
||||
|
||||
void tst_QGenericItemModel::json()
|
||||
void tst_QRangeModel::json()
|
||||
{
|
||||
QJsonDocument json = QJsonDocument::fromJson(R"([ "one", "two" ])");
|
||||
QVERIFY(json.isArray());
|
||||
QGenericItemModel model(json.array());
|
||||
QRangeModel model(json.array());
|
||||
QCOMPARE(model.rowCount(), 2);
|
||||
const QModelIndex index = model.index(1, 0);
|
||||
QVERIFY(index.isValid());
|
||||
QCOMPARE(index.data().toString(), "two");
|
||||
}
|
||||
|
||||
void tst_QGenericItemModel::ownership()
|
||||
void tst_QRangeModel::ownership()
|
||||
{
|
||||
{ // a list of pointers to objects
|
||||
Object *object = new Object;
|
||||
@ -903,22 +903,22 @@ void tst_QGenericItemModel::ownership()
|
||||
object
|
||||
};
|
||||
{ // model takes ownership of its own copy of the vector (!)
|
||||
QGenericItemModel modelOnCopy(objects);
|
||||
QRangeModel modelOnCopy(objects);
|
||||
}
|
||||
QVERIFY(!guard);
|
||||
objects[0] = new Object;
|
||||
guard = objects[0];
|
||||
{ // model does not take ownership
|
||||
QGenericItemModel modelOnPointer(&objects);
|
||||
QRangeModel modelOnPointer(&objects);
|
||||
}
|
||||
QVERIFY(guard);
|
||||
{ // model does not take ownership
|
||||
QGenericItemModel modelOnRef(std::ref(objects));
|
||||
QRangeModel modelOnRef(std::ref(objects));
|
||||
}
|
||||
QVERIFY(guard);
|
||||
|
||||
{ // model does take ownership
|
||||
QGenericItemModel movedIntoModel(std::move(objects));
|
||||
QRangeModel movedIntoModel(std::move(objects));
|
||||
QCOMPARE(movedIntoModel.columnCount(), 2);
|
||||
}
|
||||
QVERIFY(!guard);
|
||||
@ -932,25 +932,25 @@ void tst_QGenericItemModel::ownership()
|
||||
};
|
||||
{ // model does not take ownership
|
||||
QCOMPARE(objects[0].use_count(), 1);
|
||||
QGenericItemModel modelOnCopy(objects);
|
||||
QRangeModel modelOnCopy(objects);
|
||||
QCOMPARE(modelOnCopy.rowCount(), 1);
|
||||
QCOMPARE(objects[0].use_count(), 2);
|
||||
}
|
||||
QCOMPARE(objects[0].use_count(), 1);
|
||||
{ // model does not take ownership
|
||||
QGenericItemModel modelOnPointer(&objects);
|
||||
QRangeModel modelOnPointer(&objects);
|
||||
QCOMPARE(objects[0].use_count(), 1);
|
||||
}
|
||||
QCOMPARE(objects[0].use_count(), 1);
|
||||
QVERIFY(guard);
|
||||
{ // model does not take ownership
|
||||
QGenericItemModel modelOnRef(std::ref(objects));
|
||||
QRangeModel modelOnRef(std::ref(objects));
|
||||
QCOMPARE(objects[0].use_count(), 1);
|
||||
}
|
||||
QCOMPARE(objects[0].use_count(), 1);
|
||||
QVERIFY(guard);
|
||||
{ // model owns the last shared copy
|
||||
QGenericItemModel movedIntoModel(std::move(objects));
|
||||
QRangeModel movedIntoModel(std::move(objects));
|
||||
}
|
||||
QVERIFY(!guard);
|
||||
}
|
||||
@ -962,19 +962,19 @@ void tst_QGenericItemModel::ownership()
|
||||
{object}
|
||||
};
|
||||
{ // model does not take ownership
|
||||
QGenericItemModel modelOnCopy(table);
|
||||
QRangeModel modelOnCopy(table);
|
||||
}
|
||||
QVERIFY(guard);
|
||||
{ // model does not take ownership
|
||||
QGenericItemModel modelOnPointer(&table);
|
||||
QRangeModel modelOnPointer(&table);
|
||||
}
|
||||
QVERIFY(guard);
|
||||
{ // model does not take ownership
|
||||
QGenericItemModel modelOnRef(std::ref(table));
|
||||
QRangeModel modelOnRef(std::ref(table));
|
||||
}
|
||||
QVERIFY(guard);
|
||||
{ // model does take ownership of rows, but not of objects within each row
|
||||
QGenericItemModel movedIntoModel(std::move(table));
|
||||
QRangeModel movedIntoModel(std::move(table));
|
||||
}
|
||||
QVERIFY(guard);
|
||||
delete object;
|
||||
@ -984,7 +984,7 @@ void tst_QGenericItemModel::ownership()
|
||||
std::vector<std::shared_ptr<Object>> objects = { std::make_shared<Object>() };
|
||||
|
||||
{
|
||||
QGenericItemModel model(objects);
|
||||
QRangeModel model(objects);
|
||||
QCOMPARE(objects.front().use_count(), 2);
|
||||
}
|
||||
|
||||
@ -998,7 +998,7 @@ void tst_QGenericItemModel::ownership()
|
||||
};
|
||||
|
||||
{
|
||||
QGenericItemModel model(table);
|
||||
QRangeModel model(table);
|
||||
QCOMPARE(table.front().use_count(), 2);
|
||||
QCOMPARE(table.front()->front().use_count(), 1);
|
||||
}
|
||||
@ -1008,7 +1008,7 @@ void tst_QGenericItemModel::ownership()
|
||||
}
|
||||
}
|
||||
|
||||
void tst_QGenericItemModel::dimensions()
|
||||
void tst_QRangeModel::dimensions()
|
||||
{
|
||||
QFETCH(Factory, factory);
|
||||
auto model = factory();
|
||||
@ -1019,7 +1019,7 @@ void tst_QGenericItemModel::dimensions()
|
||||
QCOMPARE(model->columnCount(), expectedColumnCount);
|
||||
}
|
||||
|
||||
void tst_QGenericItemModel::sibling()
|
||||
void tst_QRangeModel::sibling()
|
||||
{
|
||||
QFETCH(Factory, factory);
|
||||
auto model = factory();
|
||||
@ -1044,7 +1044,7 @@ void tst_QGenericItemModel::sibling()
|
||||
test(withChildren);
|
||||
}
|
||||
|
||||
void tst_QGenericItemModel::flags()
|
||||
void tst_QRangeModel::flags()
|
||||
{
|
||||
QFETCH(Factory, factory);
|
||||
auto model = factory();
|
||||
@ -1061,7 +1061,7 @@ void tst_QGenericItemModel::flags()
|
||||
changeActions.testFlags(ChangeAction::SetData));
|
||||
}
|
||||
|
||||
void tst_QGenericItemModel::data()
|
||||
void tst_QRangeModel::data()
|
||||
{
|
||||
QFETCH(Factory, factory);
|
||||
auto model = factory();
|
||||
@ -1077,7 +1077,7 @@ void tst_QGenericItemModel::data()
|
||||
QVERIFY(last.data().isValid());
|
||||
}
|
||||
|
||||
void tst_QGenericItemModel::setData()
|
||||
void tst_QRangeModel::setData()
|
||||
{
|
||||
QFETCH(Factory, factory);
|
||||
auto model = factory();
|
||||
@ -1099,7 +1099,7 @@ void tst_QGenericItemModel::setData()
|
||||
QCOMPARE(first.data() == oldValue, !changeActions.testFlag(ChangeAction::SetData));
|
||||
}
|
||||
|
||||
void tst_QGenericItemModel::itemData()
|
||||
void tst_QRangeModel::itemData()
|
||||
{
|
||||
QFETCH(Factory, factory);
|
||||
auto model = factory();
|
||||
@ -1115,7 +1115,7 @@ void tst_QGenericItemModel::itemData()
|
||||
}
|
||||
}
|
||||
|
||||
void tst_QGenericItemModel::setItemData()
|
||||
void tst_QRangeModel::setItemData()
|
||||
{
|
||||
QFETCH(Factory, factory);
|
||||
auto model = factory();
|
||||
@ -1171,7 +1171,7 @@ void tst_QGenericItemModel::setItemData()
|
||||
}
|
||||
}
|
||||
|
||||
void tst_QGenericItemModel::clearItemData()
|
||||
void tst_QRangeModel::clearItemData()
|
||||
{
|
||||
QFETCH(Factory, factory);
|
||||
auto model = factory();
|
||||
@ -1188,7 +1188,7 @@ void tst_QGenericItemModel::clearItemData()
|
||||
QCOMPARE(index1.data(), oldDataAt1);
|
||||
}
|
||||
|
||||
void tst_QGenericItemModel::insertRows()
|
||||
void tst_QRangeModel::insertRows()
|
||||
{
|
||||
QFETCH(Factory, factory);
|
||||
auto model = factory();
|
||||
@ -1259,7 +1259,7 @@ void tst_QGenericItemModel::insertRows()
|
||||
verifyPmiList(pmiList);
|
||||
}
|
||||
|
||||
void tst_QGenericItemModel::removeRows()
|
||||
void tst_QRangeModel::removeRows()
|
||||
{
|
||||
QFETCH(Factory, factory);
|
||||
auto model = factory();
|
||||
@ -1282,7 +1282,7 @@ void tst_QGenericItemModel::removeRows()
|
||||
QCOMPARE(couldRemove, model->rowCount() != newRowCount);
|
||||
}
|
||||
|
||||
void tst_QGenericItemModel::moveRows()
|
||||
void tst_QRangeModel::moveRows()
|
||||
{
|
||||
QFETCH(Factory, factory);
|
||||
auto model = factory();
|
||||
@ -1325,7 +1325,7 @@ void tst_QGenericItemModel::moveRows()
|
||||
QCOMPARE(model->index(expectedRowCount - 1, 0).data(), last);
|
||||
}
|
||||
|
||||
void tst_QGenericItemModel::insertColumns()
|
||||
void tst_QRangeModel::insertColumns()
|
||||
{
|
||||
QFETCH(Factory, factory);
|
||||
auto model = factory();
|
||||
@ -1344,7 +1344,7 @@ void tst_QGenericItemModel::insertColumns()
|
||||
changeActions.testFlag(ChangeAction::InsertColumns));
|
||||
}
|
||||
|
||||
void tst_QGenericItemModel::removeColumns()
|
||||
void tst_QRangeModel::removeColumns()
|
||||
{
|
||||
QFETCH(Factory, factory);
|
||||
auto model = factory();
|
||||
@ -1356,7 +1356,7 @@ void tst_QGenericItemModel::removeColumns()
|
||||
changeActions.testFlag(ChangeAction::RemoveColumns));
|
||||
}
|
||||
|
||||
void tst_QGenericItemModel::moveColumns()
|
||||
void tst_QRangeModel::moveColumns()
|
||||
{
|
||||
QFETCH(Factory, factory);
|
||||
auto model = factory();
|
||||
@ -1401,9 +1401,9 @@ void tst_QGenericItemModel::moveColumns()
|
||||
}
|
||||
}
|
||||
|
||||
void tst_QGenericItemModel::inconsistentColumnCount()
|
||||
void tst_QRangeModel::inconsistentColumnCount()
|
||||
{
|
||||
QTest::ignoreMessage(QtCriticalMsg, "QGenericItemModel: "
|
||||
QTest::ignoreMessage(QtCriticalMsg, "QRangeModel: "
|
||||
"Column-range at row 1 is not large enough!");
|
||||
|
||||
std::vector<std::vector<int>> fuzzyTable = {
|
||||
@ -1411,7 +1411,7 @@ void tst_QGenericItemModel::inconsistentColumnCount()
|
||||
{},
|
||||
{2},
|
||||
};
|
||||
QGenericItemModel model(fuzzyTable);
|
||||
QRangeModel model(fuzzyTable);
|
||||
QCOMPARE(model.columnCount(), 1);
|
||||
for (int row = 0; row < model.rowCount(); ++row) {
|
||||
auto debug = qScopeGuard([&]{
|
||||
@ -1430,7 +1430,7 @@ void tst_QGenericItemModel::inconsistentColumnCount()
|
||||
|
||||
enum class TreeProtocol { ValueImplicit, ValueReadOnly, PointerExplicit, PointerExplicitMoved };
|
||||
|
||||
void tst_QGenericItemModel::createTree()
|
||||
void tst_QRangeModel::createTree()
|
||||
{
|
||||
tree_row root[] = {
|
||||
{"1", "one"},
|
||||
@ -1469,7 +1469,7 @@ void tst_QGenericItemModel::createTree()
|
||||
m_data->m_pointer_tree->at(1)->addChildPointer("2.2", "two.two");
|
||||
}
|
||||
|
||||
void tst_QGenericItemModel::tree_data()
|
||||
void tst_QRangeModel::tree_data()
|
||||
{
|
||||
m_data.reset(new Data);
|
||||
createTree();
|
||||
@ -1502,7 +1502,7 @@ void tst_QGenericItemModel::tree_data()
|
||||
<< ChangeActions(ChangeAction::All);
|
||||
}
|
||||
|
||||
std::unique_ptr<QAbstractItemModel> tst_QGenericItemModel::makeTreeModel()
|
||||
std::unique_ptr<QAbstractItemModel> tst_QRangeModel::makeTreeModel()
|
||||
{
|
||||
createTree();
|
||||
|
||||
@ -1511,7 +1511,7 @@ std::unique_ptr<QAbstractItemModel> tst_QGenericItemModel::makeTreeModel()
|
||||
QFETCH(const TreeProtocol, protocol);
|
||||
switch (protocol) {
|
||||
case TreeProtocol::ValueImplicit:
|
||||
model.reset(new QGenericItemModel(m_data->m_tree.get()));
|
||||
model.reset(new QRangeModel(m_data->m_tree.get()));
|
||||
break;
|
||||
case TreeProtocol::ValueReadOnly: {
|
||||
struct { // minimal (read-only) implementation of the tree traversal protocol
|
||||
@ -1519,11 +1519,11 @@ std::unique_ptr<QAbstractItemModel> tst_QGenericItemModel::makeTreeModel()
|
||||
const std::optional<value_tree> &childRows(const tree_row &row) const
|
||||
{ return row.childRows(); }
|
||||
} readOnlyProtocol;
|
||||
model.reset(new QGenericItemModel(m_data->m_tree.get(), readOnlyProtocol));
|
||||
model.reset(new QRangeModel(m_data->m_tree.get(), readOnlyProtocol));
|
||||
break;
|
||||
}
|
||||
case TreeProtocol::PointerExplicit:
|
||||
model.reset(new QGenericItemModel(m_data->m_pointer_tree.get(),
|
||||
model.reset(new QRangeModel(m_data->m_pointer_tree.get(),
|
||||
tree_row::ProtocolPointerImpl{}));
|
||||
break;
|
||||
case TreeProtocol::PointerExplicitMoved: {
|
||||
@ -1537,7 +1537,7 @@ std::unique_ptr<QAbstractItemModel> tst_QGenericItemModel::makeTreeModel()
|
||||
moved_tree.at(1)->addChildPointer("2.1", "two.one");
|
||||
moved_tree.at(1)->addChildPointer("2.2", "two.two");
|
||||
|
||||
model.reset(new QGenericItemModel(std::move(moved_tree),
|
||||
model.reset(new QRangeModel(std::move(moved_tree),
|
||||
tree_row::ProtocolPointerImpl{}));
|
||||
break;
|
||||
}
|
||||
@ -1546,7 +1546,7 @@ std::unique_ptr<QAbstractItemModel> tst_QGenericItemModel::makeTreeModel()
|
||||
return model;
|
||||
}
|
||||
|
||||
void tst_QGenericItemModel::tree()
|
||||
void tst_QRangeModel::tree()
|
||||
{
|
||||
auto model = makeTreeModel();
|
||||
QFETCH(const int, expectedRootRowCount);
|
||||
@ -1579,7 +1579,7 @@ void tst_QGenericItemModel::tree()
|
||||
#endif
|
||||
}
|
||||
|
||||
void tst_QGenericItemModel::treeModifyBranch()
|
||||
void tst_QRangeModel::treeModifyBranch()
|
||||
{
|
||||
auto model = makeTreeModel();
|
||||
QFETCH(QList<int>, rowsWithChildren);
|
||||
@ -1641,7 +1641,7 @@ void tst_QGenericItemModel::treeModifyBranch()
|
||||
#endif
|
||||
}
|
||||
|
||||
void tst_QGenericItemModel::treeCreateBranch()
|
||||
void tst_QRangeModel::treeCreateBranch()
|
||||
{
|
||||
auto model = makeTreeModel();
|
||||
QFETCH(QList<int>, rowsWithChildren);
|
||||
@ -1674,7 +1674,7 @@ void tst_QGenericItemModel::treeCreateBranch()
|
||||
verifyPmiList(pmiList);
|
||||
}
|
||||
|
||||
void tst_QGenericItemModel::treeRemoveBranch()
|
||||
void tst_QRangeModel::treeRemoveBranch()
|
||||
{
|
||||
auto model = makeTreeModel();
|
||||
QFETCH(QList<int>, rowsWithChildren);
|
||||
@ -1701,7 +1701,7 @@ void tst_QGenericItemModel::treeRemoveBranch()
|
||||
QCOMPARE(model->rowCount(parent), 0);
|
||||
}
|
||||
|
||||
void tst_QGenericItemModel::treeMoveRows()
|
||||
void tst_QRangeModel::treeMoveRows()
|
||||
{
|
||||
auto model = makeTreeModel();
|
||||
QFETCH(const QList<int>, rowsWithChildren);
|
||||
@ -1726,7 +1726,7 @@ void tst_QGenericItemModel::treeMoveRows()
|
||||
verifyPmiList(pmiList);
|
||||
}
|
||||
|
||||
void tst_QGenericItemModel::treeMoveRowBranches()
|
||||
void tst_QRangeModel::treeMoveRowBranches()
|
||||
{
|
||||
auto model = makeTreeModel();
|
||||
QFETCH(const QList<int>, rowsWithChildren);
|
||||
@ -1797,5 +1797,5 @@ void tst_QGenericItemModel::treeMoveRowBranches()
|
||||
verifyPmiList(pmiList);
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_QGenericItemModel)
|
||||
#include "tst_qgenericitemmodel.moc"
|
||||
QTEST_MAIN(tst_QRangeModel)
|
||||
#include "tst_qrangemodel.moc"
|
Loading…
x
Reference in New Issue
Block a user