1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 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 "qitemmodelbardataproxy_p.h"
31 #include "baritemmodelhandler_p.h"
32 
33 QT_BEGIN_NAMESPACE_DATAVISUALIZATION
34 
35 /*!
36  * \class QItemModelBarDataProxy
37  * \inmodule QtDataVisualization
38  * \brief Proxy class for presenting data in item models with Q3DBars.
39  * \since QtDataVisualization 1.0
40  *
41  * QItemModelBarDataProxy allows you to use QAbstractItemModel derived models as a data source
42  * for Q3DBars. It uses the defined mappings to map data from the model to rows, columns, and
43  * values of Q3DBars graph.
44  *
45  * The data is resolved asynchronously whenever mappings or the model changes.
46  * QBarDataProxy::arrayReset() is emitted when the data has been resolved.
47  * However, when useModelCategories property is set to 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 true, this proxy will map rows and
55  *    columns of QAbstractItemModel directly to rows and columns of Q3DBars, and uses the value
56  *    returned for Qt::DisplayRole as bar value by default.
57  *    The value role to be used can be redefined if Qt::DisplayRole is not suitable.
58  *
59  * \li For models that do not have data already neatly sorted into rows and columns, such as
60  *    QAbstractListModel based models, you can define a role from the model to map for each of row,
61  *    column and value.
62  *
63  * \li If you do not want to include all data contained in the model, or the autogenerated rows and
64  *    columns are not ordered as you wish, you can specify which rows and columns should be included
65  *    and in which order by defining an explicit list of categories for either or both of rows and
66  *    columns.
67  * \endlist
68  *
69  * For example, assume that you have a custom QAbstractItemModel for storing various monthly values
70  * related to a business.
71  * Each item in the model has the roles "year", "month", "income", and "expenses".
72  * You could do the following to display the data in a bar graph:
73  *
74  * \snippet doc_src_qtdatavisualization.cpp 3
75  *
76  * If the fields of the model do not contain the data in the exact format you need, you can specify
77  * a search pattern regular expression and a replace rule for each role to get the value in a
78  * format you need. For more information how the replace using regular expressions works, see
79  * QString::replace(const QRegExp &rx, const QString &after) function documentation. Note that
80  * using regular expressions has an impact on the performance, so it's more efficient to utilize
81  * item models where doing search and replace is not necessary to get the desired values.
82  *
83  * For example about using the search patterns in conjunction with the roles, see
84  * \l{Qt Quick 2 Bars Example}.
85  *
86  * \sa {Qt Data Visualization Data Handling}
87  */
88 
89 /*!
90  * \qmltype ItemModelBarDataProxy
91  * \inqmlmodule QtDataVisualization
92  * \since QtDataVisualization 1.0
93  * \ingroup datavisualization_qml
94  * \instantiates QItemModelBarDataProxy
95  * \inherits BarDataProxy
96  * \brief Proxy class for presenting data in item models with Bars3D.
97  *
98  * This type allows you to use AbstractItemModel derived models as a data source for Bars3D.
99  *
100  * Data is resolved asynchronously whenever the mapping or the model changes.
101  * QBarDataProxy::arrayReset() is emitted when the data has been resolved.
102  *
103  * For ItemModelBarDataProxy enums, see \l{QItemModelBarDataProxy::MultiMatchBehavior}.
104  *
105  * For more details, see QItemModelBarDataProxy documentation.
106  *
107  * Usage example:
108  *
109  * \snippet doc_src_qmldatavisualization.cpp 7
110  *
111  * \sa BarDataProxy, {Qt Data Visualization Data Handling}
112  */
113 
114 /*!
115  * \qmlproperty model ItemModelBarDataProxy::itemModel
116  * The item model.
117  */
118 
119 /*!
120  * \qmlproperty string ItemModelBarDataProxy::rowRole
121  * The item model role to map into row category.
122  */
123 
124 /*!
125  * \qmlproperty string ItemModelBarDataProxy::columnRole
126  * The item model role to map into column category.
127  */
128 
129 /*!
130  * \qmlproperty string ItemModelBarDataProxy::valueRole
131  * The item model role to map into bar value.
132  */
133 
134 /*!
135  * \qmlproperty string ItemModelBarDataProxy::rotationRole
136  * The item model role to map into bar rotation angle.
137  */
138 
139 /*!
140  * \qmlproperty list<String> ItemModelBarDataProxy::rowCategories
141  * The row categories of the mapping. Only items with row role values that are found in this list
142  * are included when the data is resolved. The rows are ordered in the same order as they are in
143  * this list.
144  */
145 
146 /*!
147  * \qmlproperty list<String> ItemModelBarDataProxy::columnCategories
148  * The column categories of the mapping. Only items with column role values that are found in this
149  * list are included when the data is resolved. The columns are ordered in the same order as they
150  * are in this list.
151  */
152 
153 /*!
154  * \qmlproperty bool ItemModelBarDataProxy::useModelCategories
155  * When set to \c true, the mapping ignores row and column roles and categories, and uses
156  * the rows and columns from the model instead. Row and column headers are used for row and column
157  * labels. Defaults to \c{false}.
158  */
159 
160 /*!
161  * \qmlproperty bool ItemModelBarDataProxy::autoRowCategories
162  * When set to \c true, the mapping ignores any explicitly set row categories
163  * and overwrites them with automatically generated ones whenever the
164  * data from the model is resolved. Defaults to \c{true}.
165  */
166 
167 /*!
168  * \qmlproperty bool ItemModelBarDataProxy::autoColumnCategories
169  * When set to \c true, the mapping ignores any explicitly set column categories
170  * and overwrites them with automatically generated ones whenever the
171  * data from model is resolved. Defaults to \c{true}.
172  */
173 
174 /*!
175  * \qmlproperty regExp ItemModelBarDataProxy::rowRolePattern
176  * When set, a search and replace is done on the value mapped by row role before it is used as
177  * a row category. This property specifies the regular expression to find the portion of the
178  * mapped value to replace and rowRoleReplace property contains the replacement string.
179  * This is useful for example in parsing row and column categories from a single
180  * timestamp field in the item model.
181  *
182  * \sa rowRole, rowRoleReplace
183  */
184 
185 /*!
186  * \qmlproperty regExp ItemModelBarDataProxy::columnRolePattern
187  * When set, a search and replace is done on the value mapped by column role before it is used
188  * as a column category. This property specifies the regular expression to find the portion of the
189  * mapped value to replace and columnRoleReplace property contains the replacement string.
190  * This is useful for example in parsing row and column categories from
191  * a single timestamp field in the item model.
192  *
193  * \sa columnRole, columnRoleReplace
194  */
195 
196 /*!
197  * \qmlproperty regExp ItemModelBarDataProxy::valueRolePattern
198  * When set, a search and replace is done on the value mapped by value role before it is used as
199  * a bar value. This property specifies the regular expression to find the portion of the
200  * mapped value to replace and valueRoleReplace property contains the replacement string.
201  *
202  * \sa valueRole, valueRoleReplace
203  */
204 
205 /*!
206  * \qmlproperty regExp ItemModelBarDataProxy::rotationRolePattern
207  * When set, a search and replace is done on the value mapped by rotation role before it is used
208  * as a bar rotation angle. This property specifies the regular expression to find the portion
209  * of the mapped value to replace and rotationRoleReplace property contains the replacement string.
210  *
211  * \sa rotationRole, rotationRoleReplace
212  */
213 
214 /*!
215  * \qmlproperty string ItemModelBarDataProxy::rowRoleReplace
216  * This property defines the replace content to be used in conjunction with rowRolePattern.
217  * Defaults to empty string. For more information on how the search and replace using regular
218  * expressions works, see QString::replace(const QRegExp &rx, const QString &after)
219  * function documentation.
220  *
221  * \sa rowRole, rowRolePattern
222  */
223 
224 /*!
225  * \qmlproperty string ItemModelBarDataProxy::columnRoleReplace
226  * This property defines the replace content to be used in conjunction with columnRolePattern.
227  * Defaults to empty string. For more information on how the search and replace using regular
228  * expressions works, see QString::replace(const QRegExp &rx, const QString &after)
229  * function documentation.
230  *
231  * \sa columnRole, columnRolePattern
232  */
233 
234 /*!
235  * \qmlproperty string ItemModelBarDataProxy::valueRoleReplace
236  * This property defines the replace content to be used in conjunction with valueRolePattern.
237  * Defaults to empty string. For more information on how the search and replace using regular
238  * expressions works, see QString::replace(const QRegExp &rx, const QString &after)
239  * function documentation.
240  *
241  * \sa valueRole, valueRolePattern
242  */
243 
244 /*!
245  * \qmlproperty string ItemModelBarDataProxy::rotationRoleReplace
246  * This property defines the replace content to be used in conjunction with rotationRolePattern.
247  * Defaults to empty string. For more information on how the search and replace using regular
248  * expressions works, see QString::replace(const QRegExp &rx, const QString &after)
249  * function documentation.
250  *
251  * \sa rotationRole, rotationRolePattern
252  */
253 
254 /*!
255  * \qmlproperty ItemModelBarDataProxy.MultiMatchBehavior ItemModelBarDataProxy::multiMatchBehavior
256  * Defines how multiple matches for each row/column combination are handled.
257  * Defaults to \l{QItemModelBarDataProxy::MMBLast}{ItemModelBarDataProxy.MMBLast}. The chosen
258  * behavior affects both bar value and rotation.
259  *
260  * For example, you might have an item model with timestamped data taken at irregular intervals
261  * and you want to visualize total value of data items on each day with a bar graph.
262  * This can be done by specifying row and column categories so that each bar represents a day,
263  * and setting multiMatchBehavior to
264  * \l{QItemModelBarDataProxy::MMBCumulative}{ItemModelBarDataProxy.MMBCumulative}.
265  */
266 
267 /*!
268  *  \enum QItemModelBarDataProxy::MultiMatchBehavior
269  *
270  *  Behavior types for QItemModelBarDataProxy::multiMatchBehavior property.
271  *
272  *  \value MMBFirst
273  *         The value is taken from the first item in the item model that matches
274  *         each row/column combination.
275  *  \value MMBLast
276  *         The value is taken from the last item in the item model that matches
277  *         each row/column combination.
278  *  \value MMBAverage
279  *         The values from all items matching each row/column combination are
280  *         averaged together and the average is used as the bar value.
281  *  \value MMBCumulative
282  *         The values from all items matching each row/column combination are
283  *         added together and the total is used as the bar value.
284  */
285 
286 /*!
287  * Constructs QItemModelBarDataProxy with optional \a parent.
288  */
QItemModelBarDataProxy(QObject * parent)289 QItemModelBarDataProxy::QItemModelBarDataProxy(QObject *parent)
290     : QBarDataProxy(new QItemModelBarDataProxyPrivate(this), parent)
291 {
292     dptr()->connectItemModelHandler();
293 }
294 
295 /*!
296  * Constructs QItemModelBarDataProxy with \a itemModel and optional \a parent. Proxy doesn't take
297  * ownership of the \a itemModel, as typically item models are owned by other controls.
298  */
QItemModelBarDataProxy(QAbstractItemModel * itemModel,QObject * parent)299 QItemModelBarDataProxy::QItemModelBarDataProxy(QAbstractItemModel *itemModel, QObject *parent)
300     : QBarDataProxy(new QItemModelBarDataProxyPrivate(this), parent)
301 {
302     setItemModel(itemModel);
303     dptr()->connectItemModelHandler();
304 }
305 
306 /*!
307  * Constructs QItemModelBarDataProxy with \a itemModel and optional \a parent. Proxy doesn't take
308  * ownership of the \a itemModel, as typically item models are owned by other controls.
309  * The value role is set to \a valueRole.
310  * This constructor is meant to be used with models that have data properly sorted
311  * in rows and columns already, so it also sets useModelCategories property to true.
312  */
QItemModelBarDataProxy(QAbstractItemModel * itemModel,const QString & valueRole,QObject * parent)313 QItemModelBarDataProxy::QItemModelBarDataProxy(QAbstractItemModel *itemModel,
314                                                const QString &valueRole, QObject *parent)
315     : QBarDataProxy(new QItemModelBarDataProxyPrivate(this), parent)
316 {
317     dptr()->m_itemModelHandler->setItemModel(itemModel);
318     dptr()->m_valueRole = valueRole;
319     dptr()->m_useModelCategories = true;
320     dptr()->connectItemModelHandler();
321 }
322 
323 /*!
324  * Constructs QItemModelBarDataProxy with \a itemModel and optional \a parent. Proxy doesn't take
325  * ownership of the \a itemModel, as typically item models are owned by other controls.
326  * The role mappings are set with \a rowRole, \a columnRole, and \a valueRole.
327  */
QItemModelBarDataProxy(QAbstractItemModel * itemModel,const QString & rowRole,const QString & columnRole,const QString & valueRole,QObject * parent)328 QItemModelBarDataProxy::QItemModelBarDataProxy(QAbstractItemModel *itemModel,
329                                                const QString &rowRole,
330                                                const QString &columnRole,
331                                                const QString &valueRole, QObject *parent)
332     : QBarDataProxy(new QItemModelBarDataProxyPrivate(this), parent)
333 {
334     dptr()->m_itemModelHandler->setItemModel(itemModel);
335     dptr()->m_rowRole = rowRole;
336     dptr()->m_columnRole = columnRole;
337     dptr()->m_valueRole = valueRole;
338     dptr()->connectItemModelHandler();
339 }
340 
341 /*!
342  * Constructs QItemModelBarDataProxy with \a itemModel and optional \a parent. Proxy doesn't take
343  * ownership of the \a itemModel, as typically item models are owned by other controls.
344  * The role mappings are set with \a rowRole, \a columnRole, \a valueRole, and \a rotationRole.
345  */
QItemModelBarDataProxy(QAbstractItemModel * itemModel,const QString & rowRole,const QString & columnRole,const QString & valueRole,const QString & rotationRole,QObject * parent)346 QItemModelBarDataProxy::QItemModelBarDataProxy(QAbstractItemModel *itemModel,
347                                                const QString &rowRole,
348                                                const QString &columnRole,
349                                                const QString &valueRole,
350                                                const QString &rotationRole,
351                                                QObject *parent)
352     : QBarDataProxy(new QItemModelBarDataProxyPrivate(this), parent)
353 {
354     dptr()->m_itemModelHandler->setItemModel(itemModel);
355     dptr()->m_rowRole = rowRole;
356     dptr()->m_columnRole = columnRole;
357     dptr()->m_valueRole = valueRole;
358     dptr()->m_rotationRole = rotationRole;
359     dptr()->connectItemModelHandler();
360 }
361 
362 /*!
363  * Constructs QItemModelBarDataProxy with \a itemModel and optional \a parent. Proxy doesn't take
364  * ownership of the \a itemModel, as typically item models are owned by other controls.
365  * The role mappings are set with \a rowRole, \a columnRole, and \a valueRole.
366  * Row and column categories are set with \a rowCategories and \a columnCategories.
367  * This constructor also sets autoRowCategories and autoColumnCategories to false.
368  */
QItemModelBarDataProxy(QAbstractItemModel * itemModel,const QString & rowRole,const QString & columnRole,const QString & valueRole,const QStringList & rowCategories,const QStringList & columnCategories,QObject * parent)369 QItemModelBarDataProxy::QItemModelBarDataProxy(QAbstractItemModel *itemModel,
370                                                const QString &rowRole,
371                                                const QString &columnRole,
372                                                const QString &valueRole,
373                                                const QStringList &rowCategories,
374                                                const QStringList &columnCategories,
375                                                QObject *parent)
376     : QBarDataProxy(new QItemModelBarDataProxyPrivate(this), parent)
377 {
378     dptr()->m_itemModelHandler->setItemModel(itemModel);
379     dptr()->m_rowRole = rowRole;
380     dptr()->m_columnRole = columnRole;
381     dptr()->m_valueRole = valueRole;
382     dptr()->m_rowCategories = rowCategories;
383     dptr()->m_columnCategories = columnCategories;
384     dptr()->m_autoRowCategories = false;
385     dptr()->m_autoColumnCategories = false;
386     dptr()->connectItemModelHandler();
387 }
388 
389 /*!
390  * Constructs QItemModelBarDataProxy with \a itemModel and optional \a parent. Proxy doesn't take
391  * ownership of the \a itemModel, as typically item models are owned by other controls.
392  * The role mappings are set with \a rowRole, \a columnRole, \a valueRole, and \a rotationRole.
393  * Row and column categories are set with \a rowCategories and \a columnCategories.
394  * This constructor also sets autoRowCategories and autoColumnCategories to false.
395  */
QItemModelBarDataProxy(QAbstractItemModel * itemModel,const QString & rowRole,const QString & columnRole,const QString & valueRole,const QString & rotationRole,const QStringList & rowCategories,const QStringList & columnCategories,QObject * parent)396 QItemModelBarDataProxy::QItemModelBarDataProxy(QAbstractItemModel *itemModel,
397                                                const QString &rowRole,
398                                                const QString &columnRole,
399                                                const QString &valueRole,
400                                                const QString &rotationRole,
401                                                const QStringList &rowCategories,
402                                                const QStringList &columnCategories,
403                                                QObject *parent)
404     : QBarDataProxy(new QItemModelBarDataProxyPrivate(this), parent)
405 {
406     dptr()->m_itemModelHandler->setItemModel(itemModel);
407     dptr()->m_rowRole = rowRole;
408     dptr()->m_columnRole = columnRole;
409     dptr()->m_valueRole = valueRole;
410     dptr()->m_rotationRole = rotationRole;
411     dptr()->m_rowCategories = rowCategories;
412     dptr()->m_columnCategories = columnCategories;
413     dptr()->m_autoRowCategories = false;
414     dptr()->m_autoColumnCategories = false;
415     dptr()->connectItemModelHandler();
416 }
417 
418 /*!
419  * Destroys QItemModelBarDataProxy.
420  */
~QItemModelBarDataProxy()421 QItemModelBarDataProxy::~QItemModelBarDataProxy()
422 {
423 }
424 
425 /*!
426  * \property QItemModelBarDataProxy::itemModel
427  *
428  * \brief The item model.
429  */
430 
431 /*!
432  * Sets the item model to \a itemModel. Does not take ownership of the model,
433  * but does connect to it to listen for changes.
434  */
setItemModel(QAbstractItemModel * itemModel)435 void QItemModelBarDataProxy::setItemModel(QAbstractItemModel *itemModel)
436 {
437     dptr()->m_itemModelHandler->setItemModel(itemModel);
438 }
439 
itemModel() const440 QAbstractItemModel *QItemModelBarDataProxy::itemModel() const
441 {
442     return dptrc()->m_itemModelHandler->itemModel();
443 }
444 
445 /*!
446  * \property QItemModelBarDataProxy::rowRole
447  *
448  * \brief The row role for the mapping.
449  */
setRowRole(const QString & role)450 void QItemModelBarDataProxy::setRowRole(const QString &role)
451 {
452     if (dptr()->m_rowRole != role) {
453         dptr()->m_rowRole = role;
454         emit rowRoleChanged(role);
455     }
456 }
457 
rowRole() const458 QString QItemModelBarDataProxy::rowRole() const
459 {
460     return dptrc()->m_rowRole;
461 }
462 
463 /*!
464  * \property QItemModelBarDataProxy::columnRole
465  *
466  * \brief The column role for the mapping.
467  */
setColumnRole(const QString & role)468 void QItemModelBarDataProxy::setColumnRole(const QString &role)
469 {
470     if (dptr()->m_columnRole != role) {
471         dptr()->m_columnRole = role;
472         emit columnRoleChanged(role);
473     }
474 }
475 
columnRole() const476 QString QItemModelBarDataProxy::columnRole() const
477 {
478     return dptrc()->m_columnRole;
479 }
480 
481 /*!
482  * \property QItemModelBarDataProxy::valueRole
483  *
484  * \brief The value role for the mapping.
485  */
setValueRole(const QString & role)486 void QItemModelBarDataProxy::setValueRole(const QString &role)
487 {
488     if (dptr()->m_valueRole != role) {
489         dptr()->m_valueRole = role;
490         emit valueRoleChanged(role);
491     }
492 }
493 
valueRole() const494 QString QItemModelBarDataProxy::valueRole() const
495 {
496     return dptrc()->m_valueRole;
497 }
498 
499 /*!
500  * \property QItemModelBarDataProxy::rotationRole
501  *
502  * \brief The rotation role for the mapping.
503  */
setRotationRole(const QString & role)504 void QItemModelBarDataProxy::setRotationRole(const QString &role)
505 {
506     if (dptr()->m_rotationRole != role) {
507         dptr()->m_rotationRole = role;
508         emit rotationRoleChanged(role);
509     }
510 }
511 
rotationRole() const512 QString QItemModelBarDataProxy::rotationRole() const
513 {
514     return dptrc()->m_rotationRole;
515 }
516 
517 /*!
518  * \property QItemModelBarDataProxy::rowCategories
519  *
520  * \brief The row categories for the mapping.
521  */
setRowCategories(const QStringList & categories)522 void QItemModelBarDataProxy::setRowCategories(const QStringList &categories)
523 {
524     if (dptr()->m_rowCategories != categories) {
525         dptr()->m_rowCategories = categories;
526         emit rowCategoriesChanged();
527     }
528 }
529 
rowCategories() const530 QStringList QItemModelBarDataProxy::rowCategories() const
531 {
532     return dptrc()->m_rowCategories;
533 }
534 
535 /*!
536  * \property QItemModelBarDataProxy::columnCategories
537  *
538  * \brief The column categories for the mapping.
539  */
setColumnCategories(const QStringList & categories)540 void QItemModelBarDataProxy::setColumnCategories(const QStringList &categories)
541 {
542     if (dptr()->m_columnCategories != categories) {
543         dptr()->m_columnCategories = categories;
544         emit columnCategoriesChanged();
545     }
546 }
547 
columnCategories() const548 QStringList QItemModelBarDataProxy::columnCategories() const
549 {
550     return dptrc()->m_columnCategories;
551 }
552 
553 /*!
554  * \property QItemModelBarDataProxy::useModelCategories
555  *
556  * \brief Whether row and column roles and categories are used for mapping.
557  *
558  * When set to \c true, the mapping ignores row and column roles and categories, and uses
559  * the rows and columns from the model instead. Defaults to \c{false}.
560  */
setUseModelCategories(bool enable)561 void QItemModelBarDataProxy::setUseModelCategories(bool enable)
562 {
563     if (dptr()->m_useModelCategories != enable) {
564         dptr()->m_useModelCategories = enable;
565         emit useModelCategoriesChanged(enable);
566     }
567 }
568 
useModelCategories() const569 bool QItemModelBarDataProxy::useModelCategories() const
570 {
571     return dptrc()->m_useModelCategories;
572 }
573 
574 /*!
575  * \property QItemModelBarDataProxy::autoRowCategories
576  *
577  * \brief Whether row categories are generated automatically.
578  *
579  * When set to \c true, the mapping ignores any explicitly set row categories
580  * and overwrites them with automatically generated ones whenever the
581  * data from model is resolved. Defaults to \c{true}.
582  */
setAutoRowCategories(bool enable)583 void QItemModelBarDataProxy::setAutoRowCategories(bool enable)
584 {
585     if (dptr()->m_autoRowCategories != enable) {
586         dptr()->m_autoRowCategories = enable;
587         emit autoRowCategoriesChanged(enable);
588     }
589 }
590 
autoRowCategories() const591 bool QItemModelBarDataProxy::autoRowCategories() const
592 {
593     return dptrc()->m_autoRowCategories;
594 }
595 
596 /*!
597  * \property QItemModelBarDataProxy::autoColumnCategories
598  *
599  * \brief Whether column categories are generated automatically.
600  *
601  * When set to \c true, the mapping ignores any explicitly set column categories
602  * and overwrites them with automatically generated ones whenever the
603  * data from model is resolved. Defaults to \c{true}.
604  */
setAutoColumnCategories(bool enable)605 void QItemModelBarDataProxy::setAutoColumnCategories(bool enable)
606 {
607     if (dptr()->m_autoColumnCategories != enable) {
608         dptr()->m_autoColumnCategories = enable;
609         emit autoColumnCategoriesChanged(enable);
610     }
611 }
612 
autoColumnCategories() const613 bool QItemModelBarDataProxy::autoColumnCategories() const
614 {
615     return dptrc()->m_autoColumnCategories;
616 }
617 
618 /*!
619  * Changes \a rowRole, \a columnRole, \a valueRole, \a rotationRole,
620  * \a rowCategories and \a columnCategories to the mapping.
621  */
remap(const QString & rowRole,const QString & columnRole,const QString & valueRole,const QString & rotationRole,const QStringList & rowCategories,const QStringList & columnCategories)622 void QItemModelBarDataProxy::remap(const QString &rowRole,
623                                    const QString &columnRole,
624                                    const QString &valueRole,
625                                    const QString &rotationRole,
626                                    const QStringList &rowCategories,
627                                    const QStringList &columnCategories)
628 {
629     setRowRole(rowRole);
630     setColumnRole(columnRole);
631     setValueRole(valueRole);
632     setRotationRole(rotationRole);
633     setRowCategories(rowCategories);
634     setColumnCategories(columnCategories);
635 }
636 
637 /*!
638  * Returns the index of the specified \a category in row categories list.
639  * If the row categories list is empty, -1 is returned.
640  * \note If the automatic row categories generation is in use, this method will
641  * not return a valid index before the data in the model is resolved for the first time.
642  */
rowCategoryIndex(const QString & category)643 int QItemModelBarDataProxy::rowCategoryIndex(const QString &category)
644 {
645     return dptr()->m_rowCategories.indexOf(category);
646 }
647 
648 /*!
649  * Returns the index of the specified \a category in column categories list.
650  * If the category is not found, -1 is returned.
651  * \note If the automatic column categories generation is in use, this method will
652  * not return a valid index before the data in the model is resolved for the first time.
653  */
columnCategoryIndex(const QString & category)654 int QItemModelBarDataProxy::columnCategoryIndex(const QString &category)
655 {
656     return dptr()->m_columnCategories.indexOf(category);
657 }
658 
659 /*!
660  * \property QItemModelBarDataProxy::rowRolePattern
661  *
662  * \brief Whether a search and replace is performed on the value mapped by row
663  *  role before it is used as a row category.
664  *
665  * This property specifies the regular expression to find the portion of the
666  * mapped value to replace and rowRoleReplace property contains the replacement string.
667  * This is useful for example in parsing row and column categories from a single
668  * timestamp field in the item model.
669  *
670  * \sa rowRole, rowRoleReplace
671  */
setRowRolePattern(const QRegExp & pattern)672 void QItemModelBarDataProxy::setRowRolePattern(const QRegExp &pattern)
673 {
674     if (dptr()->m_rowRolePattern != pattern) {
675         dptr()->m_rowRolePattern = pattern;
676         emit rowRolePatternChanged(pattern);
677     }
678 }
679 
rowRolePattern() const680 QRegExp QItemModelBarDataProxy::rowRolePattern() const
681 {
682     return dptrc()->m_rowRolePattern;
683 }
684 
685 /*!
686  * \property QItemModelBarDataProxy::columnRolePattern
687  *
688  * \brief Whether a search and replace is done on the value mapped by column
689  * role before it is used as a column category.
690  *
691  * This property specifies the regular expression to find the portion of the
692  * mapped value to replace and columnRoleReplace property contains the replacement string.
693  * This is useful for example in parsing row and column categories from
694  * a single timestamp field in the item model.
695  *
696  * \sa columnRole, columnRoleReplace
697  */
setColumnRolePattern(const QRegExp & pattern)698 void QItemModelBarDataProxy::setColumnRolePattern(const QRegExp &pattern)
699 {
700     if (dptr()->m_columnRolePattern != pattern) {
701         dptr()->m_columnRolePattern = pattern;
702         emit columnRolePatternChanged(pattern);
703     }
704 }
705 
columnRolePattern() const706 QRegExp QItemModelBarDataProxy::columnRolePattern() const
707 {
708     return dptrc()->m_columnRolePattern;
709 }
710 
711 /*!
712  * \property QItemModelBarDataProxy::valueRolePattern
713  *
714  * \brief Whether a search and replace is done on the value mapped by value role
715  * before it is used as a bar value.
716  *
717  * This property specifies the regular expression to find the portion of the
718  * mapped value to replace and valueRoleReplace property contains the replacement string.
719  *
720  * \sa valueRole, valueRoleReplace
721  */
setValueRolePattern(const QRegExp & pattern)722 void QItemModelBarDataProxy::setValueRolePattern(const QRegExp &pattern)
723 {
724     if (dptr()->m_valueRolePattern != pattern) {
725         dptr()->m_valueRolePattern = pattern;
726         emit valueRolePatternChanged(pattern);
727     }
728 }
729 
valueRolePattern() const730 QRegExp QItemModelBarDataProxy::valueRolePattern() const
731 {
732     return dptrc()->m_valueRolePattern;
733 }
734 
735 /*!
736  * \property QItemModelBarDataProxy::rotationRolePattern
737  *
738  * \brief Whether a search and replace is done on the value mapped by rotation
739  * role before it is used as a bar rotation angle.
740  *
741  * This property specifies the regular expression to find the portion
742  * of the mapped value to replace and rotationRoleReplace property contains the replacement string.
743  *
744  * \sa rotationRole, rotationRoleReplace
745  */
setRotationRolePattern(const QRegExp & pattern)746 void QItemModelBarDataProxy::setRotationRolePattern(const QRegExp &pattern)
747 {
748     if (dptr()->m_rotationRolePattern != pattern) {
749         dptr()->m_rotationRolePattern = pattern;
750         emit rotationRolePatternChanged(pattern);
751     }
752 }
753 
rotationRolePattern() const754 QRegExp QItemModelBarDataProxy::rotationRolePattern() const
755 {
756     return dptrc()->m_rotationRolePattern;
757 }
758 
759 /*!
760  * \property QItemModelBarDataProxy::rowRoleReplace
761  *
762  * \brief The replace content to be used in conjunction with rowRolePattern.
763  *
764  * Defaults to empty string. For more information on how the search and replace using regular
765  * expressions works, see QString::replace(const QRegExp &rx, const QString &after)
766  * function documentation.
767  *
768  * \sa rowRole, rowRolePattern
769  */
setRowRoleReplace(const QString & replace)770 void QItemModelBarDataProxy::setRowRoleReplace(const QString &replace)
771 {
772     if (dptr()->m_rowRoleReplace != replace) {
773         dptr()->m_rowRoleReplace = replace;
774         emit rowRoleReplaceChanged(replace);
775     }
776 }
777 
rowRoleReplace() const778 QString QItemModelBarDataProxy::rowRoleReplace() const
779 {
780     return dptrc()->m_rowRoleReplace;
781 }
782 
783 /*!
784  * \property QItemModelBarDataProxy::columnRoleReplace
785  *
786  * \brief The replace content to be used in conjunction with columnRolePattern.
787  *
788  * Defaults to empty string. For more information on how the search and replace using regular
789  * expressions works, see QString::replace(const QRegExp &rx, const QString &after)
790  * function documentation.
791  *
792  * \sa columnRole, columnRolePattern
793  */
setColumnRoleReplace(const QString & replace)794 void QItemModelBarDataProxy::setColumnRoleReplace(const QString &replace)
795 {
796     if (dptr()->m_columnRoleReplace != replace) {
797         dptr()->m_columnRoleReplace = replace;
798         emit columnRoleReplaceChanged(replace);
799     }
800 }
801 
columnRoleReplace() const802 QString QItemModelBarDataProxy::columnRoleReplace() const
803 {
804     return dptrc()->m_columnRoleReplace;
805 }
806 
807 /*!
808  * \property QItemModelBarDataProxy::valueRoleReplace
809  *
810  * \brief The replace content to be used in conjunction with valueRolePattern.
811  *
812  * Defaults to empty string. For more information on how the search and replace using regular
813  * expressions works, see QString::replace(const QRegExp &rx, const QString &after)
814  * function documentation.
815  *
816  * \sa valueRole, valueRolePattern
817  */
setValueRoleReplace(const QString & replace)818 void QItemModelBarDataProxy::setValueRoleReplace(const QString &replace)
819 {
820     if (dptr()->m_valueRoleReplace != replace) {
821         dptr()->m_valueRoleReplace = replace;
822         emit valueRoleReplaceChanged(replace);
823     }
824 }
825 
valueRoleReplace() const826 QString QItemModelBarDataProxy::valueRoleReplace() const
827 {
828     return dptrc()->m_valueRoleReplace;
829 }
830 
831 /*!
832  * \property QItemModelBarDataProxy::rotationRoleReplace
833  *
834  * \brief The replace content to be used in conjunction with
835  * rotationRolePattern.
836  *
837  * Defaults to empty string. For more information on how the search and replace using regular
838  * expressions works, see QString::replace(const QRegExp &rx, const QString &after)
839  * function documentation.
840  *
841  * \sa rotationRole, rotationRolePattern
842  */
setRotationRoleReplace(const QString & replace)843 void QItemModelBarDataProxy::setRotationRoleReplace(const QString &replace)
844 {
845     if (dptr()->m_rotationRoleReplace != replace) {
846         dptr()->m_rotationRoleReplace = replace;
847         emit rotationRoleReplaceChanged(replace);
848     }
849 }
850 
rotationRoleReplace() const851 QString QItemModelBarDataProxy::rotationRoleReplace() const
852 {
853     return dptrc()->m_rotationRoleReplace;
854 }
855 
856 /*!
857  * \property QItemModelBarDataProxy::multiMatchBehavior
858  *
859  * \brief How multiple matches for each row/column combination are handled.
860  *
861  * Defaults to QItemModelBarDataProxy::MMBLast. The chosen behavior affects both bar value
862  * and rotation.
863  *
864  * For example, you might have an item model with timestamped data taken at irregular intervals
865  * and you want to visualize total value of data items on each day with a bar graph.
866  * This can be done by specifying row and column categories so that each bar represents a day,
867  * and setting multiMatchBehavior to QItemModelBarDataProxy::MMBCumulative.
868  */
setMultiMatchBehavior(QItemModelBarDataProxy::MultiMatchBehavior behavior)869 void QItemModelBarDataProxy::setMultiMatchBehavior(QItemModelBarDataProxy::MultiMatchBehavior behavior)
870 {
871     if (dptr()->m_multiMatchBehavior != behavior) {
872         dptr()->m_multiMatchBehavior = behavior;
873         emit multiMatchBehaviorChanged(behavior);
874     }
875 }
876 
multiMatchBehavior() const877 QItemModelBarDataProxy::MultiMatchBehavior QItemModelBarDataProxy::multiMatchBehavior() const
878 {
879     return dptrc()->m_multiMatchBehavior;
880 }
881 
882 /*!
883  * \internal
884  */
dptr()885 QItemModelBarDataProxyPrivate *QItemModelBarDataProxy::dptr()
886 {
887     return static_cast<QItemModelBarDataProxyPrivate *>(d_ptr.data());
888 }
889 
890 /*!
891  * \internal
892  */
dptrc() const893 const QItemModelBarDataProxyPrivate *QItemModelBarDataProxy::dptrc() const
894 {
895     return static_cast<const QItemModelBarDataProxyPrivate *>(d_ptr.data());
896 }
897 
898 // QItemModelBarDataProxyPrivate
899 
QItemModelBarDataProxyPrivate(QItemModelBarDataProxy * q)900 QItemModelBarDataProxyPrivate::QItemModelBarDataProxyPrivate(QItemModelBarDataProxy *q)
901     : QBarDataProxyPrivate(q),
902       m_itemModelHandler(new BarItemModelHandler(q)),
903       m_useModelCategories(false),
904       m_autoRowCategories(true),
905       m_autoColumnCategories(true),
906       m_multiMatchBehavior(QItemModelBarDataProxy::MMBLast)
907 {
908 }
909 
~QItemModelBarDataProxyPrivate()910 QItemModelBarDataProxyPrivate::~QItemModelBarDataProxyPrivate()
911 {
912     delete m_itemModelHandler;
913 }
914 
qptr()915 QItemModelBarDataProxy *QItemModelBarDataProxyPrivate::qptr()
916 {
917     return static_cast<QItemModelBarDataProxy *>(q_ptr);
918 }
919 
connectItemModelHandler()920 void QItemModelBarDataProxyPrivate::connectItemModelHandler()
921 {
922     QObject::connect(m_itemModelHandler, &BarItemModelHandler::itemModelChanged,
923                      qptr(), &QItemModelBarDataProxy::itemModelChanged);
924     QObject::connect(qptr(), &QItemModelBarDataProxy::rowRoleChanged,
925                      m_itemModelHandler, &AbstractItemModelHandler::handleMappingChanged);
926     QObject::connect(qptr(), &QItemModelBarDataProxy::columnRoleChanged,
927                      m_itemModelHandler, &AbstractItemModelHandler::handleMappingChanged);
928     QObject::connect(qptr(), &QItemModelBarDataProxy::valueRoleChanged,
929                      m_itemModelHandler, &AbstractItemModelHandler::handleMappingChanged);
930     QObject::connect(qptr(), &QItemModelBarDataProxy::rotationRoleChanged,
931                      m_itemModelHandler, &AbstractItemModelHandler::handleMappingChanged);
932     QObject::connect(qptr(), &QItemModelBarDataProxy::rowCategoriesChanged,
933                      m_itemModelHandler, &AbstractItemModelHandler::handleMappingChanged);
934     QObject::connect(qptr(), &QItemModelBarDataProxy::columnCategoriesChanged,
935                      m_itemModelHandler, &AbstractItemModelHandler::handleMappingChanged);
936     QObject::connect(qptr(), &QItemModelBarDataProxy::useModelCategoriesChanged,
937                      m_itemModelHandler, &AbstractItemModelHandler::handleMappingChanged);
938     QObject::connect(qptr(), &QItemModelBarDataProxy::autoRowCategoriesChanged,
939                      m_itemModelHandler, &AbstractItemModelHandler::handleMappingChanged);
940     QObject::connect(qptr(), &QItemModelBarDataProxy::autoColumnCategoriesChanged,
941                      m_itemModelHandler, &AbstractItemModelHandler::handleMappingChanged);
942     QObject::connect(qptr(), &QItemModelBarDataProxy::rowRolePatternChanged,
943                      m_itemModelHandler, &AbstractItemModelHandler::handleMappingChanged);
944     QObject::connect(qptr(), &QItemModelBarDataProxy::columnRolePatternChanged,
945                      m_itemModelHandler, &AbstractItemModelHandler::handleMappingChanged);
946     QObject::connect(qptr(), &QItemModelBarDataProxy::valueRolePatternChanged,
947                      m_itemModelHandler, &AbstractItemModelHandler::handleMappingChanged);
948     QObject::connect(qptr(), &QItemModelBarDataProxy::rotationRolePatternChanged,
949                      m_itemModelHandler, &AbstractItemModelHandler::handleMappingChanged);
950     QObject::connect(qptr(), &QItemModelBarDataProxy::rowRoleReplaceChanged,
951                      m_itemModelHandler, &AbstractItemModelHandler::handleMappingChanged);
952     QObject::connect(qptr(), &QItemModelBarDataProxy::columnRoleReplaceChanged,
953                      m_itemModelHandler, &AbstractItemModelHandler::handleMappingChanged);
954     QObject::connect(qptr(), &QItemModelBarDataProxy::valueRoleReplaceChanged,
955                      m_itemModelHandler, &AbstractItemModelHandler::handleMappingChanged);
956     QObject::connect(qptr(), &QItemModelBarDataProxy::rotationRoleReplaceChanged,
957                      m_itemModelHandler, &AbstractItemModelHandler::handleMappingChanged);
958     QObject::connect(qptr(), &QItemModelBarDataProxy::multiMatchBehaviorChanged,
959                      m_itemModelHandler, &AbstractItemModelHandler::handleMappingChanged);
960 }
961 
962 QT_END_NAMESPACE_DATAVISUALIZATION
963