Source code
Revision control
Copy as Markdown
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
// Qt-Security score:significant reason:default
#include "qitemmodelsurfacedataproxy_p.h"
#include "surfaceitemmodelhandler_p.h"
#include "qgraphs3dlogging_p.h"
QT_BEGIN_NAMESPACE
/*!
* \class QItemModelSurfaceDataProxy
* \inmodule QtGraphs
* \ingroup graphs_3D
* \brief Proxy class for presenting data in item models with Q3DSurfaceWidgetItem.
*
* QItemModelSurfaceDataProxy allows you to use QAbstractItemModel derived
* models as a data source for Q3DSurfaceWidgetItem. It uses the defined mappings to map
* data from the model to rows, columns, and surface points of Q3DSurfaceWidgetItem graph.
*
* Data is resolved asynchronously whenever the mapping or the model changes.
* QSurfaceDataProxy::arrayReset() is emitted when the data has been resolved.
* However, when useModelCategories property is set to \c true, single item
* changes are resolved synchronously, unless the same frame also contains a
* change that causes the whole model to be resolved.
*
* Mappings can be used in the following ways:
*
* \list
* \li If useModelCategories property is set to \c true, this proxy will map rows and
* columns of QAbstractItemModel to rows and columns of Q3DSurfaceWidgetItem, and uses the value returned for
* Qt::DisplayRole as Y-position by default. Row and column headers are used for Z-position and
* X-position by default, if they can be converted to floats. Otherwise row and column indices
* are used.
* The Y-position role to be used can be redefined if Qt::DisplayRole is not suitable.
* The Z-position and X-position roles to be used can be redefined if the headers or indices
* are not suitable.
*
* \li For models that do not have data already neatly sorted into rows and columns, such as
* QAbstractListModel based models, you can define a role from the model to map for each of the
* row, column and Y-position.
*
* \li If you do not want to include all data contained in the model, or the autogenerated rows and
* columns are not ordered as you wish, you can specify which rows and columns should be included
* and in which order by defining an explicit list of categories for either or both of rows and
* columns.
* \endlist
*
* For example, assume that you have a custom QAbstractItemModel storing surface topography data.
* Each item in the model has the roles "longitude", "latitude", and "height".
* The item model already contains the data properly sorted so that longitudes and latitudes are
* first encountered in correct order, which enables us to utilize the row and column category
* autogeneration.
* You could do the following to display the data in a surface graph:
*
* \snippet doc_src_qtgraphs.cpp surfacemodelproxy
*
* If the fields of the model do not contain the data in the exact format you
* need, you can specify a search pattern regular expression and a replace rule
* for each role to get the value in a format you need. For more information on how
* the replacement using regular expressions works, see QString::replace(const
* QRegularExpression &rx, const QString &after) function documentation. Note
* that using regular expressions has an impact on the performance, so it's more
* efficient to utilize item models where doing search and replace is not
* necessary to get the desired values.
*
* For example about using the search patterns in conjunction with the roles,
* see ItemModelBarDataProxy usage in \l{Simple Bar Graph}.
*
* \sa {Qt Graphs Data Handling with 3D}
*/
/*!
* \qmltype ItemModelSurfaceDataProxy
* \inqmlmodule QtGraphs
* \ingroup graphs_qml_3D
* \nativetype QItemModelSurfaceDataProxy
* \inherits SurfaceDataProxy
* \brief Proxy class for presenting data in item models with Surface3D.
*
* This type allows you to use \c AbstractItemModel derived models as a data
* source for Surface3D.
*
* Data is resolved asynchronously whenever the mapping or the model changes.
*
* For ItemModelSurfaceDataProxy enums, see
* \l{QItemModelSurfaceDataProxy::MultiMatchBehavior}.
*
* For more details, see QItemModelSurfaceDataProxy documentation.
*
* Usage example:
*
* \snippet doc_src_qmlgraphs.cpp 9
*
* \sa SurfaceDataProxy, {Qt Graphs Data Handling with 3D}
*/
/*!
* \qmlproperty model ItemModelSurfaceDataProxy::itemModel
* The item model used as a data source for Surface3D.
*/
/*!
* \qmlproperty string ItemModelSurfaceDataProxy::rowRole
* The item model role to map to the row category.
* In addition to defining which row the data belongs to, the value indicated by
* the row role is also set as the Z-coordinate value of QSurfaceDataItem when the
* model data is resolved, unless a separate z position role is also defined.
*/
/*!
* \qmlproperty string ItemModelSurfaceDataProxy::columnRole
* The item model role to map to the column category.
* In addition to defining which column the data belongs to, the value indicated
* by the column role is also set as the X-coordinate value of QSurfaceDataItem
* when the model data is resolved, unless a separate x position role is also
* defined.
*/
/*!
* \qmlproperty string ItemModelSurfaceDataProxy::xPosRole
* The item model role to map to the X position. If this role is not defined,
* columnRole is used to determine the X-coordinate value of the resolved \c
* QSurfaceDataItem items.
*/
/*!
* \qmlproperty string ItemModelSurfaceDataProxy::yPosRole
* The item model role to map to the Y position.
*/
/*!
* \qmlproperty string ItemModelSurfaceDataProxy::zPosRole
* The item model role to map to the Z position. If this role is not defined,
* rowRole is used to determine the Z-coordinate value of the resolved
* \c QSurfaceDataItem items.
*/
/*!
* \qmlproperty list<String> ItemModelSurfaceDataProxy::rowCategories
* The row categories of the mapping. Only items with row roles that are found
* in this list are included when data is resolved. The rows are ordered in the
* same order as they are in this list.
*/
/*!
* \qmlproperty list<String> ItemModelSurfaceDataProxy::columnCategories
* The column categories of the mapping. Only items with column roles that are
* found in this list are included when data is resolved. The columns are
* ordered in the same order as they are in this list.
*/
/*!
* \qmlproperty bool ItemModelSurfaceDataProxy::useModelCategories
* When set to \c true, the mapping ignores row and column roles and categories,
* and uses the rows and columns from the model instead. Defaults to \c{false}.
*/
/*!
* \qmlproperty bool ItemModelSurfaceDataProxy::autoRowCategories
* When set to \c true, the mapping ignores any explicitly set row categories
* and overwrites them with automatically generated ones whenever the
* data from the model is resolved. Proxy minimum and maximum row values are
* also autogenerated from the data when this is set to \c true. Defaults to
* \c{true}.
*/
/*!
* \qmlproperty bool ItemModelSurfaceDataProxy::autoColumnCategories
* When set to \c true, the mapping ignores any explicitly set column categories
* and overwrites them with automatically generated ones whenever the
* data from the model is resolved. Proxy minimum and maximum column values are
* also autogenerated from the data when this is set to \c true. Defaults to
* \c{true}.
*/
/*!
* \qmlproperty regExp ItemModelSurfaceDataProxy::rowRolePattern
*
* When set, a search and replace is done on the value mapped by the row role
* before it is used as a row category. This property specifies the regular
* expression to find the portion of the mapped value to replace, and the
* rowRoleReplace property contains the replacement string.
*
* \sa rowRole, rowRoleReplace
*/
/*!
* \qmlproperty regExp ItemModelSurfaceDataProxy::columnRolePattern
*
* When set, a search and replace is done on the value mapped by the column role
* before it is used as a column category. This property specifies the regular
* expression to find the portion of the mapped value to replace, and the
* columnRoleReplace property contains the replacement string.
*
* \sa columnRole, columnRoleReplace
*/
/*!
* \qmlproperty regExp ItemModelSurfaceDataProxy::xPosRolePattern
*
* When set, a search and replace is done on the value mapped by the x-position
* role before it is used as an item position value. This property specifies
* the regular expression to find the portion of the mapped value to replace, and
* the xPosRoleReplace property contains the replacement string.
*
* \sa xPosRole, xPosRoleReplace
*/
/*!
* \qmlproperty regExp ItemModelSurfaceDataProxy::yPosRolePattern
*
* When set, a search and replace is done on the value mapped by the y-position
* role before it is used as an item position value. This property specifies
* the regular expression to find the portion of the mapped value to replace, and
* the yPosRoleReplace property contains the replacement string.
*
* \sa yPosRole, yPosRoleReplace
*/
/*!
* \qmlproperty regExp ItemModelSurfaceDataProxy::zPosRolePattern
*
* When set, a search and replace is done on the value mapped by the z-position
* role before it is used as an item position value. This property specifies
* the regular expression to find the portion of the mapped value to replace, and
* the zPosRoleReplace property contains the replacement string.
*
* \sa zPosRole, zPosRoleReplace
*/
/*!
* \qmlproperty string ItemModelSurfaceDataProxy::rowRoleReplace
*
* The replacement content to be used in conjunction with rowRolePattern.
* Defaults to an empty string. For more information on how the search and
* replace using regular expressions works, see the
* QString::replace(const QRegularExpression &rx, const QString &after)
* function documentation.
*
* \sa rowRole, rowRolePattern
*/
/*!
* \qmlproperty string ItemModelSurfaceDataProxy::columnRoleReplace
*
* The replacement content to be used in conjunction with columnRolePattern.
* Defaults to an empty string. For more information on how the search and
* replace using regular expressions works, see the
* QString::replace(const QRegularExpression &rx, const QString &after)
* function documentation.
*
* \sa columnRole, columnRolePattern
*/
/*!
* \qmlproperty string ItemModelSurfaceDataProxy::xPosRoleReplace
*
* The replacement content to be used in conjunction with xPosRolePattern.
* Defaults to an empty string. For more information on how the search and
* replace using regular expressions works, see the
* QString::replace(const QRegularExpression &rx, const QString &after)
* function documentation.
*
* \sa xPosRole, xPosRolePattern
*/
/*!
* \qmlproperty string ItemModelSurfaceDataProxy::yPosRoleReplace
*
* The replacement content to be used in conjunction with yPosRolePattern.
* Defaults to an empty string. For more information on how the search and
* replace using regular expressions works, see the
* QString::replace(const QRegularExpression &rx, const QString &after)
* function documentation.
*
* \sa yPosRole, yPosRolePattern
*/
/*!
* \qmlproperty string ItemModelSurfaceDataProxy::zPosRoleReplace
*
* The replacement content to be used in conjunction with zPosRolePattern.
* Defaults to an empty string. For more information on how the search and
* replace using regular expressions works, see the
* QString::replace(const QRegularExpression &rx, const QString &after)
* function documentation.
*
* \sa zPosRole, zPosRolePattern
*/
/*!
* \qmlproperty enumeration ItemModelSurfaceDataProxy::multiMatchBehavior
* Defines how multiple matches for each row/column combination are handled.
* Defaults to
* \l{QItemModelSurfaceDataProxy::MultiMatchBehavior::Last}
* {ItemModelSurfaceDataProxy.MultiMatchBehavior.Last}.
*
* For example, you might have an item model with timestamped data taken at
* irregular intervals and you want to visualize an average position of data
* items on each hour with a surface graph. This can be done by specifying row
* and column categories so that each surface point represents an hour, and
* setting multiMatchBehavior to
* \l{QItemModelSurfaceDataProxy::MultiMatchBehavior::Average}
* {ItemModelSurfaceDataProxy.MultiMatchBehavior.Average}.
*/
/*!
\qmlsignal ItemModelSurfaceDataProxy::itemModelChanged(model itemModel)
This signal is emitted when itemModel changes to \a itemModel.
*/
/*!
\qmlsignal ItemModelSurfaceDataProxy::rowRoleChanged(string role)
This signal is emitted when rowRole changes to \a role.
*/
/*!
\qmlsignal ItemModelSurfaceDataProxy::columnRoleChanged(string role)
This signal is emitted when columnRole changes to \a role.
*/
/*!
\qmlsignal ItemModelSurfaceDataProxy::xPosRoleChanged(string role)
This signal is emitted when xPosRole changes to \a role.
*/
/*!
\qmlsignal ItemModelSurfaceDataProxy::yPosRoleChanged(string role)
This signal is emitted when yPosRole changes to \a role.
*/
/*!
\qmlsignal ItemModelSurfaceDataProxy::zPosRoleChanged(string role)
This signal is emitted when zPosRole changes to \a role.
*/
/*!
\qmlsignal ItemModelSurfaceDataProxy::rowCategoriesChanged()
This signal is emitted when rowCategories changes.
*/
/*!
\qmlsignal ItemModelSurfaceDataProxy::columnCategoriesChanged()
This signal is emitted when columnCategories changes.
*/
/*!
\qmlsignal ItemModelSurfaceDataProxy::useModelCategoriesChanged(bool enable)
This signal is emitted when useModelCategories changes to \a enable.
*/
/*!
\qmlsignal ItemModelSurfaceDataProxy::autoRowCategoriesChanged(bool enable)
This signal is emitted when autoRowCategories changes to \a enable.
*/
/*!
\qmlsignal ItemModelSurfaceDataProxy::autoColumnCategoriesChanged(bool enable)
This signal is emitted when autoColumnCategories changes to \a enable.
*/
/*!
\qmlsignal ItemModelSurfaceDataProxy::rowRolePatternChanged(regExp pattern)
This signal is emitted when rowRolePattern changes to \a pattern.
*/
/*!
\qmlsignal ItemModelSurfaceDataProxy::columnRolePatternChanged(regExp pattern)
This signal is emitted when columnRolePattern changes to \a pattern.
*/
/*!
\qmlsignal ItemModelSurfaceDataProxy::xPosRolePatternChanged(regExp pattern)
This signal is emitted when xPosRolePattern changes to \a pattern.
*/
/*!
\qmlsignal ItemModelSurfaceDataProxy::yPosRolePatternChanged(regExp pattern)
This signal is emitted when yPosRolePattern changes to \a pattern.
*/
/*!
\qmlsignal ItemModelSurfaceDataProxy::zPosRolePatternChanged(regExp pattern)
This signal is emitted when zPosRolePattern changes to \a pattern.
*/
/*!
\qmlsignal ItemModelSurfaceDataProxy::rowRoleReplaceChanged(string replace)
This signal is emitted when rowRoleReplace changes to \a replace.
*/
/*!
\qmlsignal ItemModelSurfaceDataProxy::columnRoleReplaceChanged(string replace)
This signal is emitted when columnRoleReplace changes to \a replace.
*/
/*!
\qmlsignal ItemModelSurfaceDataProxy::xPosRoleReplaceChanged(string replace)
This signal is emitted when xPosRoleReplace changes to \a replace.
*/
/*!
\qmlsignal ItemModelSurfaceDataProxy::yPosRoleReplaceChanged(string replace)
This signal is emitted when yPosRoleReplace changes to \a replace.
*/
/*!
\qmlsignal ItemModelSurfaceDataProxy::zPosRoleReplaceChanged(string replace)
This signal is emitted when zPosRoleReplace changes to \a replace.
*/
/*!
\qmlsignal ItemModelSurfaceDataProxy::multiMatchBehaviorChanged(enumeration behavior)
This signal is emitted when multiMatchBehavior changes to \a behavior.
*/
/*!
* \enum QItemModelSurfaceDataProxy::MultiMatchBehavior
*
* Behavior types for QItemModelSurfaceDataProxy::multiMatchBehavior property.
*
* \value First
* The position values are taken from the first item in the item model that matches
* each row/column combination.
* \value Last
* The position values are taken from the last item in the item model that matches
* each row/column combination.
* \value Average
* The position values from all items matching each row/column combination are
* averaged together and the averages are used as the surface point position.
* \value CumulativeY
* For X and Z values this acts just like \c{Average}, but Y values are added together
* instead of averaged and the total is used as the surface point Y position.
*/
/*!
* Constructs QItemModelSurfaceDataProxy with an optional \a parent.
*/
QItemModelSurfaceDataProxy::QItemModelSurfaceDataProxy(QObject *parent)
: QSurfaceDataProxy(*(new QItemModelSurfaceDataProxyPrivate(this)), parent)
{
Q_D(QItemModelSurfaceDataProxy);
d->connectItemModelHandler();
}
/*!
* Constructs QItemModelSurfaceDataProxy with \a itemModel and an optional \a parent.
* The proxy doesn't take ownership of the \a itemModel, as typically item
* models are owned by other controls.
*/
QItemModelSurfaceDataProxy::QItemModelSurfaceDataProxy(QAbstractItemModel *itemModel,
QObject *parent)
: QSurfaceDataProxy(*(new QItemModelSurfaceDataProxyPrivate(this)), parent)
{
Q_D(QItemModelSurfaceDataProxy);
d->m_itemModelHandler->setItemModel(itemModel);
d->connectItemModelHandler();
}
/*!
* Constructs QItemModelSurfaceDataProxy with \a itemModel and an optional \a parent.
* The proxy doesn't take ownership of the \a itemModel, as typically item
* models are owned by other controls. The yPosRole role is set to \a yPosRole.
* This constructor is meant to be used with models that have data properly
* sorted in rows and columns already, so it also sets useModelCategories
* property to \c true.
*/
QItemModelSurfaceDataProxy::QItemModelSurfaceDataProxy(QAbstractItemModel *itemModel,
const QString &yPosRole,
QObject *parent)
: QSurfaceDataProxy(*(new QItemModelSurfaceDataProxyPrivate(this)), parent)
{
Q_D(QItemModelSurfaceDataProxy);
d->m_itemModelHandler->setItemModel(itemModel);
d->m_yPosRole = yPosRole;
d->m_useModelCategories = true;
d->connectItemModelHandler();
}
/*!
* Constructs QItemModelSurfaceDataProxy with \a itemModel and an optional \a parent.
* The proxy doesn't take ownership of the \a itemModel, as typically item
* models are owned by other controls. The role mappings are set with \a rowRole,
* \a columnRole, and \a yPosRole. The zPosRole and the xPosRole are
* set to \a rowRole and \a columnRole, respectively.
*/
QItemModelSurfaceDataProxy::QItemModelSurfaceDataProxy(QAbstractItemModel *itemModel,
const QString &rowRole,
const QString &columnRole,
const QString &yPosRole,
QObject *parent)
: QSurfaceDataProxy(*(new QItemModelSurfaceDataProxyPrivate(this)), parent)
{
Q_D(QItemModelSurfaceDataProxy);
d->m_itemModelHandler->setItemModel(itemModel);
d->m_rowRole = rowRole;
d->m_columnRole = columnRole;
d->m_xPosRole = columnRole;
d->m_yPosRole = yPosRole;
d->m_zPosRole = rowRole;
d->connectItemModelHandler();
}
/*!
* Constructs QItemModelSurfaceDataProxy with \a itemModel and an optional \a parent.
* The proxy doesn't take ownership of the \a itemModel, as typically item
* models are owned by other controls. The role mappings are set with \a rowRole,
* \a columnRole, \a xPosRole, \a yPosRole, and \a zPosRole.
*/
QItemModelSurfaceDataProxy::QItemModelSurfaceDataProxy(QAbstractItemModel *itemModel,
const QString &rowRole,
const QString &columnRole,
const QString &xPosRole,
const QString &yPosRole,
const QString &zPosRole,
QObject *parent)
: QSurfaceDataProxy(*(new QItemModelSurfaceDataProxyPrivate(this)), parent)
{
Q_D(QItemModelSurfaceDataProxy);
d->m_itemModelHandler->setItemModel(itemModel);
d->m_rowRole = rowRole;
d->m_columnRole = columnRole;
d->m_xPosRole = xPosRole;
d->m_yPosRole = yPosRole;
d->m_zPosRole = zPosRole;
d->connectItemModelHandler();
}
/*!
* Constructs QItemModelSurfaceDataProxy with \a itemModel and an optional \a parent.
* The proxy doesn't take ownership of the \a itemModel, as typically item
* models are owned by other controls. The role mappings are set with \a rowRole,
* \a columnRole, and \a yPosRole. The zPosRole and the xPosRole are
* set to \a rowRole and \a columnRole, respectively. Row and column categories
* are set with \a rowCategories and \a columnCategories. This constructor also
* sets autoRowCategories and autoColumnCategories to false.
*/
QItemModelSurfaceDataProxy::QItemModelSurfaceDataProxy(QAbstractItemModel *itemModel,
const QString &rowRole,
const QString &columnRole,
const QString &yPosRole,
const QStringList &rowCategories,
const QStringList &columnCategories,
QObject *parent)
: QSurfaceDataProxy(*(new QItemModelSurfaceDataProxyPrivate(this)), parent)
{
Q_D(QItemModelSurfaceDataProxy);
d->m_itemModelHandler->setItemModel(itemModel);
d->m_rowRole = rowRole;
d->m_columnRole = columnRole;
d->m_xPosRole = columnRole;
d->m_yPosRole = yPosRole;
d->m_zPosRole = rowRole;
d->m_rowCategories = rowCategories;
d->m_columnCategories = columnCategories;
d->m_autoRowCategories = false;
d->m_autoColumnCategories = false;
d->connectItemModelHandler();
}
/*!
* Constructs QItemModelSurfaceDataProxy with \a itemModel and an optional \a parent.
* The proxy doesn't take ownership of the \a itemModel, as typically item
* models are owned by other controls. The role mappings are set with \a rowRole,
* \a columnRole, \a xPosRole, \a yPosRole, and \a zPosRole. Row and
* column categories are set with \a rowCategories and \a columnCategories. This
* constructor also sets autoRowCategories and autoColumnCategories to false.
*/
QItemModelSurfaceDataProxy::QItemModelSurfaceDataProxy(QAbstractItemModel *itemModel,
const QString &rowRole,
const QString &columnRole,
const QString &xPosRole,
const QString &yPosRole,
const QString &zPosRole,
const QStringList &rowCategories,
const QStringList &columnCategories,
QObject *parent)
: QSurfaceDataProxy(*(new QItemModelSurfaceDataProxyPrivate(this)), parent)
{
Q_D(QItemModelSurfaceDataProxy);
d->m_itemModelHandler->setItemModel(itemModel);
d->m_rowRole = rowRole;
d->m_columnRole = columnRole;
d->m_xPosRole = xPosRole;
d->m_yPosRole = yPosRole;
d->m_zPosRole = zPosRole;
d->m_rowCategories = rowCategories;
d->m_columnCategories = columnCategories;
d->m_autoRowCategories = false;
d->m_autoColumnCategories = false;
d->connectItemModelHandler();
}
/*!
* Destroys QItemModelSurfaceDataProxy.
*/
QItemModelSurfaceDataProxy::~QItemModelSurfaceDataProxy() {}
/*!
* \property QItemModelSurfaceDataProxy::itemModel
*
* \brief The item model used as a data source for the 3D surface.
*/
/*!
* Sets the item model to \a itemModel. Does not take ownership of the model,
* but does connect to it to listen for changes.
*/
void QItemModelSurfaceDataProxy::setItemModel(QAbstractItemModel *itemModel)
{
Q_D(QItemModelSurfaceDataProxy);
d->m_itemModelHandler->setItemModel(itemModel);
}
QAbstractItemModel *QItemModelSurfaceDataProxy::itemModel() const
{
Q_D(const QItemModelSurfaceDataProxy);
return d->m_itemModelHandler->itemModel();
}
/*!
* \property QItemModelSurfaceDataProxy::rowRole
*
* \brief The item model role to map to the row category.
*
* In addition to defining which row the data belongs to, the value indicated by
* the row role is also set as the Z-coordinate value of QSurfaceDataItem when
* model data is resolved, unless a separate z-position role is also defined.
*/
void QItemModelSurfaceDataProxy::setRowRole(const QString &role)
{
Q_D(QItemModelSurfaceDataProxy);
if (d->m_rowRole == role) {
qCDebug(lcProperties3D, "%s value is already set to: %s",
qUtf8Printable(QLatin1String(__FUNCTION__)), qUtf8Printable(role));
return;
}
d->m_rowRole = role;
emit rowRoleChanged(role);
}
QString QItemModelSurfaceDataProxy::rowRole() const
{
Q_D(const QItemModelSurfaceDataProxy);
return d->m_rowRole;
}
/*!
* \property QItemModelSurfaceDataProxy::columnRole
*
* \brief The item model role to map to the column category.
*
* In addition to defining which column the data belongs to, the value indicated
* by the column role is also set as the X-coordinate value of QSurfaceDataItem
* when model data is resolved, unless a separate x-position role is also
* defined.
*/
void QItemModelSurfaceDataProxy::setColumnRole(const QString &role)
{
Q_D(QItemModelSurfaceDataProxy);
if (d->m_columnRole == role) {
qCDebug(lcProperties3D, "%s value is already set to: %s",
qUtf8Printable(QLatin1String(__FUNCTION__)), qUtf8Printable(role));
return;
}
d->m_columnRole = role;
emit columnRoleChanged(role);
}
QString QItemModelSurfaceDataProxy::columnRole() const
{
Q_D(const QItemModelSurfaceDataProxy);
return d->m_columnRole;
}
/*!
* \property QItemModelSurfaceDataProxy::xPosRole
*
* \brief The item model role to map to the X position.
*
* If this role is not defined, columnRole is used to determine the X-coordinate
* value of the resolved \l{QSurfaceDataItem} objects.
*/
void QItemModelSurfaceDataProxy::setXPosRole(const QString &role)
{
Q_D(QItemModelSurfaceDataProxy);
if (d->m_xPosRole == role) {
qCDebug(lcProperties3D, "%s value is already set to: %s",
qUtf8Printable(QLatin1String(__FUNCTION__)), qUtf8Printable(role));
return;
}
d->m_xPosRole = role;
emit xPosRoleChanged(role);
}
QString QItemModelSurfaceDataProxy::xPosRole() const
{
Q_D(const QItemModelSurfaceDataProxy);
return d->m_xPosRole;
}
/*!
* \property QItemModelSurfaceDataProxy::yPosRole
*
* \brief The item model role to map to the Y position.
*/
void QItemModelSurfaceDataProxy::setYPosRole(const QString &role)
{
Q_D(QItemModelSurfaceDataProxy);
if (d->m_yPosRole == role) {
qCDebug(lcProperties3D, "%s value is already set to: %s",
qUtf8Printable(QLatin1String(__FUNCTION__)), qUtf8Printable(role));
return;
}
d->m_yPosRole = role;
emit yPosRoleChanged(role);
}
QString QItemModelSurfaceDataProxy::yPosRole() const
{
Q_D(const QItemModelSurfaceDataProxy);
return d->m_yPosRole;
}
/*!
* \property QItemModelSurfaceDataProxy::zPosRole
*
* \brief The item model role to map to the Z position.
*
* If this role is not defined, rowRole is used to determine the Z-coordinate
* value of resolved \l{QSurfaceDataItem} objects.
*/
void QItemModelSurfaceDataProxy::setZPosRole(const QString &role)
{
Q_D(QItemModelSurfaceDataProxy);
if (d->m_zPosRole == role) {
qCDebug(lcProperties3D, "%s value is already set to: %s",
qUtf8Printable(QLatin1String(__FUNCTION__)), qUtf8Printable(role));
return;
}
d->m_zPosRole = role;
emit zPosRoleChanged(role);
}
QString QItemModelSurfaceDataProxy::zPosRole() const
{
Q_D(const QItemModelSurfaceDataProxy);
return d->m_zPosRole;
}
/*!
* \property QItemModelSurfaceDataProxy::rowCategories
*
* \brief The row categories for the mapping.
*/
void QItemModelSurfaceDataProxy::setRowCategories(const QStringList &categories)
{
Q_D(QItemModelSurfaceDataProxy);
if (d->m_rowCategories == categories) {
qCDebug(lcProperties3D) << __FUNCTION__
<< "value is already set to:" << categories;
return;
}
d->m_rowCategories = categories;
emit rowCategoriesChanged();
}
QStringList QItemModelSurfaceDataProxy::rowCategories() const
{
Q_D(const QItemModelSurfaceDataProxy);
return d->m_rowCategories;
}
/*!
* \property QItemModelSurfaceDataProxy::columnCategories
*
* \brief The column categories for the mapping.
*/
void QItemModelSurfaceDataProxy::setColumnCategories(const QStringList &categories)
{
Q_D(QItemModelSurfaceDataProxy);
if (d->m_columnCategories == categories) {
qCDebug(lcProperties3D) << __FUNCTION__
<< "value is already set to:" << categories;
return;
}
d->m_columnCategories = categories;
emit columnCategoriesChanged();
}
QStringList QItemModelSurfaceDataProxy::columnCategories() const
{
Q_D(const QItemModelSurfaceDataProxy);
return d->m_columnCategories;
}
/*!
* \property QItemModelSurfaceDataProxy::useModelCategories
*
* \brief Whether row and column roles and categories are used for mapping.
*
* When set to \c true, the mapping ignores row and column roles and categories,
* and uses the rows and columns from the model instead. Defaults to \c{false}.
*/
void QItemModelSurfaceDataProxy::setUseModelCategories(bool enable)
{
Q_D(QItemModelSurfaceDataProxy);
if (d->m_useModelCategories == enable) {
qCDebug(lcProperties3D) << __FUNCTION__
<< "value is already set to:" << enable;
return;
}
d->m_useModelCategories = enable;
emit useModelCategoriesChanged(enable);
}
bool QItemModelSurfaceDataProxy::useModelCategories() const
{
Q_D(const QItemModelSurfaceDataProxy);
return d->m_useModelCategories;
}
/*!
* \property QItemModelSurfaceDataProxy::autoRowCategories
*
* \brief Whether row categories are generated automatically.
*
* When set to \c true, the mapping ignores any explicitly set row categories
* and overwrites them with automatically generated ones whenever the
* data from the model is resolved. Defaults to \c{true}.
*/
void QItemModelSurfaceDataProxy::setAutoRowCategories(bool enable)
{
Q_D(QItemModelSurfaceDataProxy);
if (d->m_autoRowCategories == enable) {
qCDebug(lcProperties3D) << __FUNCTION__
<< "value is already set to:" << enable;
return;
}
d->m_autoRowCategories = enable;
emit autoRowCategoriesChanged(enable);
}
bool QItemModelSurfaceDataProxy::autoRowCategories() const
{
Q_D(const QItemModelSurfaceDataProxy);
return d->m_autoRowCategories;
}
/*!
* \property QItemModelSurfaceDataProxy::autoColumnCategories
*
* \brief Whether column categories are generated automatically.
*
* When set to \c true, the mapping ignores any explicitly set column categories
* and overwrites them with automatically generated ones whenever the
* data from the model is resolved. Defaults to \c{true}.
*/
void QItemModelSurfaceDataProxy::setAutoColumnCategories(bool enable)
{
Q_D(QItemModelSurfaceDataProxy);
if (d->m_autoColumnCategories == enable) {
qCDebug(lcProperties3D) << __FUNCTION__
<< "value is already set to:" << enable;
return;
}
d->m_autoColumnCategories = enable;
emit autoColumnCategoriesChanged(enable);
}
bool QItemModelSurfaceDataProxy::autoColumnCategories() const
{
Q_D(const QItemModelSurfaceDataProxy);
return d->m_autoColumnCategories;
}
/*!
* Changes \a rowRole, \a columnRole, \a xPosRole, \a yPosRole, \a zPosRole,
* \a rowCategories and \a columnCategories to the mapping.
*/
void QItemModelSurfaceDataProxy::remap(const QString &rowRole,
const QString &columnRole,
const QString &xPosRole,
const QString &yPosRole,
const QString &zPosRole,
const QStringList &rowCategories,
const QStringList &columnCategories)
{
setRowRole(rowRole);
setColumnRole(columnRole);
setXPosRole(xPosRole);
setYPosRole(yPosRole);
setZPosRole(zPosRole);
setRowCategories(rowCategories);
setColumnCategories(columnCategories);
}
/*!
* Returns the index of the specified \a category in the row categories list.
* If the row categories list is empty, -1 is returned.
* \note If the automatic row categories generation is in use, this method will
* not return a valid index before the data in the model is resolved for the
* first time.
*/
qsizetype QItemModelSurfaceDataProxy::rowCategoryIndex(const QString &category)
{
Q_D(QItemModelSurfaceDataProxy);
return d->m_rowCategories.indexOf(category);
}
/*!
* Returns the index of the specified \a category in the column categories list.
* If the category is not found, -1 is returned.
* \note If the automatic column categories generation is in use, this method
* will not return a valid index before the data in the model is resolved for
* the first time.
*/
qsizetype QItemModelSurfaceDataProxy::columnCategoryIndex(const QString &category)
{
Q_D(QItemModelSurfaceDataProxy);
return d->m_columnCategories.indexOf(category);
}
/*!
* \property QItemModelSurfaceDataProxy::rowRolePattern
*
* \brief Whether a search and replace is performed on the value mapped by the
* row role before it is used as a row category.
*
* This property specifies the regular expression to find the portion of the
* mapped value to replace and the rowRoleReplace property contains the
* replacement string.
*
* \sa rowRole, rowRoleReplace
*/
void QItemModelSurfaceDataProxy::setRowRolePattern(const QRegularExpression &pattern)
{
Q_D(QItemModelSurfaceDataProxy);
if (d->m_rowRolePattern == pattern) {
qCDebug(lcProperties3D) << __FUNCTION__
<< "value is already set to:" << pattern;
return;
}
d->m_rowRolePattern = pattern;
emit rowRolePatternChanged(pattern);
}
QRegularExpression QItemModelSurfaceDataProxy::rowRolePattern() const
{
Q_D(const QItemModelSurfaceDataProxy);
return d->m_rowRolePattern;
}
/*!
* \property QItemModelSurfaceDataProxy::columnRolePattern
*
* \brief Whether a search and replace is done on the value mapped by the column
* role before it is used as a column category.
*
* This property specifies the regular expression to find the portion of the
* mapped value to replace and the columnRoleReplace property contains the
* replacement string.
*
* \sa columnRole, columnRoleReplace
*/
void QItemModelSurfaceDataProxy::setColumnRolePattern(const QRegularExpression &pattern)
{
Q_D(QItemModelSurfaceDataProxy);
if (d->m_columnRolePattern == pattern) {
qCDebug(lcProperties3D) << __FUNCTION__
<< "value is already set to:" << pattern;
return;
}
d->m_columnRolePattern = pattern;
emit columnRolePatternChanged(pattern);
}
QRegularExpression QItemModelSurfaceDataProxy::columnRolePattern() const
{
Q_D(const QItemModelSurfaceDataProxy);
return d->m_columnRolePattern;
}
/*!
* \property QItemModelSurfaceDataProxy::xPosRolePattern
*
* \brief Whether a search and replace is done on the value mapped by the x
* position role before it is used as an item position value.
*
* This property specifies the regular expression to find the portion of the
* mapped value to replace and the xPosRoleReplace property contains the
* replacement string.
*
* \sa xPosRole, xPosRoleReplace
*/
void QItemModelSurfaceDataProxy::setXPosRolePattern(const QRegularExpression &pattern)
{
Q_D(QItemModelSurfaceDataProxy);
if (d->m_xPosRolePattern == pattern) {
qCDebug(lcProperties3D) << __FUNCTION__
<< "value is already set to:" << pattern;
return;
}
d->m_xPosRolePattern = pattern;
emit xPosRolePatternChanged(pattern);
}
QRegularExpression QItemModelSurfaceDataProxy::xPosRolePattern() const
{
Q_D(const QItemModelSurfaceDataProxy);
return d->m_xPosRolePattern;
}
/*!
* \property QItemModelSurfaceDataProxy::yPosRolePattern
*
* \brief Whether a search and replace is done on the value mapped by the y
* position role before it is used as an item position value.
*
* This property specifies the regular expression to find the portion of the
* mapped value to replace and the yPosRoleReplace property contains the
* replacement string.
*
* \sa yPosRole, yPosRoleReplace
*/
void QItemModelSurfaceDataProxy::setYPosRolePattern(const QRegularExpression &pattern)
{
Q_D(QItemModelSurfaceDataProxy);
if (d->m_yPosRolePattern == pattern) {
qCDebug(lcProperties3D) << __FUNCTION__
<< "value is already set to:" << pattern;
return;
}
d->m_yPosRolePattern = pattern;
emit yPosRolePatternChanged(pattern);
}
QRegularExpression QItemModelSurfaceDataProxy::yPosRolePattern() const
{
Q_D(const QItemModelSurfaceDataProxy);
return d->m_yPosRolePattern;
}
/*!
* \property QItemModelSurfaceDataProxy::zPosRolePattern
*
* \brief Whether a search and replace is done on the value mapped by the z
* position role before it is used as an item position value.
*
* This property specifies the regular expression to find the portion of the
* mapped value to replace and the zPosRoleReplace property contains the
* replacement string.
*
* \sa zPosRole, zPosRoleReplace
*/
void QItemModelSurfaceDataProxy::setZPosRolePattern(const QRegularExpression &pattern)
{
Q_D(QItemModelSurfaceDataProxy);
if (d->m_zPosRolePattern == pattern) {
qCDebug(lcProperties3D) << __FUNCTION__
<< "value is already set to:" << pattern;
return;
}
d->m_zPosRolePattern = pattern;
emit zPosRolePatternChanged(pattern);
}
QRegularExpression QItemModelSurfaceDataProxy::zPosRolePattern() const
{
Q_D(const QItemModelSurfaceDataProxy);
return d->m_zPosRolePattern;
}
/*!
* \property QItemModelSurfaceDataProxy::rowRoleReplace
*
* \brief The replacement content to be used in conjunction with the row role
* pattern.
*
* Defaults to an empty string. For more information on how the search and
* replace using regular expressions works, see QString::replace(const
* QRegularExpression &rx, const QString &after) function documentation.
*
* \sa rowRole, rowRolePattern
*/
void QItemModelSurfaceDataProxy::setRowRoleReplace(const QString &replace)
{
Q_D(QItemModelSurfaceDataProxy);
if (d->m_rowRoleReplace == replace) {
qCDebug(lcProperties3D, "%s value is already set to: %s",
qUtf8Printable(QLatin1String(__FUNCTION__)), qUtf8Printable(replace));
return;
}
d->m_rowRoleReplace = replace;
emit rowRoleReplaceChanged(replace);
}
QString QItemModelSurfaceDataProxy::rowRoleReplace() const
{
Q_D(const QItemModelSurfaceDataProxy);
return d->m_rowRoleReplace;
}
/*!
* \property QItemModelSurfaceDataProxy::columnRoleReplace
*
* \brief The replacement content to be used in conjunction with a column role
* pattern.
*
* Defaults to an empty string. For more information on how the search and
* replace using regular expressions works, see the
* QString::replace(const QRegularExpression &rx, const QString &after)
* function documentation.
*
* \sa columnRole, columnRolePattern
*/
void QItemModelSurfaceDataProxy::setColumnRoleReplace(const QString &replace)
{
Q_D(QItemModelSurfaceDataProxy);
if (d->m_columnRoleReplace == replace) {
qCDebug(lcProperties3D, "%s value is already set to: %s",
qUtf8Printable(QLatin1String(__FUNCTION__)), qUtf8Printable(replace));
return;
}
d->m_columnRoleReplace = replace;
emit columnRoleReplaceChanged(replace);
}
QString QItemModelSurfaceDataProxy::columnRoleReplace() const
{
Q_D(const QItemModelSurfaceDataProxy);
return d->m_columnRoleReplace;
}
/*!
* \property QItemModelSurfaceDataProxy::xPosRoleReplace
*
* \brief The replacement content to be used in conjunction with an x position role
* pattern.
*
* Defaults to an empty string. For more information on how the search and
* replace using regular expressions works, see the
* QString::replace(const QRegularExpression &rx, const QString &after)
* function documentation.
*
* \sa xPosRole, xPosRolePattern
*/
void QItemModelSurfaceDataProxy::setXPosRoleReplace(const QString &replace)
{
Q_D(QItemModelSurfaceDataProxy);
if (d->m_xPosRoleReplace == replace) {
qCDebug(lcProperties3D, "%s value is already set to: %s",
qUtf8Printable(QLatin1String(__FUNCTION__)), qUtf8Printable(replace));
return;
}
d->m_xPosRoleReplace = replace;
emit xPosRoleReplaceChanged(replace);
}
QString QItemModelSurfaceDataProxy::xPosRoleReplace() const
{
Q_D(const QItemModelSurfaceDataProxy);
return d->m_xPosRoleReplace;
}
/*!
* \property QItemModelSurfaceDataProxy::yPosRoleReplace
*
* \brief The replacement content to be used in conjunction with an y position role
* pattern.
*
* Defaults to an empty string. For more information on how the search and
* replace using regular expressions works, see the
* QString::replace(const QRegularExpression &rx, const QString &after)
* function documentation.
*
* \sa yPosRole, yPosRolePattern
*/
void QItemModelSurfaceDataProxy::setYPosRoleReplace(const QString &replace)
{
Q_D(QItemModelSurfaceDataProxy);
if (d->m_yPosRoleReplace == replace) {
qCDebug(lcProperties3D, "%s value is already set to: %s",
qUtf8Printable(QLatin1String(__FUNCTION__)), qUtf8Printable(replace));
return;
}
d->m_yPosRoleReplace = replace;
emit yPosRoleReplaceChanged(replace);
}
QString QItemModelSurfaceDataProxy::yPosRoleReplace() const
{
Q_D(const QItemModelSurfaceDataProxy);
return d->m_yPosRoleReplace;
}
/*!
* \property QItemModelSurfaceDataProxy::zPosRoleReplace
*
* \brief The replacement content to be used in conjunction with a z position role
* pattern.
*
* Defaults to an empty string. For more information on how the search and
* replace using regular expressions works, see the
* QString::replace(const QRegularExpression &rx, const QString &after)
* function documentation.
*
* \sa zPosRole, zPosRolePattern
*/
void QItemModelSurfaceDataProxy::setZPosRoleReplace(const QString &replace)
{
Q_D(QItemModelSurfaceDataProxy);
if (d->m_zPosRoleReplace == replace) {
qCDebug(lcProperties3D, "%s value is already set to: %s",
qUtf8Printable(QLatin1String(__FUNCTION__)), qUtf8Printable(replace));
return;
}
d->m_zPosRoleReplace = replace;
emit zPosRoleReplaceChanged(replace);
}
QString QItemModelSurfaceDataProxy::zPosRoleReplace() const
{
Q_D(const QItemModelSurfaceDataProxy);
return d->m_zPosRoleReplace;
}
/*!
* \property QItemModelSurfaceDataProxy::multiMatchBehavior
*
* \brief How multiple matches for each row/column combination are handled.
*
* Defaults to Last.
*
* For example, you might have an item model with timestamped data taken at
* irregular intervals and you want to visualize an average position of data
* items on each hour with a surface graph. This can be done by specifying row
* and column categories so that each surface point represents an hour, and
* setting this property to Average.
*/
void QItemModelSurfaceDataProxy::setMultiMatchBehavior(
QItemModelSurfaceDataProxy::MultiMatchBehavior behavior)
{
Q_D(QItemModelSurfaceDataProxy);
if (d->m_multiMatchBehavior == behavior) {
qCDebug(lcProperties3D) << __FUNCTION__
<< "value is already set to:" << behavior;
}
d->m_multiMatchBehavior = behavior;
emit multiMatchBehaviorChanged(behavior);
}
QItemModelSurfaceDataProxy::MultiMatchBehavior QItemModelSurfaceDataProxy::multiMatchBehavior() const
{
Q_D(const QItemModelSurfaceDataProxy);
return d->m_multiMatchBehavior;
}
// QItemModelSurfaceDataProxyPrivate
QItemModelSurfaceDataProxyPrivate::QItemModelSurfaceDataProxyPrivate(QItemModelSurfaceDataProxy *q)
: m_itemModelHandler(new SurfaceItemModelHandler(q))
, m_useModelCategories(false)
, m_autoRowCategories(true)
, m_autoColumnCategories(true)
, m_multiMatchBehavior(QItemModelSurfaceDataProxy::MultiMatchBehavior::Last)
{}
QItemModelSurfaceDataProxyPrivate::~QItemModelSurfaceDataProxyPrivate()
{
delete m_itemModelHandler;
}
void QItemModelSurfaceDataProxyPrivate::connectItemModelHandler()
{
Q_Q(QItemModelSurfaceDataProxy);
QObject::connect(m_itemModelHandler,
&SurfaceItemModelHandler::itemModelChanged,
q,
&QItemModelSurfaceDataProxy::itemModelChanged);
QObject::connect(q,
&QItemModelSurfaceDataProxy::rowRoleChanged,
m_itemModelHandler,
&AbstractItemModelHandler::handleMappingChanged);
QObject::connect(q,
&QItemModelSurfaceDataProxy::columnRoleChanged,
m_itemModelHandler,
&AbstractItemModelHandler::handleMappingChanged);
QObject::connect(q,
&QItemModelSurfaceDataProxy::xPosRoleChanged,
m_itemModelHandler,
&AbstractItemModelHandler::handleMappingChanged);
QObject::connect(q,
&QItemModelSurfaceDataProxy::yPosRoleChanged,
m_itemModelHandler,
&AbstractItemModelHandler::handleMappingChanged);
QObject::connect(q,
&QItemModelSurfaceDataProxy::zPosRoleChanged,
m_itemModelHandler,
&AbstractItemModelHandler::handleMappingChanged);
QObject::connect(q,
&QItemModelSurfaceDataProxy::rowCategoriesChanged,
m_itemModelHandler,
&AbstractItemModelHandler::handleMappingChanged);
QObject::connect(q,
&QItemModelSurfaceDataProxy::columnCategoriesChanged,
m_itemModelHandler,
&AbstractItemModelHandler::handleMappingChanged);
QObject::connect(q,
&QItemModelSurfaceDataProxy::useModelCategoriesChanged,
m_itemModelHandler,
&AbstractItemModelHandler::handleMappingChanged);
QObject::connect(q,
&QItemModelSurfaceDataProxy::autoRowCategoriesChanged,
m_itemModelHandler,
&AbstractItemModelHandler::handleMappingChanged);
QObject::connect(q,
&QItemModelSurfaceDataProxy::autoColumnCategoriesChanged,
m_itemModelHandler,
&AbstractItemModelHandler::handleMappingChanged);
QObject::connect(q,
&QItemModelSurfaceDataProxy::rowRolePatternChanged,
m_itemModelHandler,
&AbstractItemModelHandler::handleMappingChanged);
QObject::connect(q,
&QItemModelSurfaceDataProxy::columnRolePatternChanged,
m_itemModelHandler,
&AbstractItemModelHandler::handleMappingChanged);
QObject::connect(q,
&QItemModelSurfaceDataProxy::xPosRolePatternChanged,
m_itemModelHandler,
&AbstractItemModelHandler::handleMappingChanged);
QObject::connect(q,
&QItemModelSurfaceDataProxy::yPosRolePatternChanged,
m_itemModelHandler,
&AbstractItemModelHandler::handleMappingChanged);
QObject::connect(q,
&QItemModelSurfaceDataProxy::zPosRolePatternChanged,
m_itemModelHandler,
&AbstractItemModelHandler::handleMappingChanged);
QObject::connect(q,
&QItemModelSurfaceDataProxy::rowRoleReplaceChanged,
m_itemModelHandler,
&AbstractItemModelHandler::handleMappingChanged);
QObject::connect(q,
&QItemModelSurfaceDataProxy::columnRoleReplaceChanged,
m_itemModelHandler,
&AbstractItemModelHandler::handleMappingChanged);
QObject::connect(q,
&QItemModelSurfaceDataProxy::xPosRoleReplaceChanged,
m_itemModelHandler,
&AbstractItemModelHandler::handleMappingChanged);
QObject::connect(q,
&QItemModelSurfaceDataProxy::yPosRoleReplaceChanged,
m_itemModelHandler,
&AbstractItemModelHandler::handleMappingChanged);
QObject::connect(q,
&QItemModelSurfaceDataProxy::zPosRoleReplaceChanged,
m_itemModelHandler,
&AbstractItemModelHandler::handleMappingChanged);
QObject::connect(q,
&QItemModelSurfaceDataProxy::multiMatchBehaviorChanged,
m_itemModelHandler,
&AbstractItemModelHandler::handleMappingChanged);
}
QT_END_NAMESPACE
#include "moc_qitemmodelsurfacedataproxy.cpp"