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

source code of qtdatavis3d/src/datavisualization/data/qitemmodelsurfacedataproxy.cpp