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