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
|
SOURCES
|
||||||
itemmodels/qabstractitemmodel.cpp itemmodels/qabstractitemmodel.h itemmodels/qabstractitemmodel_p.h
|
itemmodels/qabstractitemmodel.cpp itemmodels/qabstractitemmodel.h itemmodels/qabstractitemmodel_p.h
|
||||||
itemmodels/qitemselectionmodel.cpp itemmodels/qitemselectionmodel.h itemmodels/qitemselectionmodel_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
|
qt_internal_extend_target(Core CONDITION QT_FEATURE_proxymodel
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||||
|
|
||||||
add_library(corelib_snippets OBJECT
|
add_library(corelib_snippets OBJECT
|
||||||
qgenericitemmodel/main.cpp
|
qrangemodel/main.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(corelib_snippets PRIVATE
|
target_link_libraries(corelib_snippets PRIVATE
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// Copyright (C) 2025 The Qt Company Ltd.
|
// Copyright (C) 2025 The Qt Company Ltd.
|
||||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||||
|
|
||||||
#include <QtCore/qgenericitemmodel.h>
|
#include <QtCore/qrangemodel.h>
|
||||||
|
|
||||||
#ifndef QT_NO_WIDGETS
|
#ifndef QT_NO_WIDGETS
|
||||||
|
|
||||||
@ -19,7 +19,7 @@ void array()
|
|||||||
|
|
||||||
//! [array]
|
//! [array]
|
||||||
std::array<int, 5> numbers = {1, 2, 3, 4, 5};
|
std::array<int, 5> numbers = {1, 2, 3, 4, 5};
|
||||||
QGenericItemModel model(numbers);
|
QRangeModel model(numbers);
|
||||||
listView.setModel(&model);
|
listView.setModel(&model);
|
||||||
//! [array]
|
//! [array]
|
||||||
}
|
}
|
||||||
@ -30,26 +30,26 @@ void construct_by()
|
|||||||
|
|
||||||
{
|
{
|
||||||
//! [value]
|
//! [value]
|
||||||
QGenericItemModel model(numbers);
|
QRangeModel model(numbers);
|
||||||
//! [value]
|
//! [value]
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
//! [pointer]
|
//! [pointer]
|
||||||
QGenericItemModel model(&numbers);
|
QRangeModel model(&numbers);
|
||||||
//! [pointer]
|
//! [pointer]
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
//! [reference_wrapper]
|
//! [reference_wrapper]
|
||||||
QGenericItemModel model(std::ref(numbers));
|
QRangeModel model(std::ref(numbers));
|
||||||
//! [reference_wrapper]
|
//! [reference_wrapper]
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
//! [smart_pointer]
|
//! [smart_pointer]
|
||||||
auto shared_numbers = std::make_shared<std::vector<int>>(numbers);
|
auto shared_numbers = std::make_shared<std::vector<int>>(numbers);
|
||||||
QGenericItemModel model(shared_numbers);
|
QRangeModel model(shared_numbers);
|
||||||
//! [smart_pointer]
|
//! [smart_pointer]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -59,7 +59,7 @@ void const_array()
|
|||||||
//! [const_array]
|
//! [const_array]
|
||||||
const std::array<int, 5> numbers = {1, 2, 3, 4, 5};
|
const std::array<int, 5> numbers = {1, 2, 3, 4, 5};
|
||||||
//! [const_array]
|
//! [const_array]
|
||||||
QGenericItemModel model(numbers);
|
QRangeModel model(numbers);
|
||||||
}
|
}
|
||||||
|
|
||||||
void const_values()
|
void const_values()
|
||||||
@ -67,14 +67,14 @@ void const_values()
|
|||||||
//! [const_values]
|
//! [const_values]
|
||||||
std::array<const int, 5> numbers = {1, 2, 3, 4, 5};
|
std::array<const int, 5> numbers = {1, 2, 3, 4, 5};
|
||||||
//! [const_values]
|
//! [const_values]
|
||||||
QGenericItemModel model(numbers);
|
QRangeModel model(numbers);
|
||||||
}
|
}
|
||||||
|
|
||||||
void const_ref()
|
void const_ref()
|
||||||
{
|
{
|
||||||
std::vector<int> numbers = {1, 2, 3, 4, 5};
|
std::vector<int> numbers = {1, 2, 3, 4, 5};
|
||||||
//! [const_ref]
|
//! [const_ref]
|
||||||
QGenericItemModel model(std::cref(numbers));
|
QRangeModel model(std::cref(numbers));
|
||||||
//! [const_ref]
|
//! [const_ref]
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,7 +82,7 @@ void list_of_int()
|
|||||||
{
|
{
|
||||||
//! [list_of_int]
|
//! [list_of_int]
|
||||||
QList<int> numbers = {1, 2, 3, 4, 5};
|
QList<int> numbers = {1, 2, 3, 4, 5};
|
||||||
QGenericItemModel model(numbers); // columnCount() == 1
|
QRangeModel model(numbers); // columnCount() == 1
|
||||||
QListView listView;
|
QListView listView;
|
||||||
listView.setModel(&model);
|
listView.setModel(&model);
|
||||||
//! [list_of_int]
|
//! [list_of_int]
|
||||||
@ -96,7 +96,7 @@ std::vector<std::vector<int>> gridOfNumbers = {
|
|||||||
{6, 7, 8, 9, 10},
|
{6, 7, 8, 9, 10},
|
||||||
{11, 12, 13, 14, 15},
|
{11, 12, 13, 14, 15},
|
||||||
};
|
};
|
||||||
QGenericItemModel model(&gridOfNumbers); // columnCount() == 5
|
QRangeModel model(&gridOfNumbers); // columnCount() == 5
|
||||||
QTableView tableView;
|
QTableView tableView;
|
||||||
tableView.setModel(&model);
|
tableView.setModel(&model);
|
||||||
//! [grid_of_numbers]
|
//! [grid_of_numbers]
|
||||||
@ -111,7 +111,7 @@ QList<TableRow> numberNames = {
|
|||||||
{2, "two"},
|
{2, "two"},
|
||||||
{3, "three"}
|
{3, "three"}
|
||||||
};
|
};
|
||||||
QGenericItemModel model(&numberNames); // columnCount() == 2
|
QRangeModel model(&numberNames); // columnCount() == 2
|
||||||
QTableView tableView;
|
QTableView tableView;
|
||||||
tableView.setModel(&model);
|
tableView.setModel(&model);
|
||||||
//! [pair_int_QString]
|
//! [pair_int_QString]
|
||||||
@ -220,7 +220,7 @@ public:
|
|||||||
std::optional<Tree> &childRows() { return m_children; }
|
std::optional<Tree> &childRows() { return m_children; }
|
||||||
//! [tree_protocol_3]
|
//! [tree_protocol_3]
|
||||||
//! [tree_protocol_4]
|
//! [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>
|
template <typename ...Args>
|
||||||
TreeRow &addChild(Args &&...args)
|
TreeRow &addChild(Args &&...args)
|
||||||
{
|
{
|
||||||
@ -259,7 +259,7 @@ tree[2].addChild("...");
|
|||||||
{
|
{
|
||||||
//! [tree_protocol_6]
|
//! [tree_protocol_6]
|
||||||
// instantiate the model with a pointer to the tree, not a copy!
|
// instantiate the model with a pointer to the tree, not a copy!
|
||||||
QGenericItemModel model(&tree);
|
QRangeModel model(&tree);
|
||||||
QTreeView view;
|
QTreeView view;
|
||||||
view.setModel(&model);
|
view.setModel(&model);
|
||||||
//! [tree_protocol_6]
|
//! [tree_protocol_6]
|
||||||
@ -280,7 +280,7 @@ void explicit_tree_protocol()
|
|||||||
{
|
{
|
||||||
Tree tree;
|
Tree tree;
|
||||||
//! [explicit_tree_protocol_1]
|
//! [explicit_tree_protocol_1]
|
||||||
QGenericItemModel model(&tree, TreeTraversal{});
|
QRangeModel model(&tree, TreeTraversal{});
|
||||||
//! [explicit_tree_protocol_1]
|
//! [explicit_tree_protocol_1]
|
||||||
}
|
}
|
||||||
} // namespace tree_protocol
|
} // namespace tree_protocol
|
||||||
@ -366,7 +366,7 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
Tree tree = make_tree_of_pointers();
|
Tree tree = make_tree_of_pointers();
|
||||||
|
|
||||||
QGenericItemModel model(std::move(tree), TreeTraversal{});
|
QRangeModel model(std::move(tree), TreeTraversal{});
|
||||||
QTreeView treeView;
|
QTreeView treeView;
|
||||||
treeView.setModel(&model);
|
treeView.setModel(&model);
|
||||||
treeView.show();
|
treeView.show();
|
||||||
@ -391,7 +391,7 @@ for (const QString &name : colorNames) {
|
|||||||
{Qt::DecorationRole, color},
|
{Qt::DecorationRole, color},
|
||||||
{Qt::ToolTipRole, color.name()}};
|
{Qt::ToolTipRole, color.name()}};
|
||||||
}
|
}
|
||||||
QGenericItemModel colorModel(colors);
|
QRangeModel colorModel(colors);
|
||||||
QListView list;
|
QListView list;
|
||||||
list.setModel(&colorModel);
|
list.setModel(&colorModel);
|
||||||
//! [color_map]
|
//! [color_map]
|
||||||
@ -427,12 +427,12 @@ private:
|
|||||||
void color_list() {
|
void color_list() {
|
||||||
//! [color_gadget_1]
|
//! [color_gadget_1]
|
||||||
const QStringList colorNames = QColor::colorNames();
|
const QStringList colorNames = QColor::colorNames();
|
||||||
QList<QGenericItemModel::SingleColumn<ColorEntry>> colors;
|
QList<QRangeModel::SingleColumn<ColorEntry>> colors;
|
||||||
colors.reserve(colorNames.size());
|
colors.reserve(colorNames.size());
|
||||||
for (const QString &name : colorNames)
|
for (const QString &name : colorNames)
|
||||||
colors << ColorEntry{name};
|
colors << ColorEntry{name};
|
||||||
|
|
||||||
QGenericItemModel colorModel(colors);
|
QRangeModel colorModel(colors);
|
||||||
QListView list;
|
QListView list;
|
||||||
list.setModel(&colorModel);
|
list.setModel(&colorModel);
|
||||||
//! [color_gadget_1]
|
//! [color_gadget_1]
|
@ -1,29 +1,29 @@
|
|||||||
// Copyright (C) 2025 The Qt Company Ltd.
|
// 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
|
// 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>
|
#include <QtCore/qsize.h>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\class QGenericItemModel
|
\class QRangeModel
|
||||||
\inmodule QtCore
|
\inmodule QtCore
|
||||||
\since 6.10
|
\since 6.10
|
||||||
\ingroup model-view
|
\ingroup model-view
|
||||||
\brief QGenericItemModel implements QAbstractItemModel for any C++ range.
|
\brief QRangeModel implements QAbstractItemModel for any C++ range.
|
||||||
\reentrant
|
\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.
|
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
|
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
|
and Qt Quick item views, and to allow the user of the application to
|
||||||
manipulate the data using a graphical user interface.
|
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:
|
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
|
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
|
\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
|
QAbstractItemModel APIs that modify the model, such as setData() or
|
||||||
insertRows(), have no impact on the original range.
|
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
|
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.
|
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
|
To make modifications of the model affect the original range, provide the
|
||||||
range either by reference wrapper or by pointer.
|
range either by reference wrapper or by pointer.
|
||||||
|
|
||||||
\snippet qgenericitemmodel/main.cpp pointer
|
\snippet qrangemodel/main.cpp pointer
|
||||||
\snippet qgenericitemmodel/main.cpp reference_wrapper
|
\snippet qrangemodel/main.cpp reference_wrapper
|
||||||
|
|
||||||
In this case, QAbstractItemModel APIs that modify the model also modify the
|
In this case, QAbstractItemModel APIs that modify the model also modify the
|
||||||
range. Methods that modify the structure of the range, such as insertRows()
|
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
|
Use smart pointers to make sure that the range is only deleted when all
|
||||||
clients are done with it.
|
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
|
\section2 Read-only or mutable
|
||||||
|
|
||||||
For ranges that are const objects, for which access always yields constant
|
For ranges that are const objects, for which access always yields constant
|
||||||
values, or where the required container APIs are not available,
|
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
|
\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
|
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
|
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
|
the values in the list view. By making the array const, the values also
|
||||||
become read-only.
|
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
|
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
|
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
|
rows, and the data can be changed. Passing the range as a constant
|
||||||
reference will make the model read-only.
|
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
|
\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.
|
to remove or insert columns and rows through the QAbstractItemModel API.
|
||||||
@ -112,18 +112,18 @@ QT_BEGIN_NAMESPACE
|
|||||||
\section1 Rows and columns
|
\section1 Rows and columns
|
||||||
|
|
||||||
The elements in the range are interpreted as rows of the model. Depending
|
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.
|
list, a table, or a tree.
|
||||||
|
|
||||||
If the row elements are simple values, then the range gets represented as a
|
If the row elements are simple values, then the range gets represented as a
|
||||||
list.
|
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,
|
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.
|
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()},
|
If the row type provides the standard C++ container APIs \c{resize()},
|
||||||
\c{insert()}, \c{erase()}, then columns can be added and removed via
|
\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
|
If the row type implements \l{the C++ tuple protocol}, then the range gets
|
||||||
represented as a table with a fixed number of columns.
|
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
|
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
|
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
|
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.
|
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}
|
Using QObject subclasses allows properties to be \l{Qt Bindable Properties}
|
||||||
{bindable}, or to have change notification signals. However, using QObject
|
{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},
|
If the item is an associative container that uses \c{int},
|
||||||
\l{Qt::ItemDataRole}, or QString as the key type, and QVariant as the
|
\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
|
of the data for multiple roles. The data() and setData() functions return
|
||||||
and modify the mapped value in the container, and setItemData() modifies all
|
and modify the mapped value in the container, and setItemData() modifies all
|
||||||
provided values, itemData() returns all stored values, and clearItemData()
|
provided values, itemData() returns all stored values, and clearItemData()
|
||||||
clears the entire container.
|
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
|
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
|
\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
|
are the item type in a table. The names of the properties have to match the
|
||||||
names of the roles.
|
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
|
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
|
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,
|
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.
|
wrappers.
|
||||||
|
|
||||||
\snippet qgenericitemmodel/main.cpp color_gadget_1
|
\snippet qrangemodel/main.cpp color_gadget_1
|
||||||
|
|
||||||
\section1 Trees of data
|
\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
|
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
|
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
|
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}.
|
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
|
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,
|
For any given row, the model needs to be able to retrieve the parent row,
|
||||||
and the span of children for any given 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
|
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
|
or values} for the considerations on whether to use values or pointers of
|
||||||
items for the rows.
|
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
|
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
|
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
|
to construct new row data elements, for instance in the insertRow() or
|
||||||
moveRows() implementations.
|
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 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
|
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(),
|
model to implement mutating model APIs such as insertRows(), removeRows(),
|
||||||
and moveRows(), we have to implement additional functions for write-access:
|
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()}
|
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
|
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.
|
as separate steps. This keeps the protocol interface small.
|
||||||
|
|
||||||
\dots
|
\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
|
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
|
a \c{addChild()} helper provides us with a convenient way to construct the
|
||||||
initial state of the tree.
|
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.
|
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
|
\section3 Tree traversal protocol in a separate class
|
||||||
|
|
||||||
The tree traversal protocol can also be implemented 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:
|
constructor:
|
||||||
|
|
||||||
\snippet qgenericitemmodel/main.cpp explicit_tree_protocol_1
|
\snippet qrangemodel/main.cpp explicit_tree_protocol_1
|
||||||
|
|
||||||
\section2 Rows as pointers or values
|
\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
|
the location of the parent row within the vector. Making sure that this
|
||||||
parent (and QPersistentModelIndex instances referring to items within it)
|
parent (and QPersistentModelIndex instances referring to items within it)
|
||||||
stays valid can incurr substantial performance overhead. The
|
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.
|
range become invalid when modifying the range.
|
||||||
|
|
||||||
Alternatively, we can also use a range of row pointers as the tree type:
|
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
|
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
|
operator \c{new}, and implement the destructor to \c{delete} all items in
|
||||||
the vector of children.
|
the vector of children.
|
||||||
|
|
||||||
\snippet qgenericitemmodel/main.cpp tree_of_pointers_1
|
\snippet qrangemodel/main.cpp tree_of_pointers_1
|
||||||
\snippet qgenericitemmodel/main.cpp tree_of_pointers_2
|
\snippet qrangemodel/main.cpp tree_of_pointers_2
|
||||||
|
|
||||||
Before we can construct a model that represents this data as a tree, we need
|
Before we can construct a model that represents this data as a tree, we need
|
||||||
to also implement the tree traversal protocol.
|
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
|
An explicit protocol implementation for mutable trees of pointers has to
|
||||||
provide two additional member functions, \c{newRow()} and
|
provide two additional member functions, \c{newRow()} and
|
||||||
\c{deleteRow(RowType *)}.
|
\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(),
|
The model will call those functions when creating new rows in insertRows(),
|
||||||
and when removing rows in removeRows(). In addition, if the model has
|
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
|
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
|
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
|
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.
|
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
|
\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 operator new, and will never free any rows.
|
||||||
|
|
||||||
Using pointers at rows comes with some memory allocation and management
|
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
|
type to make existing structured data available to the model/view framework
|
||||||
in Qt.
|
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
|
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
|
\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.
|
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
|
\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
|
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
|
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
|
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.
|
to disambiguate.
|
||||||
|
|
||||||
\sa {Model/View Programming}
|
\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
|
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
|
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.
|
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
|
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
|
multi-column rows with each property being one column. The range will be
|
||||||
@ -386,25 +386,25 @@ QT_BEGIN_NAMESPACE
|
|||||||
QList<ColorEntry> colors = {
|
QList<ColorEntry> colors = {
|
||||||
// ...
|
// ...
|
||||||
};
|
};
|
||||||
QGenericItemModel tableModel(colors); // columnCount() == 3
|
QRangeModel tableModel(colors); // columnCount() == 3
|
||||||
\endcode
|
\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.
|
with each instance of \c{T} represented as an item with multiple roles.
|
||||||
|
|
||||||
\code
|
\code
|
||||||
QList<QGenericItemModel::SingleColumn<ColorEntry>> colors = {
|
QList<QRangeModel::SingleColumn<ColorEntry>> colors = {
|
||||||
// ...
|
// ...
|
||||||
};
|
};
|
||||||
QGenericItemModel listModel(colors); // columnCount() == 1
|
QRangeModel listModel(colors); // columnCount() == 1
|
||||||
\endcode
|
\endcode
|
||||||
|
|
||||||
\sa QGenericItemModel::MultiColumn
|
\sa QRangeModel::MultiColumn
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\class QGenericItemModel::MultiColumn
|
\class QRangeModel::MultiColumn
|
||||||
\brief Represents the wrapped type \c{T} as multiple columns in a QGenericItemModel.
|
\brief Represents the wrapped type \c{T} as multiple columns in a QRangeModel.
|
||||||
\inmodule QtCore
|
\inmodule QtCore
|
||||||
\ingroup model-view
|
\ingroup model-view
|
||||||
\since 6.10
|
\since 6.10
|
||||||
@ -414,29 +414,29 @@ QT_BEGIN_NAMESPACE
|
|||||||
multiple columns, and the individual values will be accessed through the
|
multiple columns, and the individual values will be accessed through the
|
||||||
tuple protocol.
|
tuple protocol.
|
||||||
|
|
||||||
\snippet qgenericitemmodel/main.cpp color_gadget_0
|
\snippet qrangemodel/main.cpp color_gadget_0
|
||||||
\code
|
\code
|
||||||
namespace std {
|
namespace std {
|
||||||
template <> struct tuple_size<ColorEntry> : integral_constant<size_t, 3> {};
|
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
|
\endcode
|
||||||
|
|
||||||
To represent the type a single column value with multiple roles, use
|
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, QRangeModelDetails::if_is_table_range<Range>> QRangeModel::QRangeModel(Range &&range, QObject *parent)
|
||||||
\fn template <typename Range, QGenericItemModelDetails::if_is_tree_range<Range>> QGenericItemModel::QGenericItemModel(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, QGenericItemModelDetails::if_is_tree_range<Range, Protocol>> QGenericItemModel::QGenericItemModel(Range &&range, Protocol &&protocol, 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
|
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}
|
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.
|
The range that the model was constructed from is not destroyed.
|
||||||
*/
|
*/
|
||||||
QGenericItemModel::~QGenericItemModel() = default;
|
QRangeModel::~QRangeModel() = default;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\reimp
|
\reimp
|
||||||
@ -473,9 +473,9 @@ QGenericItemModel::~QGenericItemModel() = default;
|
|||||||
|
|
||||||
\sa parent()
|
\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()
|
\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()
|
\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()
|
\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()
|
\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
|
\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
|
\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);
|
section, orientation, role);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -599,9 +599,9 @@ QVariant QGenericItemModel::headerData(int section, Qt::Orientation orientation,
|
|||||||
|
|
||||||
\sa Qt::ItemDataRole, setData(), headerData()
|
\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.
|
returns \c{false} immediately.
|
||||||
//! [read-only-setData]
|
//! [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()
|
\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
|
\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-
|
Replaces the value stored in the range at \a index with a default-
|
||||||
constructed value.
|
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
|
of the range at \a parent. Returns \c{true} if successful; otherwise
|
||||||
returns \c{false}.
|
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
|
range at \a parent. Returns \c{true} if successful, otherwise returns
|
||||||
\c{false}.
|
\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
|
Returns \c{true} if the columns were successfully moved; otherwise returns
|
||||||
\c{false}.
|
\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)
|
const QModelIndex &destinationParent, int destinationColumn)
|
||||||
{
|
{
|
||||||
return impl->call<bool>(QGenericItemModelImplBase::MoveColumns,
|
return impl->call<bool>(QRangeModelImplBase::MoveColumns,
|
||||||
sourceParent, sourceColumn, count,
|
sourceParent, sourceColumn, count,
|
||||||
destinationParent, destinationColumn);
|
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
|
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}.
|
\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
|
\note For ranges with a dynamically sized column type, the column needs
|
||||||
to provide a \c{resize(size_t)} member function.
|
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
|
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}.
|
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
|
Returns \c{true} if the rows were successfully moved; otherwise returns
|
||||||
\c{false}.
|
\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)
|
const QModelIndex &destinationParent, int destinationRow)
|
||||||
{
|
{
|
||||||
return impl->call<bool>(QGenericItemModelImplBase::MoveRows,
|
return impl->call<bool>(QRangeModelImplBase::MoveRows,
|
||||||
sourceParent, sourceRow, count,
|
sourceParent, sourceRow, count,
|
||||||
destinationParent, destinationRow);
|
destinationParent, destinationRow);
|
||||||
}
|
}
|
||||||
@ -812,7 +812,7 @@ bool QGenericItemModel::moveRows(const QModelIndex &sourceParent, int sourceRow,
|
|||||||
/*!
|
/*!
|
||||||
\reimp
|
\reimp
|
||||||
*/
|
*/
|
||||||
bool QGenericItemModel::canFetchMore(const QModelIndex &parent) const
|
bool QRangeModel::canFetchMore(const QModelIndex &parent) const
|
||||||
{
|
{
|
||||||
return QAbstractItemModel::canFetchMore(parent);
|
return QAbstractItemModel::canFetchMore(parent);
|
||||||
}
|
}
|
||||||
@ -820,7 +820,7 @@ bool QGenericItemModel::canFetchMore(const QModelIndex &parent) const
|
|||||||
/*!
|
/*!
|
||||||
\reimp
|
\reimp
|
||||||
*/
|
*/
|
||||||
void QGenericItemModel::fetchMore(const QModelIndex &parent)
|
void QRangeModel::fetchMore(const QModelIndex &parent)
|
||||||
{
|
{
|
||||||
QAbstractItemModel::fetchMore(parent);
|
QAbstractItemModel::fetchMore(parent);
|
||||||
}
|
}
|
||||||
@ -828,7 +828,7 @@ void QGenericItemModel::fetchMore(const QModelIndex &parent)
|
|||||||
/*!
|
/*!
|
||||||
\reimp
|
\reimp
|
||||||
*/
|
*/
|
||||||
bool QGenericItemModel::hasChildren(const QModelIndex &parent) const
|
bool QRangeModel::hasChildren(const QModelIndex &parent) const
|
||||||
{
|
{
|
||||||
return QAbstractItemModel::hasChildren(parent);
|
return QAbstractItemModel::hasChildren(parent);
|
||||||
}
|
}
|
||||||
@ -836,7 +836,7 @@ bool QGenericItemModel::hasChildren(const QModelIndex &parent) const
|
|||||||
/*!
|
/*!
|
||||||
\reimp
|
\reimp
|
||||||
*/
|
*/
|
||||||
QModelIndex QGenericItemModel::buddy(const QModelIndex &index) const
|
QModelIndex QRangeModel::buddy(const QModelIndex &index) const
|
||||||
{
|
{
|
||||||
return QAbstractItemModel::buddy(index);
|
return QAbstractItemModel::buddy(index);
|
||||||
}
|
}
|
||||||
@ -844,7 +844,7 @@ QModelIndex QGenericItemModel::buddy(const QModelIndex &index) const
|
|||||||
/*!
|
/*!
|
||||||
\reimp
|
\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
|
int row, int column, const QModelIndex &parent) const
|
||||||
{
|
{
|
||||||
return QAbstractItemModel::canDropMimeData(data, action, row, column, parent);
|
return QAbstractItemModel::canDropMimeData(data, action, row, column, parent);
|
||||||
@ -853,7 +853,7 @@ bool QGenericItemModel::canDropMimeData(const QMimeData *data, Qt::DropAction ac
|
|||||||
/*!
|
/*!
|
||||||
\reimp
|
\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)
|
int row, int column, const QModelIndex &parent)
|
||||||
{
|
{
|
||||||
return QAbstractItemModel::dropMimeData(data, action, row, column, parent);
|
return QAbstractItemModel::dropMimeData(data, action, row, column, parent);
|
||||||
@ -862,7 +862,7 @@ bool QGenericItemModel::dropMimeData(const QMimeData *data, Qt::DropAction actio
|
|||||||
/*!
|
/*!
|
||||||
\reimp
|
\reimp
|
||||||
*/
|
*/
|
||||||
QMimeData *QGenericItemModel::mimeData(const QModelIndexList &indexes) const
|
QMimeData *QRangeModel::mimeData(const QModelIndexList &indexes) const
|
||||||
{
|
{
|
||||||
return QAbstractItemModel::mimeData(indexes);
|
return QAbstractItemModel::mimeData(indexes);
|
||||||
}
|
}
|
||||||
@ -870,7 +870,7 @@ QMimeData *QGenericItemModel::mimeData(const QModelIndexList &indexes) const
|
|||||||
/*!
|
/*!
|
||||||
\reimp
|
\reimp
|
||||||
*/
|
*/
|
||||||
QStringList QGenericItemModel::mimeTypes() const
|
QStringList QRangeModel::mimeTypes() const
|
||||||
{
|
{
|
||||||
return QAbstractItemModel::mimeTypes();
|
return QAbstractItemModel::mimeTypes();
|
||||||
}
|
}
|
||||||
@ -878,7 +878,7 @@ QStringList QGenericItemModel::mimeTypes() const
|
|||||||
/*!
|
/*!
|
||||||
\reimp
|
\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
|
int hits, Qt::MatchFlags flags) const
|
||||||
{
|
{
|
||||||
return QAbstractItemModel::match(start, role, value, hits, flags);
|
return QAbstractItemModel::match(start, role, value, hits, flags);
|
||||||
@ -887,7 +887,7 @@ QModelIndexList QGenericItemModel::match(const QModelIndex &start, int role, con
|
|||||||
/*!
|
/*!
|
||||||
\reimp
|
\reimp
|
||||||
*/
|
*/
|
||||||
void QGenericItemModel::multiData(const QModelIndex &index, QModelRoleDataSpan roleDataSpan) const
|
void QRangeModel::multiData(const QModelIndex &index, QModelRoleDataSpan roleDataSpan) const
|
||||||
{
|
{
|
||||||
QAbstractItemModel::multiData(index, roleDataSpan);
|
QAbstractItemModel::multiData(index, roleDataSpan);
|
||||||
}
|
}
|
||||||
@ -895,7 +895,7 @@ void QGenericItemModel::multiData(const QModelIndex &index, QModelRoleDataSpan r
|
|||||||
/*!
|
/*!
|
||||||
\reimp
|
\reimp
|
||||||
*/
|
*/
|
||||||
QHash<int, QByteArray> QGenericItemModel::roleNames() const
|
QHash<int, QByteArray> QRangeModel::roleNames() const
|
||||||
{
|
{
|
||||||
return QAbstractItemModel::roleNames();
|
return QAbstractItemModel::roleNames();
|
||||||
}
|
}
|
||||||
@ -903,7 +903,7 @@ QHash<int, QByteArray> QGenericItemModel::roleNames() const
|
|||||||
/*!
|
/*!
|
||||||
\reimp
|
\reimp
|
||||||
*/
|
*/
|
||||||
void QGenericItemModel::sort(int column, Qt::SortOrder order)
|
void QRangeModel::sort(int column, Qt::SortOrder order)
|
||||||
{
|
{
|
||||||
return QAbstractItemModel::sort(column, order);
|
return QAbstractItemModel::sort(column, order);
|
||||||
}
|
}
|
||||||
@ -911,7 +911,7 @@ void QGenericItemModel::sort(int column, Qt::SortOrder order)
|
|||||||
/*!
|
/*!
|
||||||
\reimp
|
\reimp
|
||||||
*/
|
*/
|
||||||
QSize QGenericItemModel::span(const QModelIndex &index) const
|
QSize QRangeModel::span(const QModelIndex &index) const
|
||||||
{
|
{
|
||||||
return QAbstractItemModel::span(index);
|
return QAbstractItemModel::span(index);
|
||||||
}
|
}
|
||||||
@ -919,7 +919,7 @@ QSize QGenericItemModel::span(const QModelIndex &index) const
|
|||||||
/*!
|
/*!
|
||||||
\reimp
|
\reimp
|
||||||
*/
|
*/
|
||||||
Qt::DropActions QGenericItemModel::supportedDragActions() const
|
Qt::DropActions QRangeModel::supportedDragActions() const
|
||||||
{
|
{
|
||||||
return QAbstractItemModel::supportedDragActions();
|
return QAbstractItemModel::supportedDragActions();
|
||||||
}
|
}
|
||||||
@ -927,7 +927,7 @@ Qt::DropActions QGenericItemModel::supportedDragActions() const
|
|||||||
/*!
|
/*!
|
||||||
\reimp
|
\reimp
|
||||||
*/
|
*/
|
||||||
Qt::DropActions QGenericItemModel::supportedDropActions() const
|
Qt::DropActions QRangeModel::supportedDropActions() const
|
||||||
{
|
{
|
||||||
return QAbstractItemModel::supportedDropActions();
|
return QAbstractItemModel::supportedDropActions();
|
||||||
}
|
}
|
||||||
@ -935,7 +935,7 @@ Qt::DropActions QGenericItemModel::supportedDropActions() const
|
|||||||
/*!
|
/*!
|
||||||
\reimp
|
\reimp
|
||||||
*/
|
*/
|
||||||
void QGenericItemModel::resetInternalData()
|
void QRangeModel::resetInternalData()
|
||||||
{
|
{
|
||||||
QAbstractItemModel::resetInternalData();
|
QAbstractItemModel::resetInternalData();
|
||||||
}
|
}
|
||||||
@ -943,7 +943,7 @@ void QGenericItemModel::resetInternalData()
|
|||||||
/*!
|
/*!
|
||||||
\reimp
|
\reimp
|
||||||
*/
|
*/
|
||||||
bool QGenericItemModel::event(QEvent *event)
|
bool QRangeModel::event(QEvent *event)
|
||||||
{
|
{
|
||||||
return QAbstractItemModel::event(event);
|
return QAbstractItemModel::event(event);
|
||||||
}
|
}
|
||||||
@ -951,11 +951,11 @@ bool QGenericItemModel::event(QEvent *event)
|
|||||||
/*!
|
/*!
|
||||||
\reimp
|
\reimp
|
||||||
*/
|
*/
|
||||||
bool QGenericItemModel::eventFilter(QObject *object, QEvent *event)
|
bool QRangeModel::eventFilter(QObject *object, QEvent *event)
|
||||||
{
|
{
|
||||||
return QAbstractItemModel::eventFilter(object, event);
|
return QAbstractItemModel::eventFilter(object, event);
|
||||||
}
|
}
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
#include "moc_qgenericitemmodel.cpp"
|
#include "moc_qrangemodel.cpp"
|
@ -1,14 +1,14 @@
|
|||||||
// Copyright (C) 2025 The Qt Company Ltd.
|
// 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
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
||||||
|
|
||||||
#ifndef QGENERICITEMMODEL_H
|
#ifndef QRANGEMODEL_H
|
||||||
#define QGENERICITEMMODEL_H
|
#define QRANGEMODEL_H
|
||||||
|
|
||||||
#include <QtCore/qgenericitemmodel_impl.h>
|
#include <QtCore/qrangemodel_impl.h>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
class Q_CORE_EXPORT QGenericItemModel : public QAbstractItemModel
|
class Q_CORE_EXPORT QRangeModel : public QAbstractItemModel
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
@ -25,7 +25,7 @@ public:
|
|||||||
MultiColumn<T>>, bool>;
|
MultiColumn<T>>, bool>;
|
||||||
|
|
||||||
template <typename V = T,
|
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); }
|
constexpr explicit operator bool() const noexcept { return bool(data); }
|
||||||
|
|
||||||
// unconstrained on size_t I, gcc internal error #3280
|
// unconstrained on size_t I, gcc internal error #3280
|
||||||
@ -33,23 +33,23 @@ public:
|
|||||||
friend inline decltype(auto) get(V &&multiColumn)
|
friend inline decltype(auto) get(V &&multiColumn)
|
||||||
{
|
{
|
||||||
static_assert(I < std::tuple_size_v<type>, "Index out of bounds for wrapped type");
|
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,
|
template <typename Range,
|
||||||
QGenericItemModelDetails::if_is_table_range<Range> = true>
|
QRangeModelDetails::if_is_table_range<Range> = true>
|
||||||
explicit QGenericItemModel(Range &&range, QObject *parent = nullptr);
|
explicit QRangeModel(Range &&range, QObject *parent = nullptr);
|
||||||
|
|
||||||
template <typename Range,
|
template <typename Range,
|
||||||
QGenericItemModelDetails::if_is_tree_range<Range> = true>
|
QRangeModelDetails::if_is_tree_range<Range> = true>
|
||||||
explicit QGenericItemModel(Range &&range, QObject *parent = nullptr);
|
explicit QRangeModel(Range &&range, QObject *parent = nullptr);
|
||||||
|
|
||||||
template <typename Range, typename Protocol,
|
template <typename Range, typename Protocol,
|
||||||
QGenericItemModelDetails::if_is_tree_range<Range, Protocol> = true>
|
QRangeModelDetails::if_is_tree_range<Range, Protocol> = true>
|
||||||
explicit QGenericItemModel(Range &&range, Protocol &&protocol, QObject *parent = nullptr);
|
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 index(int row, int column, const QModelIndex &parent = {}) const override;
|
||||||
QModelIndex parent(const QModelIndex &child) const override;
|
QModelIndex parent(const QModelIndex &child) const override;
|
||||||
@ -100,112 +100,112 @@ protected:
|
|||||||
bool eventFilter(QObject *, QEvent *) override;
|
bool eventFilter(QObject *, QEvent *) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Q_DISABLE_COPY_MOVE(QGenericItemModel)
|
Q_DISABLE_COPY_MOVE(QRangeModel)
|
||||||
|
|
||||||
friend class QGenericItemModelImplBase;
|
friend class QRangeModelImplBase;
|
||||||
struct Deleter { void operator()(QGenericItemModelImplBase *that) { that->destroy(); } };
|
struct Deleter { void operator()(QRangeModelImplBase *that) { that->destroy(); } };
|
||||||
std::unique_ptr<QGenericItemModelImplBase, Deleter> impl;
|
std::unique_ptr<QRangeModelImplBase, Deleter> impl;
|
||||||
};
|
};
|
||||||
|
|
||||||
// implementation of forwarders
|
// 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)
|
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)
|
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 sourceLast, const QModelIndex &destParent,
|
||||||
int destColumn)
|
int destColumn)
|
||||||
{
|
{
|
||||||
return m_itemModel->beginMoveColumns(sourceParent, sourceFirst, sourceLast,
|
return m_rangeModel->beginMoveColumns(sourceParent, sourceFirst, sourceLast,
|
||||||
destParent, destColumn);
|
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,
|
int sourceLast,
|
||||||
const QModelIndex &destParent, int destRow)
|
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,
|
template <typename Range,
|
||||||
QGenericItemModelDetails::if_is_table_range<Range>>
|
QRangeModelDetails::if_is_table_range<Range>>
|
||||||
QGenericItemModel::QGenericItemModel(Range &&range, QObject *parent)
|
QRangeModel::QRangeModel(Range &&range, QObject *parent)
|
||||||
: QAbstractItemModel(parent)
|
: QAbstractItemModel(parent)
|
||||||
, impl(new QGenericTableItemModelImpl<Range>(std::forward<Range>(range), this))
|
, impl(new QGenericTableItemModelImpl<Range>(std::forward<Range>(range), this))
|
||||||
{}
|
{}
|
||||||
|
|
||||||
template <typename Range,
|
template <typename Range,
|
||||||
QGenericItemModelDetails::if_is_tree_range<Range>>
|
QRangeModelDetails::if_is_tree_range<Range>>
|
||||||
QGenericItemModel::QGenericItemModel(Range &&range, QObject *parent)
|
QRangeModel::QRangeModel(Range &&range, QObject *parent)
|
||||||
: QGenericItemModel(std::forward<Range>(range),
|
: QRangeModel(std::forward<Range>(range),
|
||||||
QGenericItemModelDetails::DefaultTreeProtocol<Range>{}, parent)
|
QRangeModelDetails::DefaultTreeProtocol<Range>{}, parent)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
template <typename Range, typename Protocol,
|
template <typename Range, typename Protocol,
|
||||||
QGenericItemModelDetails::if_is_tree_range<Range, Protocol>>
|
QRangeModelDetails::if_is_tree_range<Range, Protocol>>
|
||||||
QGenericItemModel::QGenericItemModel(Range &&range, Protocol &&protocol, QObject *parent)
|
QRangeModel::QRangeModel(Range &&range, Protocol &&protocol, QObject *parent)
|
||||||
: QAbstractItemModel(parent)
|
: QAbstractItemModel(parent)
|
||||||
, impl(new QGenericTreeItemModelImpl<Range, Protocol>(std::forward<Range>(range),
|
, impl(new QGenericTreeItemModelImpl<Range, Protocol>(std::forward<Range>(range),
|
||||||
std::forward<Protocol>(protocol), this))
|
std::forward<Protocol>(protocol), this))
|
||||||
@ -215,13 +215,13 @@ QT_END_NAMESPACE
|
|||||||
|
|
||||||
namespace std {
|
namespace std {
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct tuple_size<QT_PREPEND_NAMESPACE(QGenericItemModel)::MultiColumn<T>>
|
struct tuple_size<QT_PREPEND_NAMESPACE(QRangeModel)::MultiColumn<T>>
|
||||||
: tuple_size<typename QT_PREPEND_NAMESPACE(QGenericItemModel)::MultiColumn<T>::type>
|
: tuple_size<typename QT_PREPEND_NAMESPACE(QRangeModel)::MultiColumn<T>::type>
|
||||||
{};
|
{};
|
||||||
template <std::size_t I, typename T>
|
template <std::size_t I, typename T>
|
||||||
struct tuple_element<I, QT_PREPEND_NAMESPACE(QGenericItemModel)::MultiColumn<T>>
|
struct tuple_element<I, QT_PREPEND_NAMESPACE(QRangeModel)::MultiColumn<T>>
|
||||||
: tuple_element<I, typename QT_PREPEND_NAMESPACE(QGenericItemModel)::MultiColumn<T>::type>
|
: 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.
|
// 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
|
// 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
|
#ifndef QRANGEMODEL_IMPL_H
|
||||||
#define QGENERICITEMMODEL_IMPL_H
|
#define QRANGEMODEL_IMPL_H
|
||||||
|
|
||||||
#ifndef Q_QDOC
|
#ifndef Q_QDOC
|
||||||
|
|
||||||
#ifndef QGENERICITEMMODEL_H
|
#ifndef QRANGEMODEL_H
|
||||||
#error Do not include qgenericitemmodel_impl.h directly
|
#error Do not include qrangemodel_impl.h directly
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
@ -30,7 +30,7 @@
|
|||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
namespace QGenericItemModelDetails
|
namespace QRangeModelDetails
|
||||||
{
|
{
|
||||||
template <typename T, template <typename...> typename... Templates>
|
template <typename T, template <typename...> typename... Templates>
|
||||||
struct is_any_of_impl : std::false_type {};
|
struct is_any_of_impl : std::false_type {};
|
||||||
@ -145,10 +145,10 @@ namespace QGenericItemModelDetails
|
|||||||
{ return std::cend(refTo(std::forward<C>(c))); }
|
{ return std::cend(refTo(std::forward<C>(c))); }
|
||||||
template <typename C>
|
template <typename C>
|
||||||
static auto pos(C &&c, int i)
|
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>
|
template <typename C>
|
||||||
static auto cpos(C &&c, int i)
|
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
|
// Test if a type is a range, and whether we can modify it using the
|
||||||
// standard C++ container member functions insert, erase, and resize.
|
// 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:
|
protected:
|
||||||
// Helpers for calling a lambda with the tuple element at a runtime index.
|
// Helpers for calling a lambda with the tuple element at a runtime index.
|
||||||
template <typename Tuple, typename F, size_t ...Is>
|
template <typename Tuple, typename F, size_t ...Is>
|
||||||
static void call_at(Tuple &&tuple, size_t idx, std::index_sequence<Is...>, F &&function)
|
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>(
|
((Is == idx ? static_cast<void>(function(get<Is>(
|
||||||
QGenericItemModelDetails::refTo(std::forward<Tuple>(tuple)))))
|
QRangeModelDetails::refTo(std::forward<Tuple>(tuple)))))
|
||||||
: static_cast<void>(0)), ...);
|
: static_cast<void>(0)), ...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename F>
|
template <typename T, typename F>
|
||||||
static auto for_element_at(T &&tuple, size_t idx, F &&function)
|
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>;
|
constexpr size_t size = std::tuple_size_v<type>;
|
||||||
Q_ASSERT(idx < size);
|
Q_ASSERT(idx < size);
|
||||||
return call_at(std::forward<T>(tuple), idx, std::make_index_sequence<size>{},
|
return call_at(std::forward<T>(tuple), idx, std::make_index_sequence<size>{},
|
||||||
@ -537,7 +537,7 @@ protected:
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
static constexpr QMetaType meta_type_at(size_t idx)
|
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>;
|
constexpr auto size = std::tuple_size_v<type>;
|
||||||
Q_ASSERT(idx < size);
|
Q_ASSERT(idx < size);
|
||||||
return makeMetaTypes<type>(std::make_index_sequence<size>{}).at(idx);
|
return makeMetaTypes<type>(std::make_index_sequence<size>{}).at(idx);
|
||||||
@ -550,7 +550,7 @@ protected:
|
|||||||
return std::invoke(fn, obj, std::get<I>(tuple)...);
|
return std::invoke(fn, obj, std::get<I>(tuple)...);
|
||||||
}
|
}
|
||||||
template <typename Ret, typename Class, typename ...Args>
|
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)
|
void *ret, const void *args)
|
||||||
{
|
{
|
||||||
const auto &tuple = *static_cast<const std::tuple<Args&...> *>(args);
|
const auto &tuple = *static_cast<const std::tuple<Args&...> *>(args);
|
||||||
@ -558,7 +558,7 @@ protected:
|
|||||||
static_cast<Class *>(obj), fn, tuple);
|
static_cast<Class *>(obj), fn, tuple);
|
||||||
}
|
}
|
||||||
template <typename Ret, typename Class, typename ...Args>
|
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)
|
void *ret, const void *args)
|
||||||
{
|
{
|
||||||
const auto &tuple = *static_cast<const std::tuple<Args&...> *>(args);
|
const auto &tuple = *static_cast<const std::tuple<Args&...> *>(args);
|
||||||
@ -599,22 +599,22 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
// prototypes
|
// prototypes
|
||||||
static void callConst(ConstOp, const QGenericItemModelImplBase *, void *, const void *);
|
static void callConst(ConstOp, const QRangeModelImplBase *, void *, const void *);
|
||||||
static void call(Op, QGenericItemModelImplBase *, void *, const void *);
|
static void call(Op, QRangeModelImplBase *, void *, const void *);
|
||||||
|
|
||||||
using CallConstFN = decltype(callConst);
|
using CallConstFN = decltype(callConst);
|
||||||
using CallTupleFN = decltype(call);
|
using CallTupleFN = decltype(call);
|
||||||
|
|
||||||
CallConstFN *callConst_fn;
|
CallConstFN *callConst_fn;
|
||||||
CallTupleFN *call_fn;
|
CallTupleFN *call_fn;
|
||||||
QGenericItemModel *m_itemModel;
|
QRangeModel *m_rangeModel;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
template <typename Impl> // type deduction
|
template <typename Impl> // type deduction
|
||||||
explicit QGenericItemModelImplBase(QGenericItemModel *itemModel, const Impl *)
|
explicit QRangeModelImplBase(QRangeModel *itemModel, const Impl *)
|
||||||
: callConst_fn(&Impl::callConst), call_fn(&Impl::call), m_itemModel(itemModel)
|
: 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 QModelIndex createIndex(int row, int column, const void *ptr = nullptr) const;
|
||||||
inline void changePersistentIndexList(const QModelIndexList &from, const QModelIndexList &to);
|
inline void changePersistentIndexList(const QModelIndexList &from, const QModelIndexList &to);
|
||||||
@ -659,52 +659,52 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
template <typename Structure, typename Range,
|
template <typename Structure, typename Range,
|
||||||
typename Protocol = QGenericItemModelDetails::table_protocol_t<Range>>
|
typename Protocol = QRangeModelDetails::table_protocol_t<Range>>
|
||||||
class QGenericItemModelImpl : public QGenericItemModelImplBase
|
class QRangeModelImpl : public QRangeModelImplBase
|
||||||
{
|
{
|
||||||
Q_DISABLE_COPY_MOVE(QGenericItemModelImpl)
|
Q_DISABLE_COPY_MOVE(QRangeModelImpl)
|
||||||
public:
|
public:
|
||||||
using range_type = QGenericItemModelDetails::wrapped_t<Range>;
|
using range_type = QRangeModelDetails::wrapped_t<Range>;
|
||||||
using row_reference = decltype(*QGenericItemModelDetails::begin(std::declval<range_type&>()));
|
using row_reference = decltype(*QRangeModelDetails::begin(std::declval<range_type&>()));
|
||||||
using const_row_reference = decltype(*QGenericItemModelDetails::cbegin(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 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>() &&
|
static_assert(!QRangeModelDetails::is_any_of<range_type, std::optional>() &&
|
||||||
!QGenericItemModelDetails::is_any_of<row_type, std::optional>(),
|
!QRangeModelDetails::is_any_of<row_type, std::optional>(),
|
||||||
"Currently, std::optional is not supported for ranges and rows, as "
|
"Currently, std::optional is not supported for ranges and rows, as "
|
||||||
"it has range semantics in c++26. Once the required behavior is clarified, "
|
"it has range semantics in c++26. Once the required behavior is clarified, "
|
||||||
"std::optional for ranges and rows will be supported.");
|
"std::optional for ranges and rows will be supported.");
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
using Self = QGenericItemModelImpl<Structure, Range, Protocol>;
|
using Self = QRangeModelImpl<Structure, Range, Protocol>;
|
||||||
Structure& that() { return static_cast<Structure &>(*this); }
|
Structure& that() { return static_cast<Structure &>(*this); }
|
||||||
const Structure& that() const { return static_cast<const Structure &>(*this); }
|
const Structure& that() const { return static_cast<const Structure &>(*this); }
|
||||||
|
|
||||||
template <typename C>
|
template <typename C>
|
||||||
static constexpr int size(const C &c)
|
static constexpr int size(const C &c)
|
||||||
{
|
{
|
||||||
if (!QGenericItemModelDetails::isValid(c))
|
if (!QRangeModelDetails::isValid(c))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if constexpr (QGenericItemModelDetails::test_size<C>()) {
|
if constexpr (QRangeModelDetails::test_size<C>()) {
|
||||||
return int(std::size(c));
|
return int(std::size(c));
|
||||||
} else {
|
} else {
|
||||||
#if defined(__cpp_lib_ranges)
|
#if defined(__cpp_lib_ranges)
|
||||||
return int(std::ranges::distance(QGenericItemModelDetails::begin(c),
|
return int(std::ranges::distance(QRangeModelDetails::begin(c),
|
||||||
QGenericItemModelDetails::end(c)));
|
QRangeModelDetails::end(c)));
|
||||||
#else
|
#else
|
||||||
return int(std::distance(QGenericItemModelDetails::begin(c),
|
return int(std::distance(QRangeModelDetails::begin(c),
|
||||||
QGenericItemModelDetails::end(c)));
|
QRangeModelDetails::end(c)));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
using range_features = QGenericItemModelDetails::range_traits<range_type>;
|
using range_features = QRangeModelDetails::range_traits<range_type>;
|
||||||
using wrapped_row_type = QGenericItemModelDetails::wrapped_t<row_type>;
|
using wrapped_row_type = QRangeModelDetails::wrapped_t<row_type>;
|
||||||
using row_features = QGenericItemModelDetails::range_traits<wrapped_row_type>;
|
using row_features = QRangeModelDetails::range_traits<wrapped_row_type>;
|
||||||
using row_traits = QGenericItemModelDetails::row_traits<std::remove_cv_t<wrapped_row_type>>;
|
using row_traits = QRangeModelDetails::row_traits<std::remove_cv_t<wrapped_row_type>>;
|
||||||
using protocol_traits = QGenericItemModelDetails::protocol_traits<Range, protocol_type>;
|
using protocol_traits = QRangeModelDetails::protocol_traits<Range, protocol_type>;
|
||||||
|
|
||||||
static constexpr bool isMutable()
|
static constexpr bool isMutable()
|
||||||
{
|
{
|
||||||
@ -713,11 +713,11 @@ protected:
|
|||||||
&& Structure::is_mutable_impl;
|
&& 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_raw_pointers = std::is_pointer_v<row_type>;
|
||||||
static constexpr bool rows_are_owning_or_raw_pointers =
|
static constexpr bool rows_are_owning_or_raw_pointers =
|
||||||
QGenericItemModelDetails::is_owning_or_raw_pointer<row_type>();
|
QRangeModelDetails::is_owning_or_raw_pointer<row_type>();
|
||||||
static constexpr int static_column_count = QGenericItemModelDetails::static_size_v<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 one_dimensional_range = static_column_count == 0;
|
||||||
|
|
||||||
static constexpr bool dynamicRows() { return isMutable() && static_row_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 *;
|
using const_row_ptr = const wrapped_row_type *;
|
||||||
|
|
||||||
template <typename T>
|
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>>>;
|
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>,
|
std::is_pointer_v<Range>,
|
||||||
Range, std::remove_reference_t<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)");
|
"The range holding a move-only row-type must support insert(pos, start, end)");
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit QGenericItemModelImpl(Range &&model, Protocol&& protocol, QGenericItemModel *itemModel)
|
explicit QRangeModelImpl(Range &&model, Protocol&& protocol, QRangeModel *itemModel)
|
||||||
: QGenericItemModelImplBase(itemModel, static_cast<const Self*>(nullptr))
|
: QRangeModelImplBase(itemModel, static_cast<const Self*>(nullptr))
|
||||||
, m_data{std::forward<Range>(model)}
|
, m_data{std::forward<Range>(model)}
|
||||||
, m_protocol(std::forward<Protocol>(protocol))
|
, m_protocol(std::forward<Protocol>(protocol))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
// static interface, called by QGenericItemModelImplBase
|
// static interface, called by QRangeModelImplBase
|
||||||
static void callConst(ConstOp op, const QGenericItemModelImplBase *that, void *r, const void *args)
|
static void callConst(ConstOp op, const QRangeModelImplBase *that, void *r, const void *args)
|
||||||
{
|
{
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case Index: makeCall(that, &Self::index, r, args);
|
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) {
|
switch (op) {
|
||||||
case Destroy: delete static_cast<Structure *>(that);
|
case Destroy: delete static_cast<Structure *>(that);
|
||||||
@ -878,7 +878,7 @@ public:
|
|||||||
// we didn't remove the const of the range first.
|
// we didn't remove the const of the range first.
|
||||||
const_row_reference row = rowData(index);
|
const_row_reference row = rowData(index);
|
||||||
row_reference mutableRow = const_cast<row_reference>(row);
|
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){
|
for_element_at(mutableRow, index.column(), [&f](auto &&ref){
|
||||||
using target_type = decltype(ref);
|
using target_type = decltype(ref);
|
||||||
if constexpr (std::is_const_v<std::remove_reference_t<target_type>>)
|
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) {
|
const auto readData = [this, column = index.column(), &result, role](const auto &value) {
|
||||||
Q_UNUSED(this);
|
Q_UNUSED(this);
|
||||||
using value_type = q20::remove_cvref_t<decltype(value)>;
|
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 constexpr (has_metaobject<value_type>) {
|
||||||
if (row_traits::fixed_size() <= 1) {
|
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()
|
} else if (column <= row_traits::fixed_size()
|
||||||
&& (role == Qt::DisplayRole || role == Qt::EditRole)) {
|
&& (role == Qt::DisplayRole || role == Qt::EditRole)) {
|
||||||
result = readProperty(column, QGenericItemModelDetails::pointerTo(value));
|
result = readProperty(column, QRangeModelDetails::pointerTo(value));
|
||||||
}
|
}
|
||||||
} else if constexpr (multi_role::value) {
|
} else if constexpr (multi_role::value) {
|
||||||
const auto it = [this, &value, role]{
|
const auto it = [this, &value, role]{
|
||||||
@ -945,7 +945,7 @@ public:
|
|||||||
return std::as_const(value).find(roleNames().value(role));
|
return std::as_const(value).find(roleNames().value(role));
|
||||||
}();
|
}();
|
||||||
if (it != value.cend()) {
|
if (it != value.cend()) {
|
||||||
result = QGenericItemModelDetails::value(it);
|
result = QRangeModelDetails::value(it);
|
||||||
}
|
}
|
||||||
} else if (role == Qt::DisplayRole || role == Qt::EditRole) {
|
} else if (role == Qt::DisplayRole || role == Qt::EditRole) {
|
||||||
result = read(value);
|
result = read(value);
|
||||||
@ -965,14 +965,14 @@ public:
|
|||||||
const auto readItemData = [this, &result, &tried](auto &&value){
|
const auto readItemData = [this, &result, &tried](auto &&value){
|
||||||
Q_UNUSED(this);
|
Q_UNUSED(this);
|
||||||
using value_type = q20::remove_cvref_t<decltype(value)>;
|
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()) {
|
if constexpr (multi_role()) {
|
||||||
tried = true;
|
tried = true;
|
||||||
if constexpr (std::is_convertible_v<value_type, decltype(result)>) {
|
if constexpr (std::is_convertible_v<value_type, decltype(result)>) {
|
||||||
result = value;
|
result = value;
|
||||||
} else {
|
} else {
|
||||||
for (auto it = std::cbegin(value); it != std::cend(value); ++it) {
|
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);
|
Q_UNUSED(this);
|
||||||
if constexpr (multi_role::int_key)
|
if constexpr (multi_role::int_key)
|
||||||
return int(key);
|
return int(key);
|
||||||
@ -981,13 +981,13 @@ public:
|
|||||||
}();
|
}();
|
||||||
|
|
||||||
if (role != -1)
|
if (role != -1)
|
||||||
result.insert(role, QGenericItemModelDetails::value(it));
|
result.insert(role, QRangeModelDetails::value(it));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if constexpr (has_metaobject<value_type>) {
|
} else if constexpr (has_metaobject<value_type>) {
|
||||||
if (row_traits::fixed_size() <= 1) {
|
if (row_traits::fixed_size() <= 1) {
|
||||||
tried = true;
|
tried = true;
|
||||||
using meta_type = QGenericItemModelDetails::wrapped_t<value_type>;
|
using meta_type = QRangeModelDetails::wrapped_t<value_type>;
|
||||||
const QMetaObject &mo = meta_type::staticMetaObject;
|
const QMetaObject &mo = meta_type::staticMetaObject;
|
||||||
for (auto &&[role, roleName] : roleNames().asKeyValueRange()) {
|
for (auto &&[role, roleName] : roleNames().asKeyValueRange()) {
|
||||||
QVariant data;
|
QVariant data;
|
||||||
@ -999,7 +999,7 @@ public:
|
|||||||
if (pi >= 0) {
|
if (pi >= 0) {
|
||||||
const QMetaProperty prop = mo.property(pi);
|
const QMetaProperty prop = mo.property(pi);
|
||||||
if (prop.isValid())
|
if (prop.isValid())
|
||||||
data = prop.readOnGadget(QGenericItemModelDetails::pointerTo(value));
|
data = prop.readOnGadget(QRangeModelDetails::pointerTo(value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (data.isValid())
|
if (data.isValid())
|
||||||
@ -1034,7 +1034,7 @@ public:
|
|||||||
|
|
||||||
const auto writeData = [this, column = index.column(), &data, role](auto &&target) -> bool {
|
const auto writeData = [this, column = index.column(), &data, role](auto &&target) -> bool {
|
||||||
using value_type = q20::remove_cvref_t<decltype(target)>;
|
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 constexpr (has_metaobject<value_type>) {
|
||||||
if (QMetaType::fromType<value_type>() == data.metaType()) {
|
if (QMetaType::fromType<value_type>() == data.metaType()) {
|
||||||
if constexpr (std::is_copy_assignable_v<value_type>) {
|
if constexpr (std::is_copy_assignable_v<value_type>) {
|
||||||
@ -1045,10 +1045,10 @@ public:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else if (row_traits::fixed_size() <= 1) {
|
} 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()
|
} else if (column <= row_traits::fixed_size()
|
||||||
&& (role == Qt::DisplayRole || role == Qt::EditRole)) {
|
&& (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) {
|
} else if constexpr (multi_role::value) {
|
||||||
Qt::ItemDataRole roleToSet = Qt::ItemDataRole(role);
|
Qt::ItemDataRole roleToSet = Qt::ItemDataRole(role);
|
||||||
@ -1094,7 +1094,7 @@ public:
|
|||||||
auto writeItemData = [this, &tried, &data](auto &target) -> bool {
|
auto writeItemData = [this, &tried, &data](auto &target) -> bool {
|
||||||
Q_UNUSED(this);
|
Q_UNUSED(this);
|
||||||
using value_type = q20::remove_cvref_t<decltype(target)>;
|
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()) {
|
if constexpr (multi_role()) {
|
||||||
using key_type = typename value_type::key_type;
|
using key_type = typename value_type::key_type;
|
||||||
tried = true;
|
tried = true;
|
||||||
@ -1124,7 +1124,7 @@ public:
|
|||||||
} else if constexpr (has_metaobject<value_type>) {
|
} else if constexpr (has_metaobject<value_type>) {
|
||||||
if (row_traits::fixed_size() <= 1) {
|
if (row_traits::fixed_size() <= 1) {
|
||||||
tried = true;
|
tried = true;
|
||||||
using meta_type = QGenericItemModelDetails::wrapped_t<value_type>;
|
using meta_type = QRangeModelDetails::wrapped_t<value_type>;
|
||||||
const QMetaObject &mo = meta_type::staticMetaObject;
|
const QMetaObject &mo = meta_type::staticMetaObject;
|
||||||
// transactional: if possible, modify a copy and only
|
// transactional: if possible, modify a copy and only
|
||||||
// update target if all values from data could be stored.
|
// update target if all values from data could be stored.
|
||||||
@ -1149,7 +1149,7 @@ public:
|
|||||||
if (pi >= 0) {
|
if (pi >= 0) {
|
||||||
const QMetaProperty prop = mo.property(pi);
|
const QMetaProperty prop = mo.property(pi);
|
||||||
if (prop.isValid())
|
if (prop.isValid())
|
||||||
written = prop.writeOnGadget(QGenericItemModelDetails::pointerTo(targetCopy), value);
|
written = prop.writeOnGadget(QRangeModelDetails::pointerTo(targetCopy), value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!written) {
|
if (!written) {
|
||||||
@ -1199,9 +1199,9 @@ public:
|
|||||||
if constexpr (has_metaobject<row_type>) {
|
if constexpr (has_metaobject<row_type>) {
|
||||||
if (row_traits::fixed_size() <= 1) {
|
if (row_traits::fixed_size() <= 1) {
|
||||||
// multi-role object/gadget: reset all properties
|
// 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()) {
|
} 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
|
} else { // normal structs, values, associative containers
|
||||||
target = {};
|
target = {};
|
||||||
@ -1226,8 +1226,8 @@ public:
|
|||||||
|
|
||||||
beginInsertColumns(parent, column, column + count - 1);
|
beginInsertColumns(parent, column, column + count - 1);
|
||||||
for (auto &child : *children) {
|
for (auto &child : *children) {
|
||||||
auto it = QGenericItemModelDetails::pos(child, column);
|
auto it = QRangeModelDetails::pos(child, column);
|
||||||
QGenericItemModelDetails::refTo(child).insert(it, count, {});
|
QRangeModelDetails::refTo(child).insert(it, count, {});
|
||||||
}
|
}
|
||||||
endInsertColumns();
|
endInsertColumns();
|
||||||
return true;
|
return true;
|
||||||
@ -1247,8 +1247,8 @@ public:
|
|||||||
|
|
||||||
beginRemoveColumns(parent, column, column + count - 1);
|
beginRemoveColumns(parent, column, column + count - 1);
|
||||||
for (auto &child : *children) {
|
for (auto &child : *children) {
|
||||||
const auto start = QGenericItemModelDetails::pos(child, column);
|
const auto start = QRangeModelDetails::pos(child, column);
|
||||||
QGenericItemModelDetails::refTo(child).erase(start, std::next(start, count));
|
QRangeModelDetails::refTo(child).erase(start, std::next(start, count));
|
||||||
}
|
}
|
||||||
endRemoveColumns();
|
endRemoveColumns();
|
||||||
return true;
|
return true;
|
||||||
@ -1279,9 +1279,9 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (auto &child : *children) {
|
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 middle = std::next(first, count);
|
||||||
const auto last = QGenericItemModelDetails::pos(child, destColumn);
|
const auto last = QRangeModelDetails::pos(child, destColumn);
|
||||||
|
|
||||||
if (sourceColumn < destColumn) // moving right
|
if (sourceColumn < destColumn) // moving right
|
||||||
std::rotate(first, middle, last);
|
std::rotate(first, middle, last);
|
||||||
@ -1307,7 +1307,7 @@ public:
|
|||||||
|
|
||||||
beginInsertRows(parent, row, row + count - 1);
|
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) {
|
if constexpr (range_features::has_insert_range) {
|
||||||
children->insert(pos, generator, EmptyRowGenerator{count});
|
children->insert(pos, generator, EmptyRowGenerator{count});
|
||||||
} else if constexpr (rows_are_owning_or_raw_pointers) {
|
} else if constexpr (rows_are_owning_or_raw_pointers) {
|
||||||
@ -1352,7 +1352,7 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
{ // erase invalidates iterators
|
{ // erase invalidates iterators
|
||||||
const auto begin = QGenericItemModelDetails::pos(children, row);
|
const auto begin = QRangeModelDetails::pos(children, row);
|
||||||
const auto end = std::next(begin, count);
|
const auto end = std::next(begin, count);
|
||||||
that().deleteRemovedRows(begin, end);
|
that().deleteRemovedRows(begin, end);
|
||||||
children->erase(begin, end);
|
children->erase(begin, end);
|
||||||
@ -1397,9 +1397,9 @@ public:
|
|||||||
if (!beginMoveRows(sourceParent, sourceRow, sourceRow + count - 1, destParent, destRow))
|
if (!beginMoveRows(sourceParent, sourceRow, sourceRow + count - 1, destParent, destRow))
|
||||||
return false;
|
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 middle = std::next(first, count);
|
||||||
const auto last = QGenericItemModelDetails::pos(source, destRow);
|
const auto last = QRangeModelDetails::pos(source, destRow);
|
||||||
|
|
||||||
if (sourceRow < destRow) // moving down
|
if (sourceRow < destRow) // moving down
|
||||||
std::rotate(first, middle, last);
|
std::rotate(first, middle, last);
|
||||||
@ -1416,7 +1416,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
~QGenericItemModelImpl()
|
~QRangeModelImpl()
|
||||||
{
|
{
|
||||||
// We delete row objects if we are not operating on a reference or pointer
|
// 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
|
// 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,
|
// client can never delete those. But copied rows will be the same pointer,
|
||||||
// which we must not delete (as we didn't create them).
|
// which we must not delete (as we didn't create them).
|
||||||
if constexpr (protocol_traits::has_deleteRow && !std::is_pointer_v<Range>
|
if constexpr (protocol_traits::has_deleteRow && !std::is_pointer_v<Range>
|
||||||
&& !QGenericItemModelDetails::is_any_of<Range, std::reference_wrapper>()) {
|
&& !QRangeModelDetails::is_any_of<Range, std::reference_wrapper>()) {
|
||||||
const auto begin = QGenericItemModelDetails::begin(*m_data.model());
|
const auto begin = QRangeModelDetails::begin(*m_data.model());
|
||||||
const auto end = QGenericItemModelDetails::end(*m_data.model());
|
const auto end = QRangeModelDetails::end(*m_data.model());
|
||||||
that().deleteRemovedRows(begin, end);
|
that().deleteRemovedRows(begin, end);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1461,9 +1461,9 @@ protected:
|
|||||||
|
|
||||||
if constexpr (one_dimensional_range) {
|
if constexpr (one_dimensional_range) {
|
||||||
result = writer(row);
|
result = writer(row);
|
||||||
} else if (QGenericItemModelDetails::isValid(row)) {
|
} else if (QRangeModelDetails::isValid(row)) {
|
||||||
if constexpr (dynamicColumns()) {
|
if constexpr (dynamicColumns()) {
|
||||||
result = writer(*QGenericItemModelDetails::pos(row, index.column()));
|
result = writer(*QRangeModelDetails::pos(row, index.column()));
|
||||||
} else {
|
} else {
|
||||||
for_element_at(row, index.column(), [&writer, &result](auto &&target) {
|
for_element_at(row, index.column(), [&writer, &result](auto &&target) {
|
||||||
using target_type = decltype(target);
|
using target_type = decltype(target);
|
||||||
@ -1484,9 +1484,9 @@ protected:
|
|||||||
const_row_reference row = rowData(index);
|
const_row_reference row = rowData(index);
|
||||||
if constexpr (one_dimensional_range) {
|
if constexpr (one_dimensional_range) {
|
||||||
return reader(row);
|
return reader(row);
|
||||||
} else if (QGenericItemModelDetails::isValid(row)) {
|
} else if (QRangeModelDetails::isValid(row)) {
|
||||||
if constexpr (dynamicColumns())
|
if constexpr (dynamicColumns())
|
||||||
reader(*QGenericItemModelDetails::cpos(row, index.column()));
|
reader(*QRangeModelDetails::cpos(row, index.column()));
|
||||||
else
|
else
|
||||||
for_element_at(row, index.column(), std::forward<F>(reader));
|
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); }
|
const protocol_type& protocol() const { return QRangeModelDetails::refTo(m_protocol); }
|
||||||
protocol_type& protocol() { return QGenericItemModelDetails::refTo(m_protocol); }
|
protocol_type& protocol() { return QRangeModelDetails::refTo(m_protocol); }
|
||||||
|
|
||||||
ModelData m_data;
|
ModelData m_data;
|
||||||
Protocol m_protocol;
|
Protocol m_protocol;
|
||||||
@ -1695,10 +1695,10 @@ protected:
|
|||||||
// support through a protocol type.
|
// support through a protocol type.
|
||||||
template <typename Range, typename Protocol>
|
template <typename Range, typename Protocol>
|
||||||
class QGenericTreeItemModelImpl
|
class QGenericTreeItemModelImpl
|
||||||
: public QGenericItemModelImpl<QGenericTreeItemModelImpl<Range, Protocol>, Range, Protocol>
|
: public QRangeModelImpl<QGenericTreeItemModelImpl<Range, Protocol>, Range, Protocol>
|
||||||
{
|
{
|
||||||
using Base = QGenericItemModelImpl<QGenericTreeItemModelImpl<Range, Protocol>, Range, Protocol>;
|
using Base = QRangeModelImpl<QGenericTreeItemModelImpl<Range, Protocol>, Range, Protocol>;
|
||||||
friend class QGenericItemModelImpl<QGenericTreeItemModelImpl<Range, Protocol>, Range, Protocol>;
|
friend class QRangeModelImpl<QGenericTreeItemModelImpl<Range, Protocol>, Range, Protocol>;
|
||||||
|
|
||||||
using range_type = typename Base::range_type;
|
using range_type = typename Base::range_type;
|
||||||
using range_features = typename Base::range_features;
|
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 is_mutable_impl = tree_traits::has_mutable_childRows;
|
||||||
|
|
||||||
static constexpr bool rows_are_any_refs_or_pointers = Base::rows_are_raw_pointers ||
|
static constexpr bool rows_are_any_refs_or_pointers = Base::rows_are_raw_pointers ||
|
||||||
QGenericItemModelDetails::is_smart_ptr<row_type>() ||
|
QRangeModelDetails::is_smart_ptr<row_type>() ||
|
||||||
QGenericItemModelDetails::is_any_of<row_type, std::reference_wrapper>();
|
QRangeModelDetails::is_any_of<row_type, std::reference_wrapper>();
|
||||||
static_assert(!Base::dynamicColumns(), "A tree must have a static number of columns!");
|
static_assert(!Base::dynamicColumns(), "A tree must have a static number of columns!");
|
||||||
|
|
||||||
public:
|
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)
|
: 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_row_ptr grandParent = static_cast<const_row_ptr>(parent.constInternalPointer());
|
||||||
const auto &parentSiblings = childrenOf(grandParent);
|
const auto &parentSiblings = childrenOf(grandParent);
|
||||||
const auto it = QGenericItemModelDetails::cpos(parentSiblings, parent.row());
|
const auto it = QRangeModelDetails::cpos(parentSiblings, parent.row());
|
||||||
return this->createIndex(row, column, QGenericItemModelDetails::pointerTo(*it));
|
return this->createIndex(row, column, QRangeModelDetails::pointerTo(*it));
|
||||||
}
|
}
|
||||||
|
|
||||||
QModelIndex parent(const QModelIndex &child) const
|
QModelIndex parent(const QModelIndex &child) const
|
||||||
@ -1745,17 +1745,17 @@ protected:
|
|||||||
return {};
|
return {};
|
||||||
|
|
||||||
// get the siblings of the parent via the grand parent
|
// get the siblings of the parent via the grand parent
|
||||||
decltype(auto) grandParent = this->protocol().parentRow(QGenericItemModelDetails::refTo(parentRow));
|
decltype(auto) grandParent = this->protocol().parentRow(QRangeModelDetails::refTo(parentRow));
|
||||||
const range_type &parentSiblings = childrenOf(QGenericItemModelDetails::pointerTo(grandParent));
|
const range_type &parentSiblings = childrenOf(QRangeModelDetails::pointerTo(grandParent));
|
||||||
// find the index of parentRow
|
// find the index of parentRow
|
||||||
const auto begin = QGenericItemModelDetails::cbegin(parentSiblings);
|
const auto begin = QRangeModelDetails::cbegin(parentSiblings);
|
||||||
const auto end = QGenericItemModelDetails::cend(parentSiblings);
|
const auto end = QRangeModelDetails::cend(parentSiblings);
|
||||||
const auto it = std::find_if(begin, end, [parentRow](auto &&s){
|
const auto it = std::find_if(begin, end, [parentRow](auto &&s){
|
||||||
return QGenericItemModelDetails::pointerTo(s) == parentRow;
|
return QRangeModelDetails::pointerTo(s) == parentRow;
|
||||||
});
|
});
|
||||||
if (it != end)
|
if (it != end)
|
||||||
return this->createIndex(std::distance(begin, it), 0,
|
return this->createIndex(std::distance(begin, it), 0,
|
||||||
QGenericItemModelDetails::pointerTo(grandParent));
|
QRangeModelDetails::pointerTo(grandParent));
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1826,9 +1826,9 @@ protected:
|
|||||||
|
|
||||||
// If we can insert data from another range into, then
|
// If we can insert data from another range into, then
|
||||||
// use that to move the old data over.
|
// 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) {
|
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);
|
const auto sourceEnd = std::next(sourceStart, count);
|
||||||
|
|
||||||
destination->insert(destStart, std::move_iterator(sourceStart),
|
destination->insert(destStart, std::move_iterator(sourceStart),
|
||||||
@ -1839,7 +1839,7 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
row_ptr parentRow = destParent.isValid()
|
row_ptr parentRow = destParent.isValid()
|
||||||
? QGenericItemModelDetails::pointerTo(this->rowData(destParent))
|
? QRangeModelDetails::pointerTo(this->rowData(destParent))
|
||||||
: nullptr;
|
: nullptr;
|
||||||
|
|
||||||
// if the source's parent was already inside the new parent row,
|
// 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
|
// 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 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);
|
const auto sourceEnd = std::next(sourceStart, count);
|
||||||
|
|
||||||
for (auto write = writeStart, read = sourceStart; write != writeEnd; ++write, ++read) {
|
for (auto write = writeStart, read = sourceStart; write != writeEnd; ++write, ++read) {
|
||||||
@ -1866,7 +1866,7 @@ protected:
|
|||||||
// only fix the parent pointer
|
// only fix the parent pointer
|
||||||
if constexpr (!range_features::has_insert_range)
|
if constexpr (!range_features::has_insert_range)
|
||||||
*write = std::move(*read);
|
*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
|
// remove the old rows from the source parent
|
||||||
source->erase(sourceStart, sourceEnd);
|
source->erase(sourceStart, sourceEnd);
|
||||||
@ -1889,9 +1889,9 @@ protected:
|
|||||||
// to change the parent of a row.
|
// to change the parent of a row.
|
||||||
static_assert(tree_traits::has_setParentRow);
|
static_assert(tree_traits::has_setParentRow);
|
||||||
row_type empty_row = this->protocol().newRow();
|
row_type empty_row = this->protocol().newRow();
|
||||||
if (QGenericItemModelDetails::isValid(empty_row) && parent.isValid()) {
|
if (QRangeModelDetails::isValid(empty_row) && parent.isValid()) {
|
||||||
this->protocol().setParentRow(QGenericItemModelDetails::refTo(empty_row),
|
this->protocol().setParentRow(QRangeModelDetails::refTo(empty_row),
|
||||||
QGenericItemModelDetails::pointerTo(this->rowData(parent)));
|
QRangeModelDetails::pointerTo(this->rowData(parent)));
|
||||||
}
|
}
|
||||||
return empty_row;
|
return empty_row;
|
||||||
}
|
}
|
||||||
@ -1908,15 +1908,15 @@ protected:
|
|||||||
void resetParentInChildren(range_type *children)
|
void resetParentInChildren(range_type *children)
|
||||||
{
|
{
|
||||||
if constexpr (tree_traits::has_setParentRow && !rows_are_any_refs_or_pointers) {
|
if constexpr (tree_traits::has_setParentRow && !rows_are_any_refs_or_pointers) {
|
||||||
const auto begin = QGenericItemModelDetails::begin(*children);
|
const auto begin = QRangeModelDetails::begin(*children);
|
||||||
const auto end = QGenericItemModelDetails::end(*children);
|
const auto end = QRangeModelDetails::end(*children);
|
||||||
for (auto it = begin; it != end; ++it) {
|
for (auto it = begin; it != end; ++it) {
|
||||||
if (auto &maybeChildren = this->protocol().childRows(*it)) {
|
if (auto &maybeChildren = this->protocol().childRows(*it)) {
|
||||||
QModelIndexList fromIndexes;
|
QModelIndexList fromIndexes;
|
||||||
QModelIndexList toIndexes;
|
QModelIndexList toIndexes;
|
||||||
fromIndexes.reserve(Base::size(*maybeChildren));
|
fromIndexes.reserve(Base::size(*maybeChildren));
|
||||||
toIndexes.reserve(Base::size(*maybeChildren));
|
toIndexes.reserve(Base::size(*maybeChildren));
|
||||||
auto *parentRow = QGenericItemModelDetails::pointerTo(*it);
|
auto *parentRow = QRangeModelDetails::pointerTo(*it);
|
||||||
|
|
||||||
int row = 0;
|
int row = 0;
|
||||||
for (auto &child : *maybeChildren) {
|
for (auto &child : *maybeChildren) {
|
||||||
@ -1929,7 +1929,7 @@ protected:
|
|||||||
++row;
|
++row;
|
||||||
}
|
}
|
||||||
this->changePersistentIndexList(fromIndexes, toIndexes);
|
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_row_ptr parentRow = static_cast<const_row_ptr>(index.constInternalPointer());
|
||||||
const range_type &siblings = childrenOf(parentRow);
|
const range_type &siblings = childrenOf(parentRow);
|
||||||
Q_ASSERT(index.row() < int(Base::size(siblings)));
|
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)
|
decltype(auto) rowDataImpl(const QModelIndex &index)
|
||||||
@ -1948,47 +1948,47 @@ protected:
|
|||||||
row_ptr parentRow = static_cast<row_ptr>(index.internalPointer());
|
row_ptr parentRow = static_cast<row_ptr>(index.internalPointer());
|
||||||
range_type &siblings = childrenOf(parentRow);
|
range_type &siblings = childrenOf(parentRow);
|
||||||
Q_ASSERT(index.row() < int(Base::size(siblings)));
|
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 range_type *childRangeImpl(const QModelIndex &index) const
|
||||||
{
|
{
|
||||||
const auto &row = this->rowData(index);
|
const auto &row = this->rowData(index);
|
||||||
if (!QGenericItemModelDetails::isValid(row))
|
if (!QRangeModelDetails::isValid(row))
|
||||||
return static_cast<const range_type *>(nullptr);
|
return static_cast<const range_type *>(nullptr);
|
||||||
|
|
||||||
decltype(auto) children = this->protocol().childRows(QGenericItemModelDetails::refTo(row));
|
decltype(auto) children = this->protocol().childRows(QRangeModelDetails::refTo(row));
|
||||||
return QGenericItemModelDetails::pointerTo(std::forward<decltype(children)>(children));
|
return QRangeModelDetails::pointerTo(std::forward<decltype(children)>(children));
|
||||||
}
|
}
|
||||||
|
|
||||||
range_type *childRangeImpl(const QModelIndex &index)
|
range_type *childRangeImpl(const QModelIndex &index)
|
||||||
{
|
{
|
||||||
auto &row = this->rowData(index);
|
auto &row = this->rowData(index);
|
||||||
if (!QGenericItemModelDetails::isValid(row))
|
if (!QRangeModelDetails::isValid(row))
|
||||||
return static_cast<range_type *>(nullptr);
|
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)>;
|
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>()) {
|
&& std::is_default_constructible<typename Children::value_type>()) {
|
||||||
if (!children)
|
if (!children)
|
||||||
children.emplace(range_type{});
|
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
|
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();
|
: *this->m_data.model();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
range_type &childrenOf(row_ptr row)
|
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();
|
: *this->m_data.model();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -1996,10 +1996,10 @@ private:
|
|||||||
// specialization for flat models without protocol
|
// specialization for flat models without protocol
|
||||||
template <typename Range>
|
template <typename Range>
|
||||||
class QGenericTableItemModelImpl
|
class QGenericTableItemModelImpl
|
||||||
: public QGenericItemModelImpl<QGenericTableItemModelImpl<Range>, Range>
|
: public QRangeModelImpl<QGenericTableItemModelImpl<Range>, Range>
|
||||||
{
|
{
|
||||||
using Base = QGenericItemModelImpl<QGenericTableItemModelImpl<Range>, Range>;
|
using Base = QRangeModelImpl<QGenericTableItemModelImpl<Range>, Range>;
|
||||||
friend class QGenericItemModelImpl<QGenericTableItemModelImpl<Range>, Range>;
|
friend class QRangeModelImpl<QGenericTableItemModelImpl<Range>, Range>;
|
||||||
|
|
||||||
using range_type = typename Base::range_type;
|
using range_type = typename Base::range_type;
|
||||||
using range_features = typename Base::range_features;
|
using range_features = typename Base::range_features;
|
||||||
@ -2011,7 +2011,7 @@ class QGenericTableItemModelImpl
|
|||||||
static constexpr bool is_mutable_impl = true;
|
static constexpr bool is_mutable_impl = true;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit QGenericTableItemModelImpl(Range &&model, QGenericItemModel *itemModel)
|
explicit QGenericTableItemModelImpl(Range &&model, QRangeModel *itemModel)
|
||||||
: Base(std::forward<Range>(model), {}, itemModel)
|
: Base(std::forward<Range>(model), {}, itemModel)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
@ -2019,10 +2019,10 @@ protected:
|
|||||||
QModelIndex indexImpl(int row, int column, const QModelIndex &) const
|
QModelIndex indexImpl(int row, int column, const QModelIndex &) const
|
||||||
{
|
{
|
||||||
if constexpr (Base::dynamicColumns()) {
|
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);
|
return this->createIndex(row, column);
|
||||||
// if we got here, then column < columnCount(), but this row is to short
|
// 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 {};
|
return {};
|
||||||
} else {
|
} else {
|
||||||
return this->createIndex(row, column);
|
return this->createIndex(row, column);
|
||||||
@ -2050,7 +2050,7 @@ protected:
|
|||||||
if constexpr (Base::dynamicColumns()) {
|
if constexpr (Base::dynamicColumns()) {
|
||||||
return int(Base::size(*this->m_data.model()) == 0
|
return int(Base::size(*this->m_data.model()) == 0
|
||||||
? 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) {
|
} else if constexpr (Base::one_dimensional_range) {
|
||||||
return row_traits::fixed_size();
|
return row_traits::fixed_size();
|
||||||
} else {
|
} else {
|
||||||
@ -2096,8 +2096,8 @@ protected:
|
|||||||
|
|
||||||
// dynamically sized rows all have to have the same column count
|
// dynamically sized rows all have to have the same column count
|
||||||
if constexpr (Base::dynamicColumns() && row_features::has_resize) {
|
if constexpr (Base::dynamicColumns() && row_features::has_resize) {
|
||||||
if (QGenericItemModelDetails::isValid(empty_row))
|
if (QRangeModelDetails::isValid(empty_row))
|
||||||
QGenericItemModelDetails::refTo(empty_row).resize(this->itemModel().columnCount());
|
QRangeModelDetails::refTo(empty_row).resize(this->itemModel().columnCount());
|
||||||
}
|
}
|
||||||
|
|
||||||
return empty_row;
|
return empty_row;
|
||||||
@ -2115,13 +2115,13 @@ protected:
|
|||||||
decltype(auto) rowDataImpl(const QModelIndex &index) const
|
decltype(auto) rowDataImpl(const QModelIndex &index) const
|
||||||
{
|
{
|
||||||
Q_ASSERT(index.row() < int(Base::size(*this->m_data.model())));
|
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)
|
decltype(auto) rowDataImpl(const QModelIndex &index)
|
||||||
{
|
{
|
||||||
Q_ASSERT(index.row() < int(Base::size(*this->m_data.model())));
|
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
|
auto childRangeImpl(const QModelIndex &) const
|
||||||
@ -2149,4 +2149,4 @@ QT_END_NAMESPACE
|
|||||||
|
|
||||||
#endif // Q_QDOC
|
#endif // Q_QDOC
|
||||||
|
|
||||||
#endif // QGENERICITEMMODEL_IMPL_H
|
#endif // QRANGEMODEL_IMPL_H
|
@ -2,7 +2,7 @@
|
|||||||
# SPDX-License-Identifier: BSD-3-Clause
|
# SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
add_subdirectory(qstringlistmodel)
|
add_subdirectory(qstringlistmodel)
|
||||||
add_subdirectory(qgenericitemmodel)
|
add_subdirectory(qrangemodel)
|
||||||
if(TARGET Qt::Gui)
|
if(TARGET Qt::Gui)
|
||||||
add_subdirectory(qabstractitemmodel)
|
add_subdirectory(qabstractitemmodel)
|
||||||
if(QT_FEATURE_proxymodel)
|
if(QT_FEATURE_proxymodel)
|
||||||
|
@ -2,18 +2,18 @@
|
|||||||
# SPDX-License-Identifier: BSD-3-Clause
|
# SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
#####################################################################
|
#####################################################################
|
||||||
## tst_qgenericitemmodel Test:
|
## tst_qrangemodel Test:
|
||||||
#####################################################################
|
#####################################################################
|
||||||
|
|
||||||
if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
|
if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
|
||||||
cmake_minimum_required(VERSION 3.16)
|
cmake_minimum_required(VERSION 3.16)
|
||||||
project(tst_qgenericitemmodel LANGUAGES CXX)
|
project(tst_qrangemodel LANGUAGES CXX)
|
||||||
find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
|
find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
qt_internal_add_test(tst_qgenericitemmodel
|
qt_internal_add_test(tst_qrangemodel
|
||||||
SOURCES
|
SOURCES
|
||||||
tst_qgenericitemmodel.cpp
|
tst_qrangemodel.cpp
|
||||||
LIBRARIES
|
LIBRARIES
|
||||||
Qt::Gui
|
Qt::Gui
|
||||||
)
|
)
|
||||||
@ -24,6 +24,6 @@ if (
|
|||||||
# gcc 10.2.0 chokes in a standard library header
|
# 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))
|
(NOT CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 10.2.0))
|
||||||
if ("${CMAKE_CXX_COMPILE_FEATURES}" MATCHES "cxx_std_20")
|
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()
|
||||||
endif()
|
endif()
|
@ -2,7 +2,7 @@
|
|||||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
|
||||||
|
|
||||||
#include <QTest>
|
#include <QTest>
|
||||||
#include <QtCore/qgenericitemmodel.h>
|
#include <QtCore/qrangemodel.h>
|
||||||
#include <QtCore/qjsondocument.h>
|
#include <QtCore/qjsondocument.h>
|
||||||
#include <QtCore/qjsonarray.h>
|
#include <QtCore/qjsonarray.h>
|
||||||
|
|
||||||
@ -273,7 +273,7 @@ namespace std {
|
|||||||
{ using type = decltype(get<I>(std::declval<tree_row>())); };
|
{ using type = decltype(get<I>(std::declval<tree_row>())); };
|
||||||
}
|
}
|
||||||
|
|
||||||
class tst_QGenericItemModel : public QObject
|
class tst_QRangeModel : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
@ -459,7 +459,7 @@ private:
|
|||||||
{"green", Qt::green, "0x00ff00"},
|
{"green", Qt::green, "0x00ff00"},
|
||||||
{"blue", Qt::blue, "0x0000ff"},
|
{"blue", Qt::blue, "0x0000ff"},
|
||||||
};
|
};
|
||||||
std::vector<QGenericItemModel::SingleColumn<Item>> listOfGadgets = {
|
std::vector<QRangeModel::SingleColumn<Item>> listOfGadgets = {
|
||||||
{{"red", Qt::red, "0xff0000"}},
|
{{"red", Qt::red, "0xff0000"}},
|
||||||
{{"green", Qt::green, "0x00ff00"}},
|
{{"green", Qt::green, "0x00ff00"}},
|
||||||
{{"blue", Qt::blue, "0x0000ff"}},
|
{{"blue", Qt::blue, "0x0000ff"}},
|
||||||
@ -480,7 +480,7 @@ private:
|
|||||||
MetaObjectTuple mot1;
|
MetaObjectTuple mot1;
|
||||||
MetaObjectTuple mot2;
|
MetaObjectTuple mot2;
|
||||||
MetaObjectTuple mot3;
|
MetaObjectTuple mot3;
|
||||||
std::vector<QGenericItemModel::SingleColumn<MetaObjectTuple *>> listOfMetaObjectTuple = {
|
std::vector<QRangeModel::SingleColumn<MetaObjectTuple *>> listOfMetaObjectTuple = {
|
||||||
&mot1,
|
&mot1,
|
||||||
&mot2,
|
&mot2,
|
||||||
&mot3,
|
&mot3,
|
||||||
@ -488,7 +488,7 @@ private:
|
|||||||
MetaObjectTuple mot4;
|
MetaObjectTuple mot4;
|
||||||
MetaObjectTuple mot5;
|
MetaObjectTuple mot5;
|
||||||
MetaObjectTuple mot6;
|
MetaObjectTuple mot6;
|
||||||
std::vector<QGenericItemModel::MultiColumn<MetaObjectTuple *>> tableOfMetaObjectTuple = {
|
std::vector<QRangeModel::MultiColumn<MetaObjectTuple *>> tableOfMetaObjectTuple = {
|
||||||
{&mot4},
|
{&mot4},
|
||||||
{&mot5},
|
{&mot5},
|
||||||
{&mot6},
|
{&mot6},
|
||||||
@ -613,7 +613,7 @@ public:
|
|||||||
Q_DECLARE_FLAGS(ChangeActions, ChangeAction);
|
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>()>;
|
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>
|
template <typename T, std::enable_if_t<!std::is_copy_assignable_v<T>, bool> = true>
|
||||||
void createBackup(QObject* , T& ) {}
|
void createBackup(QObject* , T& ) {}
|
||||||
|
|
||||||
void tst_QGenericItemModel::createTestData()
|
void tst_QRangeModel::createTestData()
|
||||||
{
|
{
|
||||||
m_data.reset(new Data);
|
m_data.reset(new Data);
|
||||||
|
|
||||||
@ -643,7 +643,7 @@ void tst_QGenericItemModel::createTestData()
|
|||||||
#define ADD_HELPER(Model, Tag, Policy, ColumnCount, Actions) \
|
#define ADD_HELPER(Model, Tag, Policy, ColumnCount, Actions) \
|
||||||
{ \
|
{ \
|
||||||
Factory factory = [this]() -> std::unique_ptr<QAbstractItemModel> { \
|
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); \
|
createBackup(result.get(), m_data->Model); \
|
||||||
return result; \
|
return result; \
|
||||||
}; \
|
}; \
|
||||||
@ -735,7 +735,7 @@ void tst_QGenericItemModel::createTestData()
|
|||||||
{"2/0", "2/1", "2/2", "2/3"},
|
{"2/0", "2/1", "2/2", "2/3"},
|
||||||
{"3/0", "3/1", "3/2", "3/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);
|
}) << 4 << 4 << ChangeActions(ChangeAction::All);
|
||||||
|
|
||||||
// moved list of pointers -> model takes ownership
|
// moved list of pointers -> model takes ownership
|
||||||
@ -746,25 +746,25 @@ void tst_QGenericItemModel::createTestData()
|
|||||||
};
|
};
|
||||||
|
|
||||||
return std::unique_ptr<QAbstractItemModel>(
|
return std::unique_ptr<QAbstractItemModel>(
|
||||||
new QGenericItemModel(std::move(movedListOfObjects))
|
new QRangeModel(std::move(movedListOfObjects))
|
||||||
);
|
);
|
||||||
}) << 6 << 2 << (ChangeAction::ChangeRows | ChangeAction::SetData);
|
}) << 6 << 2 << (ChangeAction::ChangeRows | ChangeAction::SetData);
|
||||||
|
|
||||||
// special case: tree
|
// special case: tree
|
||||||
QTest::addRow("value tree (ref)") << Factory([this]{
|
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>)
|
}) << int(std::size(*m_data->m_tree.get())) << int(std::tuple_size_v<tree_row>)
|
||||||
<< (ChangeAction::ChangeRows | ChangeAction::SetData);
|
<< (ChangeAction::ChangeRows | ChangeAction::SetData);
|
||||||
|
|
||||||
QTest::addRow("pointer tree") << Factory([this]{
|
QTest::addRow("pointer tree") << Factory([this]{
|
||||||
return std::unique_ptr<QAbstractItemModel>(
|
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>)
|
}) << int(std::size(*m_data->m_pointer_tree.get())) << int(std::tuple_size_v<tree_row>)
|
||||||
<< (ChangeAction::ChangeRows | ChangeAction::SetData);
|
<< (ChangeAction::ChangeRows | ChangeAction::SetData);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_QGenericItemModel::basics()
|
void tst_QRangeModel::basics()
|
||||||
{
|
{
|
||||||
#if QT_CONFIG(itemmodeltester)
|
#if QT_CONFIG(itemmodeltester)
|
||||||
QFETCH(Factory, factory);
|
QFETCH(Factory, factory);
|
||||||
@ -778,25 +778,25 @@ void tst_QGenericItemModel::basics()
|
|||||||
|
|
||||||
using ModelFromData = std::function<std::unique_ptr<QAbstractItemModel>(std::vector<int> &)>;
|
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<ModelFromData>("modelFromData");
|
||||||
QTest::addColumn<bool>("modifiesOriginal");
|
QTest::addColumn<bool>("modifiesOriginal");
|
||||||
|
|
||||||
QTest::newRow("copy") << ModelFromData([](std::vector<int> &numbers){
|
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;
|
}) << false;
|
||||||
|
|
||||||
QTest::newRow("reference_wrapper") << ModelFromData([](std::vector<int> &numbers){
|
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;
|
}) << true;
|
||||||
|
|
||||||
QTest::newRow("pointer") << ModelFromData([](std::vector<int> &numbers){
|
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;
|
}) << true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_QGenericItemModel::modifies()
|
void tst_QRangeModel::modifies()
|
||||||
{
|
{
|
||||||
QFETCH(ModelFromData, modelFromData);
|
QFETCH(ModelFromData, modelFromData);
|
||||||
QFETCH(bool, modifiesOriginal);
|
QFETCH(bool, modifiesOriginal);
|
||||||
@ -824,7 +824,7 @@ void tst_QGenericItemModel::modifies()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_QGenericItemModel::minimalIterator()
|
void tst_QRangeModel::minimalIterator()
|
||||||
{
|
{
|
||||||
struct Minimal
|
struct Minimal
|
||||||
{
|
{
|
||||||
@ -861,7 +861,7 @@ void tst_QGenericItemModel::minimalIterator()
|
|||||||
int m_size;
|
int m_size;
|
||||||
} minimal{100};
|
} minimal{100};
|
||||||
|
|
||||||
QGenericItemModel model(minimal);
|
QRangeModel model(minimal);
|
||||||
QCOMPARE(model.rowCount(), minimal.m_size);
|
QCOMPARE(model.rowCount(), minimal.m_size);
|
||||||
for (int row = model.rowCount() - 1; row >= 0; --row) {
|
for (int row = model.rowCount() - 1; row >= 0; --row) {
|
||||||
const QModelIndex index = model.index(row, 0);
|
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)
|
#if defined(__cpp_lib_ranges)
|
||||||
const int lowest = 1;
|
const int lowest = 1;
|
||||||
const int highest = 10;
|
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.rowCount(), highest - lowest);
|
||||||
QCOMPARE(model.columnCount(), 1);
|
QCOMPARE(model.columnCount(), 1);
|
||||||
#else
|
#else
|
||||||
@ -883,18 +883,18 @@ void tst_QGenericItemModel::ranges()
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_QGenericItemModel::json()
|
void tst_QRangeModel::json()
|
||||||
{
|
{
|
||||||
QJsonDocument json = QJsonDocument::fromJson(R"([ "one", "two" ])");
|
QJsonDocument json = QJsonDocument::fromJson(R"([ "one", "two" ])");
|
||||||
QVERIFY(json.isArray());
|
QVERIFY(json.isArray());
|
||||||
QGenericItemModel model(json.array());
|
QRangeModel model(json.array());
|
||||||
QCOMPARE(model.rowCount(), 2);
|
QCOMPARE(model.rowCount(), 2);
|
||||||
const QModelIndex index = model.index(1, 0);
|
const QModelIndex index = model.index(1, 0);
|
||||||
QVERIFY(index.isValid());
|
QVERIFY(index.isValid());
|
||||||
QCOMPARE(index.data().toString(), "two");
|
QCOMPARE(index.data().toString(), "two");
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_QGenericItemModel::ownership()
|
void tst_QRangeModel::ownership()
|
||||||
{
|
{
|
||||||
{ // a list of pointers to objects
|
{ // a list of pointers to objects
|
||||||
Object *object = new Object;
|
Object *object = new Object;
|
||||||
@ -903,22 +903,22 @@ void tst_QGenericItemModel::ownership()
|
|||||||
object
|
object
|
||||||
};
|
};
|
||||||
{ // model takes ownership of its own copy of the vector (!)
|
{ // model takes ownership of its own copy of the vector (!)
|
||||||
QGenericItemModel modelOnCopy(objects);
|
QRangeModel modelOnCopy(objects);
|
||||||
}
|
}
|
||||||
QVERIFY(!guard);
|
QVERIFY(!guard);
|
||||||
objects[0] = new Object;
|
objects[0] = new Object;
|
||||||
guard = objects[0];
|
guard = objects[0];
|
||||||
{ // model does not take ownership
|
{ // model does not take ownership
|
||||||
QGenericItemModel modelOnPointer(&objects);
|
QRangeModel modelOnPointer(&objects);
|
||||||
}
|
}
|
||||||
QVERIFY(guard);
|
QVERIFY(guard);
|
||||||
{ // model does not take ownership
|
{ // model does not take ownership
|
||||||
QGenericItemModel modelOnRef(std::ref(objects));
|
QRangeModel modelOnRef(std::ref(objects));
|
||||||
}
|
}
|
||||||
QVERIFY(guard);
|
QVERIFY(guard);
|
||||||
|
|
||||||
{ // model does take ownership
|
{ // model does take ownership
|
||||||
QGenericItemModel movedIntoModel(std::move(objects));
|
QRangeModel movedIntoModel(std::move(objects));
|
||||||
QCOMPARE(movedIntoModel.columnCount(), 2);
|
QCOMPARE(movedIntoModel.columnCount(), 2);
|
||||||
}
|
}
|
||||||
QVERIFY(!guard);
|
QVERIFY(!guard);
|
||||||
@ -932,25 +932,25 @@ void tst_QGenericItemModel::ownership()
|
|||||||
};
|
};
|
||||||
{ // model does not take ownership
|
{ // model does not take ownership
|
||||||
QCOMPARE(objects[0].use_count(), 1);
|
QCOMPARE(objects[0].use_count(), 1);
|
||||||
QGenericItemModel modelOnCopy(objects);
|
QRangeModel modelOnCopy(objects);
|
||||||
QCOMPARE(modelOnCopy.rowCount(), 1);
|
QCOMPARE(modelOnCopy.rowCount(), 1);
|
||||||
QCOMPARE(objects[0].use_count(), 2);
|
QCOMPARE(objects[0].use_count(), 2);
|
||||||
}
|
}
|
||||||
QCOMPARE(objects[0].use_count(), 1);
|
QCOMPARE(objects[0].use_count(), 1);
|
||||||
{ // model does not take ownership
|
{ // model does not take ownership
|
||||||
QGenericItemModel modelOnPointer(&objects);
|
QRangeModel modelOnPointer(&objects);
|
||||||
QCOMPARE(objects[0].use_count(), 1);
|
QCOMPARE(objects[0].use_count(), 1);
|
||||||
}
|
}
|
||||||
QCOMPARE(objects[0].use_count(), 1);
|
QCOMPARE(objects[0].use_count(), 1);
|
||||||
QVERIFY(guard);
|
QVERIFY(guard);
|
||||||
{ // model does not take ownership
|
{ // 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);
|
||||||
}
|
}
|
||||||
QCOMPARE(objects[0].use_count(), 1);
|
QCOMPARE(objects[0].use_count(), 1);
|
||||||
QVERIFY(guard);
|
QVERIFY(guard);
|
||||||
{ // model owns the last shared copy
|
{ // model owns the last shared copy
|
||||||
QGenericItemModel movedIntoModel(std::move(objects));
|
QRangeModel movedIntoModel(std::move(objects));
|
||||||
}
|
}
|
||||||
QVERIFY(!guard);
|
QVERIFY(!guard);
|
||||||
}
|
}
|
||||||
@ -962,19 +962,19 @@ void tst_QGenericItemModel::ownership()
|
|||||||
{object}
|
{object}
|
||||||
};
|
};
|
||||||
{ // model does not take ownership
|
{ // model does not take ownership
|
||||||
QGenericItemModel modelOnCopy(table);
|
QRangeModel modelOnCopy(table);
|
||||||
}
|
}
|
||||||
QVERIFY(guard);
|
QVERIFY(guard);
|
||||||
{ // model does not take ownership
|
{ // model does not take ownership
|
||||||
QGenericItemModel modelOnPointer(&table);
|
QRangeModel modelOnPointer(&table);
|
||||||
}
|
}
|
||||||
QVERIFY(guard);
|
QVERIFY(guard);
|
||||||
{ // model does not take ownership
|
{ // model does not take ownership
|
||||||
QGenericItemModel modelOnRef(std::ref(table));
|
QRangeModel modelOnRef(std::ref(table));
|
||||||
}
|
}
|
||||||
QVERIFY(guard);
|
QVERIFY(guard);
|
||||||
{ // model does take ownership of rows, but not of objects within each row
|
{ // 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);
|
QVERIFY(guard);
|
||||||
delete object;
|
delete object;
|
||||||
@ -984,7 +984,7 @@ void tst_QGenericItemModel::ownership()
|
|||||||
std::vector<std::shared_ptr<Object>> objects = { std::make_shared<Object>() };
|
std::vector<std::shared_ptr<Object>> objects = { std::make_shared<Object>() };
|
||||||
|
|
||||||
{
|
{
|
||||||
QGenericItemModel model(objects);
|
QRangeModel model(objects);
|
||||||
QCOMPARE(objects.front().use_count(), 2);
|
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().use_count(), 2);
|
||||||
QCOMPARE(table.front()->front().use_count(), 1);
|
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);
|
QFETCH(Factory, factory);
|
||||||
auto model = factory();
|
auto model = factory();
|
||||||
@ -1019,7 +1019,7 @@ void tst_QGenericItemModel::dimensions()
|
|||||||
QCOMPARE(model->columnCount(), expectedColumnCount);
|
QCOMPARE(model->columnCount(), expectedColumnCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_QGenericItemModel::sibling()
|
void tst_QRangeModel::sibling()
|
||||||
{
|
{
|
||||||
QFETCH(Factory, factory);
|
QFETCH(Factory, factory);
|
||||||
auto model = factory();
|
auto model = factory();
|
||||||
@ -1044,7 +1044,7 @@ void tst_QGenericItemModel::sibling()
|
|||||||
test(withChildren);
|
test(withChildren);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_QGenericItemModel::flags()
|
void tst_QRangeModel::flags()
|
||||||
{
|
{
|
||||||
QFETCH(Factory, factory);
|
QFETCH(Factory, factory);
|
||||||
auto model = factory();
|
auto model = factory();
|
||||||
@ -1061,7 +1061,7 @@ void tst_QGenericItemModel::flags()
|
|||||||
changeActions.testFlags(ChangeAction::SetData));
|
changeActions.testFlags(ChangeAction::SetData));
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_QGenericItemModel::data()
|
void tst_QRangeModel::data()
|
||||||
{
|
{
|
||||||
QFETCH(Factory, factory);
|
QFETCH(Factory, factory);
|
||||||
auto model = factory();
|
auto model = factory();
|
||||||
@ -1077,7 +1077,7 @@ void tst_QGenericItemModel::data()
|
|||||||
QVERIFY(last.data().isValid());
|
QVERIFY(last.data().isValid());
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_QGenericItemModel::setData()
|
void tst_QRangeModel::setData()
|
||||||
{
|
{
|
||||||
QFETCH(Factory, factory);
|
QFETCH(Factory, factory);
|
||||||
auto model = factory();
|
auto model = factory();
|
||||||
@ -1099,7 +1099,7 @@ void tst_QGenericItemModel::setData()
|
|||||||
QCOMPARE(first.data() == oldValue, !changeActions.testFlag(ChangeAction::SetData));
|
QCOMPARE(first.data() == oldValue, !changeActions.testFlag(ChangeAction::SetData));
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_QGenericItemModel::itemData()
|
void tst_QRangeModel::itemData()
|
||||||
{
|
{
|
||||||
QFETCH(Factory, factory);
|
QFETCH(Factory, factory);
|
||||||
auto model = factory();
|
auto model = factory();
|
||||||
@ -1115,7 +1115,7 @@ void tst_QGenericItemModel::itemData()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_QGenericItemModel::setItemData()
|
void tst_QRangeModel::setItemData()
|
||||||
{
|
{
|
||||||
QFETCH(Factory, factory);
|
QFETCH(Factory, factory);
|
||||||
auto model = factory();
|
auto model = factory();
|
||||||
@ -1171,7 +1171,7 @@ void tst_QGenericItemModel::setItemData()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_QGenericItemModel::clearItemData()
|
void tst_QRangeModel::clearItemData()
|
||||||
{
|
{
|
||||||
QFETCH(Factory, factory);
|
QFETCH(Factory, factory);
|
||||||
auto model = factory();
|
auto model = factory();
|
||||||
@ -1188,7 +1188,7 @@ void tst_QGenericItemModel::clearItemData()
|
|||||||
QCOMPARE(index1.data(), oldDataAt1);
|
QCOMPARE(index1.data(), oldDataAt1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_QGenericItemModel::insertRows()
|
void tst_QRangeModel::insertRows()
|
||||||
{
|
{
|
||||||
QFETCH(Factory, factory);
|
QFETCH(Factory, factory);
|
||||||
auto model = factory();
|
auto model = factory();
|
||||||
@ -1259,7 +1259,7 @@ void tst_QGenericItemModel::insertRows()
|
|||||||
verifyPmiList(pmiList);
|
verifyPmiList(pmiList);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_QGenericItemModel::removeRows()
|
void tst_QRangeModel::removeRows()
|
||||||
{
|
{
|
||||||
QFETCH(Factory, factory);
|
QFETCH(Factory, factory);
|
||||||
auto model = factory();
|
auto model = factory();
|
||||||
@ -1282,7 +1282,7 @@ void tst_QGenericItemModel::removeRows()
|
|||||||
QCOMPARE(couldRemove, model->rowCount() != newRowCount);
|
QCOMPARE(couldRemove, model->rowCount() != newRowCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_QGenericItemModel::moveRows()
|
void tst_QRangeModel::moveRows()
|
||||||
{
|
{
|
||||||
QFETCH(Factory, factory);
|
QFETCH(Factory, factory);
|
||||||
auto model = factory();
|
auto model = factory();
|
||||||
@ -1325,7 +1325,7 @@ void tst_QGenericItemModel::moveRows()
|
|||||||
QCOMPARE(model->index(expectedRowCount - 1, 0).data(), last);
|
QCOMPARE(model->index(expectedRowCount - 1, 0).data(), last);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_QGenericItemModel::insertColumns()
|
void tst_QRangeModel::insertColumns()
|
||||||
{
|
{
|
||||||
QFETCH(Factory, factory);
|
QFETCH(Factory, factory);
|
||||||
auto model = factory();
|
auto model = factory();
|
||||||
@ -1344,7 +1344,7 @@ void tst_QGenericItemModel::insertColumns()
|
|||||||
changeActions.testFlag(ChangeAction::InsertColumns));
|
changeActions.testFlag(ChangeAction::InsertColumns));
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_QGenericItemModel::removeColumns()
|
void tst_QRangeModel::removeColumns()
|
||||||
{
|
{
|
||||||
QFETCH(Factory, factory);
|
QFETCH(Factory, factory);
|
||||||
auto model = factory();
|
auto model = factory();
|
||||||
@ -1356,7 +1356,7 @@ void tst_QGenericItemModel::removeColumns()
|
|||||||
changeActions.testFlag(ChangeAction::RemoveColumns));
|
changeActions.testFlag(ChangeAction::RemoveColumns));
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_QGenericItemModel::moveColumns()
|
void tst_QRangeModel::moveColumns()
|
||||||
{
|
{
|
||||||
QFETCH(Factory, factory);
|
QFETCH(Factory, factory);
|
||||||
auto model = 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!");
|
"Column-range at row 1 is not large enough!");
|
||||||
|
|
||||||
std::vector<std::vector<int>> fuzzyTable = {
|
std::vector<std::vector<int>> fuzzyTable = {
|
||||||
@ -1411,7 +1411,7 @@ void tst_QGenericItemModel::inconsistentColumnCount()
|
|||||||
{},
|
{},
|
||||||
{2},
|
{2},
|
||||||
};
|
};
|
||||||
QGenericItemModel model(fuzzyTable);
|
QRangeModel model(fuzzyTable);
|
||||||
QCOMPARE(model.columnCount(), 1);
|
QCOMPARE(model.columnCount(), 1);
|
||||||
for (int row = 0; row < model.rowCount(); ++row) {
|
for (int row = 0; row < model.rowCount(); ++row) {
|
||||||
auto debug = qScopeGuard([&]{
|
auto debug = qScopeGuard([&]{
|
||||||
@ -1430,7 +1430,7 @@ void tst_QGenericItemModel::inconsistentColumnCount()
|
|||||||
|
|
||||||
enum class TreeProtocol { ValueImplicit, ValueReadOnly, PointerExplicit, PointerExplicitMoved };
|
enum class TreeProtocol { ValueImplicit, ValueReadOnly, PointerExplicit, PointerExplicitMoved };
|
||||||
|
|
||||||
void tst_QGenericItemModel::createTree()
|
void tst_QRangeModel::createTree()
|
||||||
{
|
{
|
||||||
tree_row root[] = {
|
tree_row root[] = {
|
||||||
{"1", "one"},
|
{"1", "one"},
|
||||||
@ -1469,7 +1469,7 @@ void tst_QGenericItemModel::createTree()
|
|||||||
m_data->m_pointer_tree->at(1)->addChildPointer("2.2", "two.two");
|
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);
|
m_data.reset(new Data);
|
||||||
createTree();
|
createTree();
|
||||||
@ -1502,7 +1502,7 @@ void tst_QGenericItemModel::tree_data()
|
|||||||
<< ChangeActions(ChangeAction::All);
|
<< ChangeActions(ChangeAction::All);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<QAbstractItemModel> tst_QGenericItemModel::makeTreeModel()
|
std::unique_ptr<QAbstractItemModel> tst_QRangeModel::makeTreeModel()
|
||||||
{
|
{
|
||||||
createTree();
|
createTree();
|
||||||
|
|
||||||
@ -1511,7 +1511,7 @@ std::unique_ptr<QAbstractItemModel> tst_QGenericItemModel::makeTreeModel()
|
|||||||
QFETCH(const TreeProtocol, protocol);
|
QFETCH(const TreeProtocol, protocol);
|
||||||
switch (protocol) {
|
switch (protocol) {
|
||||||
case TreeProtocol::ValueImplicit:
|
case TreeProtocol::ValueImplicit:
|
||||||
model.reset(new QGenericItemModel(m_data->m_tree.get()));
|
model.reset(new QRangeModel(m_data->m_tree.get()));
|
||||||
break;
|
break;
|
||||||
case TreeProtocol::ValueReadOnly: {
|
case TreeProtocol::ValueReadOnly: {
|
||||||
struct { // minimal (read-only) implementation of the tree traversal protocol
|
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
|
const std::optional<value_tree> &childRows(const tree_row &row) const
|
||||||
{ return row.childRows(); }
|
{ return row.childRows(); }
|
||||||
} readOnlyProtocol;
|
} readOnlyProtocol;
|
||||||
model.reset(new QGenericItemModel(m_data->m_tree.get(), readOnlyProtocol));
|
model.reset(new QRangeModel(m_data->m_tree.get(), readOnlyProtocol));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TreeProtocol::PointerExplicit:
|
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{}));
|
tree_row::ProtocolPointerImpl{}));
|
||||||
break;
|
break;
|
||||||
case TreeProtocol::PointerExplicitMoved: {
|
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.1", "two.one");
|
||||||
moved_tree.at(1)->addChildPointer("2.2", "two.two");
|
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{}));
|
tree_row::ProtocolPointerImpl{}));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1546,7 +1546,7 @@ std::unique_ptr<QAbstractItemModel> tst_QGenericItemModel::makeTreeModel()
|
|||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_QGenericItemModel::tree()
|
void tst_QRangeModel::tree()
|
||||||
{
|
{
|
||||||
auto model = makeTreeModel();
|
auto model = makeTreeModel();
|
||||||
QFETCH(const int, expectedRootRowCount);
|
QFETCH(const int, expectedRootRowCount);
|
||||||
@ -1579,7 +1579,7 @@ void tst_QGenericItemModel::tree()
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_QGenericItemModel::treeModifyBranch()
|
void tst_QRangeModel::treeModifyBranch()
|
||||||
{
|
{
|
||||||
auto model = makeTreeModel();
|
auto model = makeTreeModel();
|
||||||
QFETCH(QList<int>, rowsWithChildren);
|
QFETCH(QList<int>, rowsWithChildren);
|
||||||
@ -1641,7 +1641,7 @@ void tst_QGenericItemModel::treeModifyBranch()
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_QGenericItemModel::treeCreateBranch()
|
void tst_QRangeModel::treeCreateBranch()
|
||||||
{
|
{
|
||||||
auto model = makeTreeModel();
|
auto model = makeTreeModel();
|
||||||
QFETCH(QList<int>, rowsWithChildren);
|
QFETCH(QList<int>, rowsWithChildren);
|
||||||
@ -1674,7 +1674,7 @@ void tst_QGenericItemModel::treeCreateBranch()
|
|||||||
verifyPmiList(pmiList);
|
verifyPmiList(pmiList);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_QGenericItemModel::treeRemoveBranch()
|
void tst_QRangeModel::treeRemoveBranch()
|
||||||
{
|
{
|
||||||
auto model = makeTreeModel();
|
auto model = makeTreeModel();
|
||||||
QFETCH(QList<int>, rowsWithChildren);
|
QFETCH(QList<int>, rowsWithChildren);
|
||||||
@ -1701,7 +1701,7 @@ void tst_QGenericItemModel::treeRemoveBranch()
|
|||||||
QCOMPARE(model->rowCount(parent), 0);
|
QCOMPARE(model->rowCount(parent), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_QGenericItemModel::treeMoveRows()
|
void tst_QRangeModel::treeMoveRows()
|
||||||
{
|
{
|
||||||
auto model = makeTreeModel();
|
auto model = makeTreeModel();
|
||||||
QFETCH(const QList<int>, rowsWithChildren);
|
QFETCH(const QList<int>, rowsWithChildren);
|
||||||
@ -1726,7 +1726,7 @@ void tst_QGenericItemModel::treeMoveRows()
|
|||||||
verifyPmiList(pmiList);
|
verifyPmiList(pmiList);
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_QGenericItemModel::treeMoveRowBranches()
|
void tst_QRangeModel::treeMoveRowBranches()
|
||||||
{
|
{
|
||||||
auto model = makeTreeModel();
|
auto model = makeTreeModel();
|
||||||
QFETCH(const QList<int>, rowsWithChildren);
|
QFETCH(const QList<int>, rowsWithChildren);
|
||||||
@ -1797,5 +1797,5 @@ void tst_QGenericItemModel::treeMoveRowBranches()
|
|||||||
verifyPmiList(pmiList);
|
verifyPmiList(pmiList);
|
||||||
}
|
}
|
||||||
|
|
||||||
QTEST_MAIN(tst_QGenericItemModel)
|
QTEST_MAIN(tst_QRangeModel)
|
||||||
#include "tst_qgenericitemmodel.moc"
|
#include "tst_qrangemodel.moc"
|
Loading…
x
Reference in New Issue
Block a user