1 /****************************************************************************
2 **
3 ** Copyright (C) 2017 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the Qt Data Visualization module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:GPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU
19 ** General Public License version 3 or (at your option) any later version
20 ** approved by the KDE Free Qt Foundation. The licenses are as published by
21 ** the Free Software Foundation and appearing in the file LICENSE.GPL3
22 ** included in the packaging of this file. Please review the following
23 ** information to ensure the GNU General Public License requirements will
24 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
25 **
26 ** $QT_END_LICENSE$
27 **
28 ****************************************************************************/
29 
30 #include "qitemmodelsurfacedataproxy_p.h"
31 #include "surfaceitemmodelhandler_p.h"
32 
33 QT_BEGIN_NAMESPACE_DATAVISUALIZATION
34 
35 /*!
36  * \class QItemModelSurfaceDataProxy
37  * \inmodule QtDataVisualization
38  * \brief Proxy class for presenting data in item models with Q3DSurface.
39  * \since QtDataVisualization 1.0
40  *
41  * QItemModelSurfaceDataProxy allows you to use QAbstractItemModel derived models as a data source
42  * for Q3DSurface. It uses the defined mappings to map data from the model to rows, columns, and
43  * surface points of Q3DSurface graph.
44  *
45  * Data is resolved asynchronously whenever the mapping or the model changes.
46  * QSurfaceDataProxy::arrayReset() is emitted when the data has been resolved.
47  * However, when useModelCategories property is set to \c true, single item changes are resolved
48  * synchronously, unless the same frame also contains a change that causes the whole model to be
49  * resolved.
50  *
51  * Mappings can be used in the following ways:
52  *
53  * \list
54  * \li If useModelCategories property is set to \c true, this proxy will map rows and
55  *    columns of QAbstractItemModel to rows and columns of Q3DSurface, and uses the value returned for
56  *    Qt::DisplayRole as Y-position by default. Row and column headers are used for Z-position and
57  *    X-position by default, if they can be converted to floats. Otherwise row and column indices
58  *    are used.
59  *    The Y-position role to be used can be redefined if Qt::DisplayRole is not suitable.
60  *    The Z-position and X-position roles to be used can be redefined if the headers or indices
61  *    are not suitable.
62  *
63  * \li For models that do not have data already neatly sorted into rows and columns, such as
64  *    QAbstractListModel based models, you can define a role from the model to map for each of row,
65  *    column and Y-position.
66  *
67  * \li If you do not want to include all data contained in the model, or the autogenerated rows and
68  *    columns are not ordered as you wish, you can specify which rows and columns should be included
69  *    and in which order by defining an explicit list of categories for either or both of rows and
70  *    columns.
71  * \endlist
72  *
73  * For example, assume that you have a custom QAbstractItemModel storing surface topography data.
74  * Each item in the model has the roles "longitude", "latitude", and "height".
75  * The item model already contains the data properly sorted so that longitudes and latitudes are
76  * first encountered in correct order, which enables us to utilize the row and column category
77  * autogeneration.
78  * You could do the following to display the data in a surface graph:
79  *
80  * \snippet doc_src_qtdatavisualization.cpp 5
81  *
82  * If the fields of the model do not contain the data in the exact format you need, you can specify
83  * a search pattern regular expression and a replace rule for each role to get the value in a
84  * format you need. For more information how the replace using regular expressions works, see
85  * QString::replace(const QRegExp &rx, const QString &after) function documentation. Note that
86  * using regular expressions has an impact on the performance, so it's more efficient to utilize
87  * item models where doing search and replace is not necessary to get the desired values.
88  *
89  * For example about using the search patterns in conjunction with the roles, see
90  * ItemModelBarDataProxy usage in \l{Qt Quick 2 Bars Example}.
91  *
92  * \sa {Qt Data Visualization Data Handling}
93  */
94 
95 /*!
96  * \qmltype ItemModelSurfaceDataProxy
97  * \inqmlmodule QtDataVisualization
98  * \since QtDataVisualization 1.0
99  * \ingroup datavisualization_qml
100  * \instantiates QItemModelSurfaceDataProxy
101  * \inherits SurfaceDataProxy
102  * \brief Proxy class for presenting data in item models with Surface3D.
103  *
104  * This type allows you to use \c AbstractItemModel derived models as a data
105  * source for Surface3D.
106  *
107  * Data is resolved asynchronously whenever the mapping or the model changes.
108  *
109  * For ItemModelSurfaceDataProxy enums, see \l{QItemModelSurfaceDataProxy::MultiMatchBehavior}.
110  *
111  * For more details, see QItemModelSurfaceDataProxy documentation.
112  *
113  * Usage example:
114  *
115  * \snippet doc_src_qmldatavisualization.cpp 9
116  *
117  * \sa SurfaceDataProxy, {Qt Data Visualization Data Handling}
118  */
119 
120 /*!
121  * \qmlproperty model ItemModelSurfaceDataProxy::itemModel
122  * The item model used as a data source for Surface3D.
123  */
124 
125 /*!
126  * \qmlproperty string ItemModelSurfaceDataProxy::rowRole
127  * The item model role to map to the row category.
128  * In addition to defining which row the data belongs to, the value indicated by the row role
129  * is also set as the Z-coordinate value of QSurfaceDataItem when model data is resolved,
130  * unless a separate z position role is also defined.
131  */
132 
133 /*!
134  * \qmlproperty string ItemModelSurfaceDataProxy::columnRole
135  * The item model role to map to the column category.
136  * In addition to defining which column the data belongs to, the value indicated by the column role
137  * is also set as the X-coordinate value of QSurfaceDataItem when model data is resolved,
138  * unless a separate x position role is also defined.
139  */
140 
141 /*!
142  * \qmlproperty string ItemModelSurfaceDataProxy::xPosRole
143  * The item model role to map to the X position. If this role is not defined, columnRole is
144  * used to determine the X-coordinate value of the resolved \c QSurfaceDataItem
145  * items.
146  */
147 
148 /*!
149  * \qmlproperty string ItemModelSurfaceDataProxy::yPosRole
150  * The item model role to map to the Y position.
151  */
152 
153 /*!
154  * \qmlproperty string ItemModelSurfaceDataProxy::zPosRole
155  * The item model role to map to the Z position. If this role is not defined, rowRole is
156  * used to determine the Z-coordinate value of the resolved \c QSurfaceDataItem
157  * items.
158  */
159 
160 /*!
161  * \qmlproperty list<String> ItemModelSurfaceDataProxy::rowCategories
162  * The row categories of the mapping. Only items with row roles that are found in this list are
163  * included when data is resolved. The rows are ordered in the same order as they are in this list.
164  */
165 
166 /*!
167  * \qmlproperty list<String> ItemModelSurfaceDataProxy::columnCategories
168  * The column categories of the mapping. Only items with column roles that are found in this
169  * list are included when data is resolved. The columns are ordered in the same order as they are
170  * in this list.
171  */
172 
173 /*!
174  * \qmlproperty bool ItemModelSurfaceDataProxy::useModelCategories
175  * When set to \c true, the mapping ignores row and column roles and categories, and uses
176  * the rows and columns from the model instead. Defaults to \c{false}.
177  */
178 
179 /*!
180  * \qmlproperty bool ItemModelSurfaceDataProxy::autoRowCategories
181  * When set to \c true, the mapping ignores any explicitly set row categories
182  * and overwrites them with automatically generated ones whenever the
183  * data from the model is resolved. Proxy minimum and maximum row values are also
184  * autogenerated from the data when this is set to \c true. Defaults to \c{true}.
185  */
186 
187 /*!
188  * \qmlproperty bool ItemModelSurfaceDataProxy::autoColumnCategories
189  * When set to \c true, the mapping ignores any explicitly set column categories
190  * and overwrites them with automatically generated ones whenever the
191  * data from the model is resolved. Proxy minimum and maximum column values are also
192  * autogenerated from the data when this is set to \c true. Defaults to \c{true}.
193  */
194 
195 /*!
196  * \qmlproperty regExp ItemModelSurfaceDataProxy::rowRolePattern
197  *
198  * When set, a search and replace is done on the value mapped by the row role before it is used as
199  * a row category. This property specifies the regular expression to find the portion of the
200  * mapped value to replace and the rowRoleReplace property contains the replacement string.
201  *
202  * \sa rowRole, rowRoleReplace
203  */
204 
205 /*!
206  * \qmlproperty regExp ItemModelSurfaceDataProxy::columnRolePattern
207  *
208  * When set, a search and replace is done on the value mapped by the column role before it is used
209  * as a column category. This property specifies the regular expression to find the portion of the
210  * mapped value to replace and the columnRoleReplace property contains the replacement string.
211  *
212  * \sa columnRole, columnRoleReplace
213  */
214 
215 /*!
216  * \qmlproperty regExp ItemModelSurfaceDataProxy::xPosRolePattern
217  *
218  * When set, a search and replace is done on the value mapped by the x position
219  * role before it is used as an item position value. This property specifies
220  * the regular expression to find the portion of the mapped value to replace and
221  * the xPosRoleReplace property contains the replacement string.
222  *
223  * \sa xPosRole, xPosRoleReplace
224  */
225 
226 /*!
227  * \qmlproperty regExp ItemModelSurfaceDataProxy::yPosRolePattern
228  *
229  * When set, a search and replace is done on the value mapped by the y position
230  * role before it is used as an item position value. This property specifies
231  * the regular expression to find the portion of the mapped value to replace and
232  * the yPosRoleReplace property contains the replacement string.
233  *
234  * \sa yPosRole, yPosRoleReplace
235  */
236 
237 /*!
238  * \qmlproperty regExp ItemModelSurfaceDataProxy::zPosRolePattern
239  *
240  * When set, a search and replace is done on the value mapped by the z position
241  * role before it is used as an item position value. This property specifies
242  * the regular expression to find the portion of the mapped value to replace and
243  * the zPosRoleReplace property contains the replacement string.
244  *
245  * \sa zPosRole, zPosRoleReplace
246  */
247 
248 /*!
249  * \qmlproperty string ItemModelSurfaceDataProxy::rowRoleReplace
250  *
251  * The replace content to be used in conjunction with rowRolePattern.
252  * Defaults to an empty string. For more information on how the search and
253  * replace using regular expressions works, see the
254  * QString::replace(const QRegExp &rx, const QString &after)
255  * function documentation.
256  *
257  * \sa rowRole, rowRolePattern
258  */
259 
260 /*!
261  * \qmlproperty string ItemModelSurfaceDataProxy::columnRoleReplace
262  *
263  * The replace content to be used in conjunction with columnRolePattern.
264  * Defaults to an empty string. For more information on how the search and
265  * replace using regular expressions works, see the
266  * QString::replace(const QRegExp &rx, const QString &after)
267  * function documentation.
268  *
269  * \sa columnRole, columnRolePattern
270  */
271 
272 /*!
273  * \qmlproperty string ItemModelSurfaceDataProxy::xPosRoleReplace
274  *
275  * The replace content to be used in conjunction with xPosRolePattern.
276  * Defaults to an empty string. For more information on how the search and
277  * replace using regular expressions works, see the
278  * QString::replace(const QRegExp &rx, const QString &after)
279  * function documentation.
280  *
281  * \sa xPosRole, xPosRolePattern
282  */
283 
284 /*!
285  * \qmlproperty string ItemModelSurfaceDataProxy::yPosRoleReplace
286  *
287  * The replace content to be used in conjunction with yPosRolePattern.
288  * Defaults to an empty string. For more information on how the search and
289  * replace using regular expressions works, see the
290  * QString::replace(const QRegExp &rx, const QString &after)
291  * function documentation.
292  *
293  * \sa yPosRole, yPosRolePattern
294  */
295 
296 /*!
297  * \qmlproperty string ItemModelSurfaceDataProxy::zPosRoleReplace
298  *
299  * The replace content to be used in conjunction with zPosRolePattern.
300  * Defaults to an empty string. For more information on how the search and
301  * replace using regular expressions works, see the
302  * QString::replace(const QRegExp &rx, const QString &after)
303  * function documentation.
304  *
305  * \sa zPosRole, zPosRolePattern
306  */
307 
308 /*!
309  * \qmlproperty ItemModelSurfaceDataProxy.MultiMatchBehavior ItemModelSurfaceDataProxy::multiMatchBehavior
310  * Defines how multiple matches for each row/column combination are handled.
311  * Defaults to \l{QItemModelSurfaceDataProxy::MMBLast}{ItemModelSurfaceDataProxy.MMBLast}.
312  *
313  * For example, you might have an item model with timestamped data taken at irregular intervals
314  * and you want to visualize an average position of data items on each hour with a surface graph.
315  * This can be done by specifying row and column categories so that each surface point represents
316  * an hour, and setting multiMatchBehavior to
317  * \l{QItemModelSurfaceDataProxy::MMBAverage}{ItemModelSurfaceDataProxy.MMBAverage}.
318  */
319 
320 /*!
321  *  \enum QItemModelSurfaceDataProxy::MultiMatchBehavior
322  *
323  *  Behavior types for QItemModelSurfaceDataProxy::multiMatchBehavior property.
324  *
325  *  \value MMBFirst
326  *         The position values are taken from the first item in the item model that matches
327  *         each row/column combination.
328  *  \value MMBLast
329  *         The position values are taken from the last item in the item model that matches
330  *         each row/column combination.
331  *  \value MMBAverage
332  *         The position values from all items matching each row/column combination are
333  *         averaged together and the averages are used as the surface point position.
334  *  \value MMBCumulativeY
335  *         For X and Z values this acts just like \c{MMBAverage}, but Y values are added together
336  *         instead of averaged and the total is used as the surface point Y position.
337  */
338 
339 /*!
340  * Constructs QItemModelSurfaceDataProxy with optional \a parent.
341  */
QItemModelSurfaceDataProxy(QObject * parent)342 QItemModelSurfaceDataProxy::QItemModelSurfaceDataProxy(QObject *parent)
343     : QSurfaceDataProxy(new QItemModelSurfaceDataProxyPrivate(this), parent)
344 {
345     dptr()->connectItemModelHandler();
346 }
347 
348 /*!
349  * Constructs QItemModelSurfaceDataProxy with \a itemModel and optional \a parent. Proxy doesn't take
350  * ownership of the \a itemModel, as typically item models are owned by other controls.
351  */
QItemModelSurfaceDataProxy(QAbstractItemModel * itemModel,QObject * parent)352 QItemModelSurfaceDataProxy::QItemModelSurfaceDataProxy(QAbstractItemModel *itemModel,
353                                                        QObject *parent)
354     : QSurfaceDataProxy(new QItemModelSurfaceDataProxyPrivate(this), parent)
355 {
356     dptr()->m_itemModelHandler->setItemModel(itemModel);
357     dptr()->connectItemModelHandler();
358 }
359 
360 /*!
361  * Constructs QItemModelSurfaceDataProxy with \a itemModel and optional \a parent. Proxy doesn't take
362  * ownership of the \a itemModel, as typically item models are owned by other controls.
363  * The yPosRole role is set to \a yPosRole.
364  * This constructor is meant to be used with models that have data properly sorted
365  * in rows and columns already, so it also sets useModelCategories property to \c true.
366  */
QItemModelSurfaceDataProxy(QAbstractItemModel * itemModel,const QString & yPosRole,QObject * parent)367 QItemModelSurfaceDataProxy::QItemModelSurfaceDataProxy(QAbstractItemModel *itemModel,
368                                                        const QString &yPosRole,
369                                                        QObject *parent)
370     : QSurfaceDataProxy(new QItemModelSurfaceDataProxyPrivate(this), parent)
371 {
372     dptr()->m_itemModelHandler->setItemModel(itemModel);
373     dptr()->m_yPosRole = yPosRole;
374     dptr()->m_useModelCategories = true;
375     dptr()->connectItemModelHandler();
376 }
377 
378 /*!
379  * Constructs QItemModelSurfaceDataProxy with \a itemModel and optional \a parent. Proxy doesn't take
380  * ownership of the \a itemModel, as typically item models are owned by other controls.
381  * The role mappings are set with \a rowRole, \a columnRole, and \a yPosRole.
382  * The zPosRole and the xPosRole are set to \a rowRole and \a columnRole, respectively.
383  */
QItemModelSurfaceDataProxy(QAbstractItemModel * itemModel,const QString & rowRole,const QString & columnRole,const QString & yPosRole,QObject * parent)384 QItemModelSurfaceDataProxy::QItemModelSurfaceDataProxy(QAbstractItemModel *itemModel,
385                                                        const QString &rowRole,
386                                                        const QString &columnRole,
387                                                        const QString &yPosRole,
388                                                        QObject *parent)
389     : QSurfaceDataProxy(new QItemModelSurfaceDataProxyPrivate(this), parent)
390 {
391     dptr()->m_itemModelHandler->setItemModel(itemModel);
392     dptr()->m_rowRole = rowRole;
393     dptr()->m_columnRole = columnRole;
394     dptr()->m_xPosRole = columnRole;
395     dptr()->m_yPosRole = yPosRole;
396     dptr()->m_zPosRole = rowRole;
397     dptr()->connectItemModelHandler();
398 }
399 
400 /*!
401  * Constructs QItemModelSurfaceDataProxy with \a itemModel and optional \a parent. Proxy doesn't take
402  * ownership of the \a itemModel, as typically item models are owned by other controls.
403  * The role mappings are set with \a rowRole, \a columnRole, \a xPosRole, \a yPosRole, and
404  * \a zPosRole.
405  */
QItemModelSurfaceDataProxy(QAbstractItemModel * itemModel,const QString & rowRole,const QString & columnRole,const QString & xPosRole,const QString & yPosRole,const QString & zPosRole,QObject * parent)406 QItemModelSurfaceDataProxy::QItemModelSurfaceDataProxy(QAbstractItemModel *itemModel,
407                                                        const QString &rowRole,
408                                                        const QString &columnRole,
409                                                        const QString &xPosRole,
410                                                        const QString &yPosRole,
411                                                        const QString &zPosRole,
412                                                        QObject *parent)
413     : QSurfaceDataProxy(new QItemModelSurfaceDataProxyPrivate(this), parent)
414 {
415     dptr()->m_itemModelHandler->setItemModel(itemModel);
416     dptr()->m_rowRole = rowRole;
417     dptr()->m_columnRole = columnRole;
418     dptr()->m_xPosRole = xPosRole;
419     dptr()->m_yPosRole = yPosRole;
420     dptr()->m_zPosRole = zPosRole;
421     dptr()->connectItemModelHandler();
422 }
423 
424 /*!
425  * Constructs QItemModelSurfaceDataProxy with \a itemModel and optional \a parent. Proxy doesn't take
426  * ownership of the \a itemModel, as typically item models are owned by other controls.
427  * The role mappings are set with \a rowRole, \a columnRole, and \a yPosRole.
428  * The zPosRole and the xPosRole are set to \a rowRole and \a columnRole, respectively.
429  * Row and column categories are set with \a rowCategories and \a columnCategories.
430  * This constructor also sets autoRowCategories and autoColumnCategories to false.
431  */
QItemModelSurfaceDataProxy(QAbstractItemModel * itemModel,const QString & rowRole,const QString & columnRole,const QString & yPosRole,const QStringList & rowCategories,const QStringList & columnCategories,QObject * parent)432 QItemModelSurfaceDataProxy::QItemModelSurfaceDataProxy(QAbstractItemModel *itemModel,
433                                                        const QString &rowRole,
434                                                        const QString &columnRole,
435                                                        const QString &yPosRole,
436                                                        const QStringList &rowCategories,
437                                                        const QStringList &columnCategories,
438                                                        QObject *parent)
439     : QSurfaceDataProxy(new QItemModelSurfaceDataProxyPrivate(this), parent)
440 {
441     dptr()->m_itemModelHandler->setItemModel(itemModel);
442     dptr()->m_rowRole = rowRole;
443     dptr()->m_columnRole = columnRole;
444     dptr()->m_xPosRole = columnRole;
445     dptr()->m_yPosRole = yPosRole;
446     dptr()->m_zPosRole = rowRole;
447     dptr()->m_rowCategories = rowCategories;
448     dptr()->m_columnCategories = columnCategories;
449     dptr()->m_autoRowCategories = false;
450     dptr()->m_autoColumnCategories = false;
451     dptr()->connectItemModelHandler();
452 }
453 
454 /*!
455  * Constructs QItemModelSurfaceDataProxy with \a itemModel and optional \a parent. Proxy doesn't take
456  * ownership of the \a itemModel, as typically item models are owned by other controls.
457  * The role mappings are set with \a rowRole, \a columnRole, \a xPosRole, \a yPosRole,
458  * and \a zPosRole.
459  * Row and column categories are set with \a rowCategories and \a columnCategories.
460  * This constructor also sets autoRowCategories and autoColumnCategories to false.
461  */
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)462 QItemModelSurfaceDataProxy::QItemModelSurfaceDataProxy(QAbstractItemModel *itemModel,
463                                                        const QString &rowRole,
464                                                        const QString &columnRole,
465                                                        const QString &xPosRole,
466                                                        const QString &yPosRole,
467                                                        const QString &zPosRole,
468                                                        const QStringList &rowCategories,
469                                                        const QStringList &columnCategories,
470                                                        QObject *parent)
471     : QSurfaceDataProxy(new QItemModelSurfaceDataProxyPrivate(this), parent)
472 {
473     dptr()->m_itemModelHandler->setItemModel(itemModel);
474     dptr()->m_rowRole = rowRole;
475     dptr()->m_columnRole = columnRole;
476     dptr()->m_xPosRole = xPosRole;
477     dptr()->m_yPosRole = yPosRole;
478     dptr()->m_zPosRole = zPosRole;
479     dptr()->m_rowCategories = rowCategories;
480     dptr()->m_columnCategories = columnCategories;
481     dptr()->m_autoRowCategories = false;
482     dptr()->m_autoColumnCategories = false;
483     dptr()->connectItemModelHandler();
484 }
485 
486 /*!
487  * Destroys QItemModelSurfaceDataProxy.
488  */
~QItemModelSurfaceDataProxy()489 QItemModelSurfaceDataProxy::~QItemModelSurfaceDataProxy()
490 {
491 }
492 
493 /*!
494  * \property QItemModelSurfaceDataProxy::itemModel
495  *
496  * \brief The item model used as a data source for the 3D surface.
497  */
498 
499 /*!
500  * Sets the item model to \a itemModel. Does not take ownership of the model,
501  * but does connect to it to listen for changes.
502  */
setItemModel(QAbstractItemModel * itemModel)503 void QItemModelSurfaceDataProxy::setItemModel(QAbstractItemModel *itemModel)
504 {
505     dptr()->m_itemModelHandler->setItemModel(itemModel);
506 }
507 
itemModel() const508 QAbstractItemModel *QItemModelSurfaceDataProxy::itemModel() const
509 {
510     return dptrc()->m_itemModelHandler->itemModel();
511 }
512 
513 /*!
514  * \property QItemModelSurfaceDataProxy::rowRole
515  *
516  * \brief The item model role to map to the row category.
517  *
518  * In addition to defining which row the data belongs to, the value indicated by the row role
519  * is also set as the Z-coordinate value of QSurfaceDataItem when model data is resolved,
520  * unless a separate z position role is also defined.
521  */
setRowRole(const QString & role)522 void QItemModelSurfaceDataProxy::setRowRole(const QString &role)
523 {
524     if (dptr()->m_rowRole != role) {
525         dptr()->m_rowRole = role;
526         emit rowRoleChanged(role);
527     }
528 }
529 
rowRole() const530 QString QItemModelSurfaceDataProxy::rowRole() const
531 {
532     return dptrc()->m_rowRole;
533 }
534 
535 /*!
536  * \property QItemModelSurfaceDataProxy::columnRole
537  *
538  * \brief The item model role to map to the column category.
539  *
540  * In addition to defining which column the data belongs to, the value indicated by the column
541  * role is also set as the X-coordinate value of QSurfaceDataItem when model data is resolved,
542  * unless a separate x position role is also defined.
543  */
setColumnRole(const QString & role)544 void QItemModelSurfaceDataProxy::setColumnRole(const QString &role)
545 {
546     if (dptr()->m_columnRole != role) {
547         dptr()->m_columnRole = role;
548         emit columnRoleChanged(role);
549     }
550 }
551 
columnRole() const552 QString QItemModelSurfaceDataProxy::columnRole() const
553 {
554     return dptrc()->m_columnRole;
555 }
556 
557 /*!
558  * \property QItemModelSurfaceDataProxy::xPosRole
559  *
560  * \brief The item model role to map to the X position.
561  *
562  * If this role is not defined, columnRole is used to determine the X-coordinate
563  * value of the resolved \l{QSurfaceDataItem} objects.
564  */
setXPosRole(const QString & role)565 void QItemModelSurfaceDataProxy::setXPosRole(const QString &role)
566 {
567     if (dptr()->m_xPosRole != role) {
568         dptr()->m_xPosRole = role;
569         emit xPosRoleChanged(role);
570     }
571 }
572 
xPosRole() const573 QString QItemModelSurfaceDataProxy::xPosRole() const
574 {
575     return dptrc()->m_xPosRole;
576 }
577 
578 /*!
579  * \property QItemModelSurfaceDataProxy::yPosRole
580  *
581  * \brief The item model role to map to the Y position.
582  */
setYPosRole(const QString & role)583 void QItemModelSurfaceDataProxy::setYPosRole(const QString &role)
584 {
585     if (dptr()->m_yPosRole != role) {
586         dptr()->m_yPosRole = role;
587         emit yPosRoleChanged(role);
588     }
589 }
590 
yPosRole() const591 QString QItemModelSurfaceDataProxy::yPosRole() const
592 {
593     return dptrc()->m_yPosRole;
594 }
595 
596 /*!
597  * \property QItemModelSurfaceDataProxy::zPosRole
598  *
599  * \brief The item model role to map to the Z position.
600  *
601  * If this role is not defined, rowRole is used to determine the Z-coordinate
602  * value of resolved \l{QSurfaceDataItem} objects.
603  */
setZPosRole(const QString & role)604 void QItemModelSurfaceDataProxy::setZPosRole(const QString &role)
605 {
606     if (dptr()->m_zPosRole != role) {
607         dptr()->m_zPosRole = role;
608         emit zPosRoleChanged(role);
609     }
610 }
611 
zPosRole() const612 QString QItemModelSurfaceDataProxy::zPosRole() const
613 {
614     return dptrc()->m_zPosRole;
615 }
616 
617 /*!
618  * \property QItemModelSurfaceDataProxy::rowCategories
619  *
620  * \brief The row categories for the mapping.
621  */
setRowCategories(const QStringList & categories)622 void QItemModelSurfaceDataProxy::setRowCategories(const QStringList &categories)
623 {
624     if (dptr()->m_rowCategories != categories) {
625         dptr()->m_rowCategories = categories;
626         emit rowCategoriesChanged();
627     }
628 }
629 
rowCategories() const630 QStringList QItemModelSurfaceDataProxy::rowCategories() const
631 {
632     return dptrc()->m_rowCategories;
633 }
634 
635 /*!
636  * \property QItemModelSurfaceDataProxy::columnCategories
637  *
638  * \brief The column categories for the mapping.
639  */
setColumnCategories(const QStringList & categories)640 void QItemModelSurfaceDataProxy::setColumnCategories(const QStringList &categories)
641 {
642     if (dptr()->m_columnCategories != categories) {
643         dptr()->m_columnCategories = categories;
644         emit columnCategoriesChanged();
645     }
646 }
647 
columnCategories() const648 QStringList QItemModelSurfaceDataProxy::columnCategories() const
649 {
650     return dptrc()->m_columnCategories;
651 }
652 
653 /*!
654  * \property QItemModelSurfaceDataProxy::useModelCategories
655  *
656  * \brief Whether row and column roles and categories are used for mapping.
657  *
658  * When set to \c true, the mapping ignores row and column roles and categories, and uses
659  * the rows and columns from the model instead. Defaults to \c{false}.
660  */
setUseModelCategories(bool enable)661 void QItemModelSurfaceDataProxy::setUseModelCategories(bool enable)
662 {
663     if (dptr()->m_useModelCategories != enable) {
664         dptr()->m_useModelCategories = enable;
665         emit useModelCategoriesChanged(enable);
666     }
667 }
668 
useModelCategories() const669 bool QItemModelSurfaceDataProxy::useModelCategories() const
670 {
671     return dptrc()->m_useModelCategories;
672 }
673 
674 /*!
675  * \property QItemModelSurfaceDataProxy::autoRowCategories
676  *
677  * \brief Whether row categories are generated automatically.
678  *
679  * When set to \c true, the mapping ignores any explicitly set row categories
680  * and overwrites them with automatically generated ones whenever the
681  * data from the model is resolved. Defaults to \c{true}.
682  */
setAutoRowCategories(bool enable)683 void QItemModelSurfaceDataProxy::setAutoRowCategories(bool enable)
684 {
685     if (dptr()->m_autoRowCategories != enable) {
686         dptr()->m_autoRowCategories = enable;
687         emit autoRowCategoriesChanged(enable);
688     }
689 }
690 
autoRowCategories() const691 bool QItemModelSurfaceDataProxy::autoRowCategories() const
692 {
693     return dptrc()->m_autoRowCategories;
694 }
695 
696 /*!
697  * \property QItemModelSurfaceDataProxy::autoColumnCategories
698  *
699  * \brief Whether column categories are generated automatically.
700  *
701  * When set to \c true, the mapping ignores any explicitly set column categories
702  * and overwrites them with automatically generated ones whenever the
703  * data from the model is resolved. Defaults to \c{true}.
704  */
setAutoColumnCategories(bool enable)705 void QItemModelSurfaceDataProxy::setAutoColumnCategories(bool enable)
706 {
707     if (dptr()->m_autoColumnCategories != enable) {
708         dptr()->m_autoColumnCategories = enable;
709         emit autoColumnCategoriesChanged(enable);
710     }
711 }
712 
autoColumnCategories() const713 bool QItemModelSurfaceDataProxy::autoColumnCategories() const
714 {
715     return dptrc()->m_autoColumnCategories;
716 }
717 
718 /*!
719  * Changes \a rowRole, \a columnRole, \a xPosRole, \a yPosRole, \a zPosRole,
720  * \a rowCategories and \a columnCategories to the mapping.
721  */
remap(const QString & rowRole,const QString & columnRole,const QString & xPosRole,const QString & yPosRole,const QString & zPosRole,const QStringList & rowCategories,const QStringList & columnCategories)722 void QItemModelSurfaceDataProxy::remap(const QString &rowRole,
723                                        const QString &columnRole,
724                                        const QString &xPosRole,
725                                        const QString &yPosRole,
726                                        const QString &zPosRole,
727                                        const QStringList &rowCategories,
728                                        const QStringList &columnCategories)
729 {
730     setRowRole(rowRole);
731     setColumnRole(columnRole);
732     setXPosRole(xPosRole);
733     setYPosRole(yPosRole);
734     setZPosRole(zPosRole);
735     setRowCategories(rowCategories);
736     setColumnCategories(columnCategories);
737 }
738 
739 /*!
740  * Returns the index of the specified \a category in the row categories list.
741  * If the row categories list is empty, -1 is returned.
742  * \note If the automatic row categories generation is in use, this method will
743  * not return a valid index before the data in the model is resolved for the first time.
744  */
rowCategoryIndex(const QString & category)745 int QItemModelSurfaceDataProxy::rowCategoryIndex(const QString &category)
746 {
747     return dptr()->m_rowCategories.indexOf(category);
748 }
749 
750 /*!
751  * Returns the index of the specified \a category in the column categories list.
752  * If the category is not found, -1 is returned.
753  * \note If the automatic column categories generation is in use, this method will
754  * not return a valid index before the data in the model is resolved for the first time.
755  */
columnCategoryIndex(const QString & category)756 int QItemModelSurfaceDataProxy::columnCategoryIndex(const QString &category)
757 {
758     return dptr()->m_columnCategories.indexOf(category);
759 }
760 
761 /*!
762  * \property QItemModelSurfaceDataProxy::rowRolePattern
763  *
764  * \brief Whether a search and replace is performed on the value mapped by the
765  * row role before it is used as a row category.
766  *
767  * This property specifies the regular expression to find the portion of the
768  * mapped value to replace and the rowRoleReplace property contains the
769  * replacement string.
770  *
771  * \sa rowRole, rowRoleReplace
772  */
setRowRolePattern(const QRegExp & pattern)773 void QItemModelSurfaceDataProxy::setRowRolePattern(const QRegExp &pattern)
774 {
775     if (dptr()->m_rowRolePattern != pattern) {
776         dptr()->m_rowRolePattern = pattern;
777         emit rowRolePatternChanged(pattern);
778     }
779 }
780 
rowRolePattern() const781 QRegExp QItemModelSurfaceDataProxy::rowRolePattern() const
782 {
783     return dptrc()->m_rowRolePattern;
784 }
785 
786 /*!
787  * \property QItemModelSurfaceDataProxy::columnRolePattern
788  *
789  * \brief Whether a search and replace is done on the value mapped by the column
790  * role before it is used as a column category.
791  *
792  * This property specifies the regular expression to find the portion of the
793  * mapped value to replace and the columnRoleReplace property contains the
794  * replacement string.
795  *
796  * \sa columnRole, columnRoleReplace
797  */
setColumnRolePattern(const QRegExp & pattern)798 void QItemModelSurfaceDataProxy::setColumnRolePattern(const QRegExp &pattern)
799 {
800     if (dptr()->m_columnRolePattern != pattern) {
801         dptr()->m_columnRolePattern = pattern;
802         emit columnRolePatternChanged(pattern);
803     }
804 }
805 
columnRolePattern() const806 QRegExp QItemModelSurfaceDataProxy::columnRolePattern() const
807 {
808     return dptrc()->m_columnRolePattern;
809 }
810 
811 /*!
812  * \property QItemModelSurfaceDataProxy::xPosRolePattern
813  *
814  * \brief Whether a search and replace is done on the value mapped by the x
815  * position role before it is used as an item position value.
816  *
817  * This property specifies the regular expression to find the portion of the
818  * mapped value to replace and the xPosRoleReplace property contains the
819  * replacement string.
820  *
821  * \sa xPosRole, xPosRoleReplace
822  */
setXPosRolePattern(const QRegExp & pattern)823 void QItemModelSurfaceDataProxy::setXPosRolePattern(const QRegExp &pattern)
824 {
825     if (dptr()->m_xPosRolePattern != pattern) {
826         dptr()->m_xPosRolePattern = pattern;
827         emit xPosRolePatternChanged(pattern);
828     }
829 }
830 
xPosRolePattern() const831 QRegExp QItemModelSurfaceDataProxy::xPosRolePattern() const
832 {
833     return dptrc()->m_xPosRolePattern;
834 }
835 
836 /*!
837  * \property QItemModelSurfaceDataProxy::yPosRolePattern
838  *
839  * \brief Whether a search and replace is done on the value mapped by the y
840  * position role before it is used as an item position value.
841  *
842  * This property specifies the regular expression to find the portion of the
843  * mapped value to replace and the yPosRoleReplace property contains the
844  * replacement string.
845  *
846  * \sa yPosRole, yPosRoleReplace
847  */
setYPosRolePattern(const QRegExp & pattern)848 void QItemModelSurfaceDataProxy::setYPosRolePattern(const QRegExp &pattern)
849 {
850     if (dptr()->m_yPosRolePattern != pattern) {
851         dptr()->m_yPosRolePattern = pattern;
852         emit yPosRolePatternChanged(pattern);
853     }
854 }
855 
yPosRolePattern() const856 QRegExp QItemModelSurfaceDataProxy::yPosRolePattern() const
857 {
858     return dptrc()->m_yPosRolePattern;
859 }
860 
861 /*!
862  * \property QItemModelSurfaceDataProxy::zPosRolePattern
863  *
864  * \brief Whether a search and replace is done on the value mapped by the z
865  * position role before it is used as an item position value.
866  *
867  * This property specifies the regular expression to find the portion of the
868  * mapped value to replace and the zPosRoleReplace property contains the
869  * replacement string.
870  *
871  * \sa zPosRole, zPosRoleReplace
872  */
setZPosRolePattern(const QRegExp & pattern)873 void QItemModelSurfaceDataProxy::setZPosRolePattern(const QRegExp &pattern)
874 {
875     if (dptr()->m_zPosRolePattern != pattern) {
876         dptr()->m_zPosRolePattern = pattern;
877         emit zPosRolePatternChanged(pattern);
878     }
879 }
880 
zPosRolePattern() const881 QRegExp QItemModelSurfaceDataProxy::zPosRolePattern() const
882 {
883     return dptrc()->m_zPosRolePattern;
884 }
885 
886 /*!
887  * \property QItemModelSurfaceDataProxy::rowRoleReplace
888  *
889  * \brief The replace content to be used in conjunction with the row role
890  * pattern.
891  *
892  * Defaults to an empty string. For more information on how the search and replace using regular
893  * expressions works, see QString::replace(const QRegExp &rx, const QString &after)
894  * function documentation.
895  *
896  * \sa rowRole, rowRolePattern
897  */
setRowRoleReplace(const QString & replace)898 void QItemModelSurfaceDataProxy::setRowRoleReplace(const QString &replace)
899 {
900     if (dptr()->m_rowRoleReplace != replace) {
901         dptr()->m_rowRoleReplace = replace;
902         emit rowRoleReplaceChanged(replace);
903     }
904 }
905 
rowRoleReplace() const906 QString QItemModelSurfaceDataProxy::rowRoleReplace() const
907 {
908     return dptrc()->m_rowRoleReplace;
909 }
910 
911 /*!
912  * \property QItemModelSurfaceDataProxy::columnRoleReplace
913  *
914  * \brief The replace content to be used in conjunction with a column role
915  * pattern.
916  *
917  * Defaults to an empty string. For more information on how the search and
918  * replace using regular expressions works, see the
919  * QString::replace(const QRegExp &rx, const QString &after)
920  * function documentation.
921  *
922  * \sa columnRole, columnRolePattern
923  */
setColumnRoleReplace(const QString & replace)924 void QItemModelSurfaceDataProxy::setColumnRoleReplace(const QString &replace)
925 {
926     if (dptr()->m_columnRoleReplace != replace) {
927         dptr()->m_columnRoleReplace = replace;
928         emit columnRoleReplaceChanged(replace);
929     }
930 }
931 
columnRoleReplace() const932 QString QItemModelSurfaceDataProxy::columnRoleReplace() const
933 {
934     return dptrc()->m_columnRoleReplace;
935 }
936 
937 /*!
938  * \property QItemModelSurfaceDataProxy::xPosRoleReplace
939  *
940  * \brief The replace content to be used in conjunction with an x position role
941  * pattern.
942  *
943  * Defaults to an empty string. For more information on how the search and
944  * replace using regular expressions works, see the
945  * QString::replace(const QRegExp &rx, const QString &after)
946  * function documentation.
947  *
948  * \sa xPosRole, xPosRolePattern
949  */
setXPosRoleReplace(const QString & replace)950 void QItemModelSurfaceDataProxy::setXPosRoleReplace(const QString &replace)
951 {
952     if (dptr()->m_xPosRoleReplace != replace) {
953         dptr()->m_xPosRoleReplace = replace;
954         emit xPosRoleReplaceChanged(replace);
955     }
956 }
957 
xPosRoleReplace() const958 QString QItemModelSurfaceDataProxy::xPosRoleReplace() const
959 {
960     return dptrc()->m_xPosRoleReplace;
961 }
962 
963 /*!
964  * \property QItemModelSurfaceDataProxy::yPosRoleReplace
965  *
966  * \brief The replace content to be used in conjunction with an y position role
967  * pattern.
968  *
969  * Defaults to an empty string. For more information on how the search and
970  * replace using regular expressions works, see the
971  * QString::replace(const QRegExp &rx, const QString &after)
972  * function documentation.
973  *
974  * \sa yPosRole, yPosRolePattern
975  */
setYPosRoleReplace(const QString & replace)976 void QItemModelSurfaceDataProxy::setYPosRoleReplace(const QString &replace)
977 {
978     if (dptr()->m_yPosRoleReplace != replace) {
979         dptr()->m_yPosRoleReplace = replace;
980         emit yPosRoleReplaceChanged(replace);
981     }
982 }
983 
yPosRoleReplace() const984 QString QItemModelSurfaceDataProxy::yPosRoleReplace() const
985 {
986     return dptrc()->m_yPosRoleReplace;
987 }
988 
989 /*!
990  * \property QItemModelSurfaceDataProxy::zPosRoleReplace
991  *
992  * \brief The replace content to be used in conjunction with a z position role
993  * pattern.
994  *
995  * Defaults to an empty string. For more information on how the search and
996  * replace using regular expressions works, see the
997  * QString::replace(const QRegExp &rx, const QString &after)
998  * function documentation.
999  *
1000  * \sa zPosRole, zPosRolePattern
1001  */
setZPosRoleReplace(const QString & replace)1002 void QItemModelSurfaceDataProxy::setZPosRoleReplace(const QString &replace)
1003 {
1004     if (dptr()->m_zPosRoleReplace != replace) {
1005         dptr()->m_zPosRoleReplace = replace;
1006         emit zPosRoleReplaceChanged(replace);
1007     }
1008 }
1009 
zPosRoleReplace() const1010 QString QItemModelSurfaceDataProxy::zPosRoleReplace() const
1011 {
1012     return dptrc()->m_zPosRoleReplace;
1013 }
1014 
1015 /*!
1016  * \property QItemModelSurfaceDataProxy::multiMatchBehavior
1017  *
1018  * \brief How multiple matches for each row/column combination are handled.
1019  *
1020  * Defaults to MMBLast.
1021  *
1022  * For example, you might have an item model with timestamped data taken at irregular intervals
1023  * and you want to visualize an average position of data items on each hour with a surface graph.
1024  * This can be done by specifying row and column categories so that each surface point represents
1025  * an hour, and setting this property to MMBAverage.
1026  */
1027 
setMultiMatchBehavior(QItemModelSurfaceDataProxy::MultiMatchBehavior behavior)1028 void QItemModelSurfaceDataProxy::setMultiMatchBehavior(QItemModelSurfaceDataProxy::MultiMatchBehavior behavior)
1029 {
1030     if (dptr()->m_multiMatchBehavior != behavior) {
1031         dptr()->m_multiMatchBehavior = behavior;
1032         emit multiMatchBehaviorChanged(behavior);
1033     }
1034 }
1035 
multiMatchBehavior() const1036 QItemModelSurfaceDataProxy::MultiMatchBehavior QItemModelSurfaceDataProxy::multiMatchBehavior() const
1037 {
1038     return dptrc()->m_multiMatchBehavior;
1039 }
1040 
1041 /*!
1042  * \internal
1043  */
dptr()1044 QItemModelSurfaceDataProxyPrivate *QItemModelSurfaceDataProxy::dptr()
1045 {
1046     return static_cast<QItemModelSurfaceDataProxyPrivate *>(d_ptr.data());
1047 }
1048 
1049 /*!
1050  * \internal
1051  */
dptrc() const1052 const QItemModelSurfaceDataProxyPrivate *QItemModelSurfaceDataProxy::dptrc() const
1053 {
1054     return static_cast<const QItemModelSurfaceDataProxyPrivate *>(d_ptr.data());
1055 }
1056 
1057 // QItemModelSurfaceDataProxyPrivate
1058 
QItemModelSurfaceDataProxyPrivate(QItemModelSurfaceDataProxy * q)1059 QItemModelSurfaceDataProxyPrivate::QItemModelSurfaceDataProxyPrivate(QItemModelSurfaceDataProxy *q)
1060     : QSurfaceDataProxyPrivate(q),
1061       m_itemModelHandler(new SurfaceItemModelHandler(q)),
1062       m_useModelCategories(false),
1063       m_autoRowCategories(true),
1064       m_autoColumnCategories(true),
1065       m_multiMatchBehavior(QItemModelSurfaceDataProxy::MMBLast)
1066 {
1067 }
1068 
~QItemModelSurfaceDataProxyPrivate()1069 QItemModelSurfaceDataProxyPrivate::~QItemModelSurfaceDataProxyPrivate()
1070 {
1071     delete m_itemModelHandler;
1072 }
1073 
qptr()1074 QItemModelSurfaceDataProxy *QItemModelSurfaceDataProxyPrivate::qptr()
1075 {
1076     return static_cast<QItemModelSurfaceDataProxy *>(q_ptr);
1077 }
1078 
connectItemModelHandler()1079 void QItemModelSurfaceDataProxyPrivate::connectItemModelHandler()
1080 {
1081     QObject::connect(m_itemModelHandler, &SurfaceItemModelHandler::itemModelChanged,
1082                      qptr(), &QItemModelSurfaceDataProxy::itemModelChanged);
1083     QObject::connect(qptr(), &QItemModelSurfaceDataProxy::rowRoleChanged,
1084                      m_itemModelHandler, &AbstractItemModelHandler::handleMappingChanged);
1085     QObject::connect(qptr(), &QItemModelSurfaceDataProxy::columnRoleChanged,
1086                      m_itemModelHandler, &AbstractItemModelHandler::handleMappingChanged);
1087     QObject::connect(qptr(), &QItemModelSurfaceDataProxy::xPosRoleChanged,
1088                      m_itemModelHandler, &AbstractItemModelHandler::handleMappingChanged);
1089     QObject::connect(qptr(), &QItemModelSurfaceDataProxy::yPosRoleChanged,
1090                      m_itemModelHandler, &AbstractItemModelHandler::handleMappingChanged);
1091     QObject::connect(qptr(), &QItemModelSurfaceDataProxy::zPosRoleChanged,
1092                      m_itemModelHandler, &AbstractItemModelHandler::handleMappingChanged);
1093     QObject::connect(qptr(), &QItemModelSurfaceDataProxy::rowCategoriesChanged,
1094                      m_itemModelHandler, &AbstractItemModelHandler::handleMappingChanged);
1095     QObject::connect(qptr(), &QItemModelSurfaceDataProxy::columnCategoriesChanged,
1096                      m_itemModelHandler, &AbstractItemModelHandler::handleMappingChanged);
1097     QObject::connect(qptr(), &QItemModelSurfaceDataProxy::useModelCategoriesChanged,
1098                      m_itemModelHandler, &AbstractItemModelHandler::handleMappingChanged);
1099     QObject::connect(qptr(), &QItemModelSurfaceDataProxy::autoRowCategoriesChanged,
1100                      m_itemModelHandler, &AbstractItemModelHandler::handleMappingChanged);
1101     QObject::connect(qptr(), &QItemModelSurfaceDataProxy::autoColumnCategoriesChanged,
1102                      m_itemModelHandler, &AbstractItemModelHandler::handleMappingChanged);
1103     QObject::connect(qptr(), &QItemModelSurfaceDataProxy::rowRolePatternChanged,
1104                      m_itemModelHandler, &AbstractItemModelHandler::handleMappingChanged);
1105     QObject::connect(qptr(), &QItemModelSurfaceDataProxy::columnRolePatternChanged,
1106                      m_itemModelHandler, &AbstractItemModelHandler::handleMappingChanged);
1107     QObject::connect(qptr(), &QItemModelSurfaceDataProxy::xPosRolePatternChanged,
1108                      m_itemModelHandler, &AbstractItemModelHandler::handleMappingChanged);
1109     QObject::connect(qptr(), &QItemModelSurfaceDataProxy::yPosRolePatternChanged,
1110                      m_itemModelHandler, &AbstractItemModelHandler::handleMappingChanged);
1111     QObject::connect(qptr(), &QItemModelSurfaceDataProxy::zPosRolePatternChanged,
1112                      m_itemModelHandler, &AbstractItemModelHandler::handleMappingChanged);
1113     QObject::connect(qptr(), &QItemModelSurfaceDataProxy::rowRoleReplaceChanged,
1114                      m_itemModelHandler, &AbstractItemModelHandler::handleMappingChanged);
1115     QObject::connect(qptr(), &QItemModelSurfaceDataProxy::columnRoleReplaceChanged,
1116                      m_itemModelHandler, &AbstractItemModelHandler::handleMappingChanged);
1117     QObject::connect(qptr(), &QItemModelSurfaceDataProxy::xPosRoleReplaceChanged,
1118                      m_itemModelHandler, &AbstractItemModelHandler::handleMappingChanged);
1119     QObject::connect(qptr(), &QItemModelSurfaceDataProxy::yPosRoleReplaceChanged,
1120                      m_itemModelHandler, &AbstractItemModelHandler::handleMappingChanged);
1121     QObject::connect(qptr(), &QItemModelSurfaceDataProxy::zPosRoleReplaceChanged,
1122                      m_itemModelHandler, &AbstractItemModelHandler::handleMappingChanged);
1123     QObject::connect(qptr(), &QItemModelSurfaceDataProxy::multiMatchBehaviorChanged,
1124                      m_itemModelHandler, &AbstractItemModelHandler::handleMappingChanged);
1125 }
1126 
1127 QT_END_NAMESPACE_DATAVISUALIZATION
1128