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
33QT_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 */
342QItemModelSurfaceDataProxy::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 */
352QItemModelSurfaceDataProxy::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 */
367QItemModelSurfaceDataProxy::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 */
384QItemModelSurfaceDataProxy::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 */
406QItemModelSurfaceDataProxy::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 */
432QItemModelSurfaceDataProxy::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 */
462QItemModelSurfaceDataProxy::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 */
489QItemModelSurfaceDataProxy::~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 */
503void QItemModelSurfaceDataProxy::setItemModel(QAbstractItemModel *itemModel)
504{
505 dptr()->m_itemModelHandler->setItemModel(itemModel);
506}
507
508QAbstractItemModel *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 */
522void QItemModelSurfaceDataProxy::setRowRole(const QString &role)
523{
524 if (dptr()->m_rowRole != role) {
525 dptr()->m_rowRole = role;
526 emit rowRoleChanged(role);
527 }
528}
529
530QString 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 */
544void QItemModelSurfaceDataProxy::setColumnRole(const QString &role)
545{
546 if (dptr()->m_columnRole != role) {
547 dptr()->m_columnRole = role;
548 emit columnRoleChanged(role);
549 }
550}
551
552QString 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 */
565void QItemModelSurfaceDataProxy::setXPosRole(const QString &role)
566{
567 if (dptr()->m_xPosRole != role) {
568 dptr()->m_xPosRole = role;
569 emit xPosRoleChanged(role);
570 }
571}
572
573QString 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 */
583void QItemModelSurfaceDataProxy::setYPosRole(const QString &role)
584{
585 if (dptr()->m_yPosRole != role) {
586 dptr()->m_yPosRole = role;
587 emit yPosRoleChanged(role);
588 }
589}
590
591QString 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 */
604void QItemModelSurfaceDataProxy::setZPosRole(const QString &role)
605{
606 if (dptr()->m_zPosRole != role) {
607 dptr()->m_zPosRole = role;
608 emit zPosRoleChanged(role);
609 }
610}
611
612QString 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 */
622void QItemModelSurfaceDataProxy::setRowCategories(const QStringList &categories)
623{
624 if (dptr()->m_rowCategories != categories) {
625 dptr()->m_rowCategories = categories;
626 emit rowCategoriesChanged();
627 }
628}
629
630QStringList 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 */
640void QItemModelSurfaceDataProxy::setColumnCategories(const QStringList &categories)
641{
642 if (dptr()->m_columnCategories != categories) {
643 dptr()->m_columnCategories = categories;
644 emit columnCategoriesChanged();
645 }
646}
647
648QStringList 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 */
661void QItemModelSurfaceDataProxy::setUseModelCategories(bool enable)
662{
663 if (dptr()->m_useModelCategories != enable) {
664 dptr()->m_useModelCategories = enable;
665 emit useModelCategoriesChanged(enable);
666 }
667}
668
669bool 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 */
683void QItemModelSurfaceDataProxy::setAutoRowCategories(bool enable)
684{
685 if (dptr()->m_autoRowCategories != enable) {
686 dptr()->m_autoRowCategories = enable;
687 emit autoRowCategoriesChanged(enable);
688 }
689}
690
691bool 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 */
705void QItemModelSurfaceDataProxy::setAutoColumnCategories(bool enable)
706{
707 if (dptr()->m_autoColumnCategories != enable) {
708 dptr()->m_autoColumnCategories = enable;
709 emit autoColumnCategoriesChanged(enable);
710 }
711}
712
713bool 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 */
722void 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 */
745int QItemModelSurfaceDataProxy::rowCategoryIndex(const QString &category)
746{
747 return dptr()->m_rowCategories.indexOf(t: 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 */
756int QItemModelSurfaceDataProxy::columnCategoryIndex(const QString &category)
757{
758 return dptr()->m_columnCategories.indexOf(t: 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 */
773void QItemModelSurfaceDataProxy::setRowRolePattern(const QRegExp &pattern)
774{
775 if (dptr()->m_rowRolePattern != pattern) {
776 dptr()->m_rowRolePattern = pattern;
777 emit rowRolePatternChanged(pattern);
778 }
779}
780
781QRegExp 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 */
798void QItemModelSurfaceDataProxy::setColumnRolePattern(const QRegExp &pattern)
799{
800 if (dptr()->m_columnRolePattern != pattern) {
801 dptr()->m_columnRolePattern = pattern;
802 emit columnRolePatternChanged(pattern);
803 }
804}
805
806QRegExp 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 */
823void QItemModelSurfaceDataProxy::setXPosRolePattern(const QRegExp &pattern)
824{
825 if (dptr()->m_xPosRolePattern != pattern) {
826 dptr()->m_xPosRolePattern = pattern;
827 emit xPosRolePatternChanged(pattern);
828 }
829}
830
831QRegExp 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 */
848void QItemModelSurfaceDataProxy::setYPosRolePattern(const QRegExp &pattern)
849{
850 if (dptr()->m_yPosRolePattern != pattern) {
851 dptr()->m_yPosRolePattern = pattern;
852 emit yPosRolePatternChanged(pattern);
853 }
854}
855
856QRegExp 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 */
873void QItemModelSurfaceDataProxy::setZPosRolePattern(const QRegExp &pattern)
874{
875 if (dptr()->m_zPosRolePattern != pattern) {
876 dptr()->m_zPosRolePattern = pattern;
877 emit zPosRolePatternChanged(pattern);
878 }
879}
880
881QRegExp 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 */
898void QItemModelSurfaceDataProxy::setRowRoleReplace(const QString &replace)
899{
900 if (dptr()->m_rowRoleReplace != replace) {
901 dptr()->m_rowRoleReplace = replace;
902 emit rowRoleReplaceChanged(replace);
903 }
904}
905
906QString 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 */
924void QItemModelSurfaceDataProxy::setColumnRoleReplace(const QString &replace)
925{
926 if (dptr()->m_columnRoleReplace != replace) {
927 dptr()->m_columnRoleReplace = replace;
928 emit columnRoleReplaceChanged(replace);
929 }
930}
931
932QString 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 */
950void QItemModelSurfaceDataProxy::setXPosRoleReplace(const QString &replace)
951{
952 if (dptr()->m_xPosRoleReplace != replace) {
953 dptr()->m_xPosRoleReplace = replace;
954 emit xPosRoleReplaceChanged(replace);
955 }
956}
957
958QString 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 */
976void QItemModelSurfaceDataProxy::setYPosRoleReplace(const QString &replace)
977{
978 if (dptr()->m_yPosRoleReplace != replace) {
979 dptr()->m_yPosRoleReplace = replace;
980 emit yPosRoleReplaceChanged(replace);
981 }
982}
983
984QString 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 */
1002void QItemModelSurfaceDataProxy::setZPosRoleReplace(const QString &replace)
1003{
1004 if (dptr()->m_zPosRoleReplace != replace) {
1005 dptr()->m_zPosRoleReplace = replace;
1006 emit zPosRoleReplaceChanged(replace);
1007 }
1008}
1009
1010QString 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
1028void QItemModelSurfaceDataProxy::setMultiMatchBehavior(QItemModelSurfaceDataProxy::MultiMatchBehavior behavior)
1029{
1030 if (dptr()->m_multiMatchBehavior != behavior) {
1031 dptr()->m_multiMatchBehavior = behavior;
1032 emit multiMatchBehaviorChanged(behavior);
1033 }
1034}
1035
1036QItemModelSurfaceDataProxy::MultiMatchBehavior QItemModelSurfaceDataProxy::multiMatchBehavior() const
1037{
1038 return dptrc()->m_multiMatchBehavior;
1039}
1040
1041/*!
1042 * \internal
1043 */
1044QItemModelSurfaceDataProxyPrivate *QItemModelSurfaceDataProxy::dptr()
1045{
1046 return static_cast<QItemModelSurfaceDataProxyPrivate *>(d_ptr.data());
1047}
1048
1049/*!
1050 * \internal
1051 */
1052const QItemModelSurfaceDataProxyPrivate *QItemModelSurfaceDataProxy::dptrc() const
1053{
1054 return static_cast<const QItemModelSurfaceDataProxyPrivate *>(d_ptr.data());
1055}
1056
1057// QItemModelSurfaceDataProxyPrivate
1058
1059QItemModelSurfaceDataProxyPrivate::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
1069QItemModelSurfaceDataProxyPrivate::~QItemModelSurfaceDataProxyPrivate()
1070{
1071 delete m_itemModelHandler;
1072}
1073
1074QItemModelSurfaceDataProxy *QItemModelSurfaceDataProxyPrivate::qptr()
1075{
1076 return static_cast<QItemModelSurfaceDataProxy *>(q_ptr);
1077}
1078
1079void QItemModelSurfaceDataProxyPrivate::connectItemModelHandler()
1080{
1081 QObject::connect(sender: m_itemModelHandler, signal: &SurfaceItemModelHandler::itemModelChanged,
1082 receiver: qptr(), slot: &QItemModelSurfaceDataProxy::itemModelChanged);
1083 QObject::connect(sender: qptr(), signal: &QItemModelSurfaceDataProxy::rowRoleChanged,
1084 receiver: m_itemModelHandler, slot: &AbstractItemModelHandler::handleMappingChanged);
1085 QObject::connect(sender: qptr(), signal: &QItemModelSurfaceDataProxy::columnRoleChanged,
1086 receiver: m_itemModelHandler, slot: &AbstractItemModelHandler::handleMappingChanged);
1087 QObject::connect(sender: qptr(), signal: &QItemModelSurfaceDataProxy::xPosRoleChanged,
1088 receiver: m_itemModelHandler, slot: &AbstractItemModelHandler::handleMappingChanged);
1089 QObject::connect(sender: qptr(), signal: &QItemModelSurfaceDataProxy::yPosRoleChanged,
1090 receiver: m_itemModelHandler, slot: &AbstractItemModelHandler::handleMappingChanged);
1091 QObject::connect(sender: qptr(), signal: &QItemModelSurfaceDataProxy::zPosRoleChanged,
1092 receiver: m_itemModelHandler, slot: &AbstractItemModelHandler::handleMappingChanged);
1093 QObject::connect(sender: qptr(), signal: &QItemModelSurfaceDataProxy::rowCategoriesChanged,
1094 receiver: m_itemModelHandler, slot: &AbstractItemModelHandler::handleMappingChanged);
1095 QObject::connect(sender: qptr(), signal: &QItemModelSurfaceDataProxy::columnCategoriesChanged,
1096 receiver: m_itemModelHandler, slot: &AbstractItemModelHandler::handleMappingChanged);
1097 QObject::connect(sender: qptr(), signal: &QItemModelSurfaceDataProxy::useModelCategoriesChanged,
1098 receiver: m_itemModelHandler, slot: &AbstractItemModelHandler::handleMappingChanged);
1099 QObject::connect(sender: qptr(), signal: &QItemModelSurfaceDataProxy::autoRowCategoriesChanged,
1100 receiver: m_itemModelHandler, slot: &AbstractItemModelHandler::handleMappingChanged);
1101 QObject::connect(sender: qptr(), signal: &QItemModelSurfaceDataProxy::autoColumnCategoriesChanged,
1102 receiver: m_itemModelHandler, slot: &AbstractItemModelHandler::handleMappingChanged);
1103 QObject::connect(sender: qptr(), signal: &QItemModelSurfaceDataProxy::rowRolePatternChanged,
1104 receiver: m_itemModelHandler, slot: &AbstractItemModelHandler::handleMappingChanged);
1105 QObject::connect(sender: qptr(), signal: &QItemModelSurfaceDataProxy::columnRolePatternChanged,
1106 receiver: m_itemModelHandler, slot: &AbstractItemModelHandler::handleMappingChanged);
1107 QObject::connect(sender: qptr(), signal: &QItemModelSurfaceDataProxy::xPosRolePatternChanged,
1108 receiver: m_itemModelHandler, slot: &AbstractItemModelHandler::handleMappingChanged);
1109 QObject::connect(sender: qptr(), signal: &QItemModelSurfaceDataProxy::yPosRolePatternChanged,
1110 receiver: m_itemModelHandler, slot: &AbstractItemModelHandler::handleMappingChanged);
1111 QObject::connect(sender: qptr(), signal: &QItemModelSurfaceDataProxy::zPosRolePatternChanged,
1112 receiver: m_itemModelHandler, slot: &AbstractItemModelHandler::handleMappingChanged);
1113 QObject::connect(sender: qptr(), signal: &QItemModelSurfaceDataProxy::rowRoleReplaceChanged,
1114 receiver: m_itemModelHandler, slot: &AbstractItemModelHandler::handleMappingChanged);
1115 QObject::connect(sender: qptr(), signal: &QItemModelSurfaceDataProxy::columnRoleReplaceChanged,
1116 receiver: m_itemModelHandler, slot: &AbstractItemModelHandler::handleMappingChanged);
1117 QObject::connect(sender: qptr(), signal: &QItemModelSurfaceDataProxy::xPosRoleReplaceChanged,
1118 receiver: m_itemModelHandler, slot: &AbstractItemModelHandler::handleMappingChanged);
1119 QObject::connect(sender: qptr(), signal: &QItemModelSurfaceDataProxy::yPosRoleReplaceChanged,
1120 receiver: m_itemModelHandler, slot: &AbstractItemModelHandler::handleMappingChanged);
1121 QObject::connect(sender: qptr(), signal: &QItemModelSurfaceDataProxy::zPosRoleReplaceChanged,
1122 receiver: m_itemModelHandler, slot: &AbstractItemModelHandler::handleMappingChanged);
1123 QObject::connect(sender: qptr(), signal: &QItemModelSurfaceDataProxy::multiMatchBehaviorChanged,
1124 receiver: m_itemModelHandler, slot: &AbstractItemModelHandler::handleMappingChanged);
1125}
1126
1127QT_END_NAMESPACE_DATAVISUALIZATION
1128

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