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