summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMiikka Heikkinen <miikka.heikkinen@digia.com>2013-09-13 13:56:22 +0300
committerMiikka Heikkinen <miikka.heikkinen@digia.com>2013-09-16 09:48:31 +0300
commit73ffd814281d9fa07f5d25b2b3a8ce04a011780c (patch)
tree99cfff8e2cc95b0366b582bf912c0f9ff47f2382 /src
parentcff52478831a7653514fb382c27db0faba395c7c (diff)
Automatic row/col categories for bar and surface item model mappers
Task-number: QTRD-2271 Change-Id: I571e4010f3780722564f06c06bcc346d5803c646 Reviewed-by: Tomi Korpipää <tomi.korpipaa@digia.com>
Diffstat (limited to 'src')
-rw-r--r--src/datavisualization/axis/q3dvalueaxis.cpp2
-rw-r--r--src/datavisualization/data/baritemmodelhandler.cpp64
-rw-r--r--src/datavisualization/data/qitemmodelbardatamapping.cpp160
-rw-r--r--src/datavisualization/data/qitemmodelbardatamapping.h14
-rw-r--r--src/datavisualization/data/qitemmodelbardatamapping_p.h5
-rw-r--r--src/datavisualization/data/qitemmodelscatterdatamapping_p.h6
-rw-r--r--src/datavisualization/data/qitemmodelsurfacedatamapping.cpp169
-rw-r--r--src/datavisualization/data/qitemmodelsurfacedatamapping.h14
-rw-r--r--src/datavisualization/data/qitemmodelsurfacedatamapping_p.h5
-rw-r--r--src/datavisualization/data/surfaceitemmodelhandler.cpp45
-rw-r--r--src/datavisualization/doc/snippets/doc_src_qmldatavisualization.cpp2
-rw-r--r--src/datavisualization/doc/snippets/doc_src_qtdatavisualization.cpp9
-rw-r--r--src/datavisualizationqml2/declarativebars.cpp2
-rw-r--r--src/datavisualizationqml2/declarativebars_p.h3
14 files changed, 431 insertions, 69 deletions
diff --git a/src/datavisualization/axis/q3dvalueaxis.cpp b/src/datavisualization/axis/q3dvalueaxis.cpp
index fb430428..86b16fd9 100644
--- a/src/datavisualization/axis/q3dvalueaxis.cpp
+++ b/src/datavisualization/axis/q3dvalueaxis.cpp
@@ -295,7 +295,7 @@ void Q3DValueAxisPrivate::setRange(qreal min, qreal max)
m_min = min;
dirty = true;
}
- if (m_max != max) {
+ if (m_max != max || min >= max) {
if (min >= max) {
m_max = min + 1.0;
qWarning() << "Warning: Tried to set invalid range for value axis."
diff --git a/src/datavisualization/data/baritemmodelhandler.cpp b/src/datavisualization/data/baritemmodelhandler.cpp
index 07a802cd..f456604b 100644
--- a/src/datavisualization/data/baritemmodelhandler.cpp
+++ b/src/datavisualization/data/baritemmodelhandler.cpp
@@ -17,7 +17,7 @@
****************************************************************************/
#include "baritemmodelhandler_p.h"
-#include <QTimer>
+#include "qitemmodelbardatamapping_p.h"
QT_DATAVISUALIZATION_BEGIN_NAMESPACE
@@ -40,33 +40,47 @@ void BarItemModelHandler::resolveModel()
return;
}
- bool useModelRows(false);
- if (!mapping->rowCategories().size() || !mapping->columnCategories().size()) {
- useModelRows = true;
- } else if (mapping->rowRole().isEmpty() || mapping->columnRole().isEmpty()) {
+ if (!mapping->useModelCategories()
+ && (mapping->rowRole().isEmpty() || mapping->columnRole().isEmpty())) {
m_proxy->resetArray(0);
return;
}
+ QStringList rowLabels;
+ QStringList columnLabels;
+
QBarDataArray *newProxyArray = new QBarDataArray;
QHash<int, QByteArray> roleHash = m_itemModel->roleNames();
+
// Default to display role if no mapping
int valueRole = roleHash.key(mapping->valueRole().toLatin1(), Qt::DisplayRole);
int rowCount = m_itemModel->rowCount();
int columnCount = m_itemModel->columnCount();
- if (useModelRows) {
+ if (mapping->useModelCategories()) {
for (int i = 0; i < rowCount; i++) {
QBarDataRow *newProxyRow = new QBarDataRow(columnCount);
for (int j = 0; j < columnCount; j++)
(*newProxyRow)[j].setValue(m_itemModel->index(i, j).data(valueRole).toReal());
newProxyArray->append(newProxyRow);
}
+ // Generate labels from headers if using model rows/columns
+ for (int i = 0; i < rowCount; i++)
+ rowLabels << m_itemModel->headerData(i, Qt::Vertical).toString();
+ for (int i = 0; i < columnCount; i++)
+ columnLabels << m_itemModel->headerData(i, Qt::Horizontal).toString();
} else {
int rowRole = roleHash.key(mapping->rowRole().toLatin1());
int columnRole = roleHash.key(mapping->columnRole().toLatin1());
- const QStringList &rowList = mapping->rowCategories();
- const QStringList &columnList = mapping->columnCategories();
+
+ bool generateRows = mapping->autoRowCategories();
+ bool generateColumns = mapping->autoColumnCategories();
+ QStringList rowList;
+ QStringList columnList;
+ // For detecting duplicates in categories generation, using QHashes should be faster than
+ // simple QStringList::contains() check.
+ QHash<QString, bool> rowListHash;
+ QHash<QString, bool> columnListHash;
// Sort values into rows and columns
typedef QHash<QString, qreal> ColumnValueMap;
@@ -74,11 +88,30 @@ void BarItemModelHandler::resolveModel()
for (int i = 0; i < rowCount; i++) {
for (int j = 0; j < columnCount; j++) {
QModelIndex index = m_itemModel->index(i, j);
- itemValueMap[index.data(rowRole).toString()][index.data(columnRole).toString()]
- = index.data(valueRole).toReal();
+ QString rowRoleStr = index.data(rowRole).toString();
+ QString columnRoleStr = index.data(columnRole).toString();
+ itemValueMap[rowRoleStr][columnRoleStr] = index.data(valueRole).toReal();
+ if (generateRows && !rowListHash.value(rowRoleStr, false)) {
+ rowListHash.insert(rowRoleStr, true);
+ rowList << rowRoleStr;
+ }
+ if (generateColumns && !columnListHash.value(columnRoleStr, false)) {
+ columnListHash.insert(columnRoleStr, true);
+ columnList << columnRoleStr;
+ }
}
}
+ if (generateRows)
+ mapping->dptr()->m_rowCategories = rowList;
+ else
+ rowList = mapping->rowCategories();
+
+ if (generateColumns)
+ mapping->dptr()->m_columnCategories = columnList;
+ else
+ columnList = mapping->columnCategories();
+
// Create new data array from itemValueMap
foreach (QString rowKey, rowList) {
QBarDataRow *newProxyRow = new QBarDataRow(columnList.size());
@@ -86,16 +119,9 @@ void BarItemModelHandler::resolveModel()
(*newProxyRow)[i].setValue(itemValueMap[rowKey][columnList.at(i)]);
newProxyArray->append(newProxyRow);
}
- }
- // Generate labels from headers if using model rows/columns
- QStringList rowLabels;
- QStringList columnLabels;
- if (useModelRows) {
- for (int i = 0; i < rowCount; i++)
- rowLabels << m_itemModel->headerData(i, Qt::Vertical).toString();
- for (int i = 0; i < columnCount; i++)
- columnLabels << m_itemModel->headerData(i, Qt::Horizontal).toString();
+ rowLabels = rowList;
+ columnLabels = columnList;
}
m_proxy->resetArray(newProxyArray, rowLabels, columnLabels);
diff --git a/src/datavisualization/data/qitemmodelbardatamapping.cpp b/src/datavisualization/data/qitemmodelbardatamapping.cpp
index 2c47bda4..6a60ff1e 100644
--- a/src/datavisualization/data/qitemmodelbardatamapping.cpp
+++ b/src/datavisualization/data/qitemmodelbardatamapping.cpp
@@ -27,15 +27,22 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE
* \since 1.0.0
*
* QItemModelBarDataMapping is used to map roles of QAbstractItemModel to rows, columns, and values
- * of Q3DBars. There are two ways to use QItemModelBarDataMapping:
+ * of Q3DBars. There are three ways to use QItemModelBarDataMapping:
*
- * 1) By default, the QItemModelBarDataMapping will map the rows and columns of QAbstractItemModel
- * to rows and columns of Q3DBars, and uses the value returned for Qt::DisplayRole as bar value.
+ * 1) If useModelCategories property is set to true, QItemModelBarDataMapping will map rows and
+ * columns of QAbstractItemModel to rows and columns of Q3DBars, and uses the value returned for
+ * Qt::DisplayRole as bar value by default.
* The value role to be used can be redefined if Qt::DisplayRole is not suitable.
*
* 2) For models that do not have data already neatly sorted into rows and columns, such as
- * QAbstractListModel based models, you can define a list of categories for both rows and columns,
- * and define a role to map for each of row, column and value.
+ * QAbstractListModel based models, you can define a role from the model to map for each of row,
+ * column and value.
+ *
+ * 3) If you do not want to include all data contained in the model, or the autogenerated rows and
+ * columns are not ordered as you wish, you can specify which rows and columns should be included
+ * and in which order by defining an explicit list of categories for either or both of rows and
+ * columns.
+ *
* For example, assume that you have a custom QAbstractItemModel for storing various monthly values
* related to a business.
* Each item in the model has roles "year", "month", "income", and "expenses".
@@ -86,6 +93,26 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE
*/
/*!
+ * \qmlproperty list BarDataMapping::useModelCategories
+ * When set to true, the mapping ignores row and column roles and categories, and uses
+ * the rows and columns from the model instead. Defaults to false.
+ */
+
+/*!
+ * \qmlproperty list BarDataMapping::autoRowCategories
+ * When set to true, the mapping ignores any explicitly set row categories
+ * and overwrites them with automatically generated ones whenever the
+ * data from model is resolved. Defaults to true.
+ */
+
+/*!
+ * \qmlproperty list BarDataMapping::autoColumnCategories
+ * When set to true, the mapping ignores any explicitly set column categories
+ * and overwrites them with automatically generated ones whenever the
+ * data from model is resolved. Defaults to true.
+ */
+
+/*!
* Constructs QItemModelBarDataMapping with the given \a parent.
*/
QItemModelBarDataMapping::QItemModelBarDataMapping(QObject *parent)
@@ -95,16 +122,35 @@ QItemModelBarDataMapping::QItemModelBarDataMapping(QObject *parent)
/*!
* Constructs QItemModelBarDataMapping with \a valueRole and the given \a parent.
+ * This constructor is meant to be used with models that have data properly sorted
+ * in rows and columns already, so it also sets useModelCategories property to true.
*/
QItemModelBarDataMapping::QItemModelBarDataMapping(const QString &valueRole, QObject *parent)
: QAbstractDataMapping(new QItemModelBarDataMappingPrivate(this), parent)
{
dptr()->m_valueRole = valueRole;
+ dptr()->m_useModelCategories = true;
+}
+
+/*!
+ * Constructs QItemModelBarDataMapping with \a rowRole, \a columnRole, \a valueRole
+ * and the given \a parent.
+ */
+QItemModelBarDataMapping::QItemModelBarDataMapping(const QString &rowRole,
+ const QString &columnRole,
+ const QString &valueRole,
+ QObject *parent)
+ : QAbstractDataMapping(new QItemModelBarDataMappingPrivate(this), parent)
+{
+ dptr()->m_rowRole = rowRole;
+ dptr()->m_columnRole = columnRole;
+ dptr()->m_valueRole = valueRole;
}
/*!
* Constructs QItemModelBarDataMapping with \a rowRole, \a columnRole, \a valueRole,
- * \a rowCategories, \a columnCategories and the given \a parent.
+ * \a rowCategories, \a columnCategories and the given \a parent. This constructor
+ * also sets autoRowCategories and autoColumnCategories to false.
*/
QItemModelBarDataMapping::QItemModelBarDataMapping(const QString &rowRole,
const QString &columnRole,
@@ -119,6 +165,8 @@ QItemModelBarDataMapping::QItemModelBarDataMapping(const QString &rowRole,
dptr()->m_valueRole = valueRole;
dptr()->m_rowCategories = rowCategories;
dptr()->m_columnCategories = columnCategories;
+ dptr()->m_autoRowCategories = false;
+ dptr()->m_autoColumnCategories = false;
}
/*!
@@ -135,8 +183,10 @@ QItemModelBarDataMapping::~QItemModelBarDataMapping()
*/
void QItemModelBarDataMapping::setRowRole(const QString &role)
{
- dptr()->m_rowRole = role;
- emit mappingChanged();
+ if (dptr()->m_rowRole != role) {
+ dptr()->m_rowRole = role;
+ emit mappingChanged();
+ }
}
QString QItemModelBarDataMapping::rowRole() const
@@ -151,8 +201,10 @@ QString QItemModelBarDataMapping::rowRole() const
*/
void QItemModelBarDataMapping::setColumnRole(const QString &role)
{
- dptr()->m_columnRole = role;
- emit mappingChanged();
+ if (dptr()->m_columnRole != role) {
+ dptr()->m_columnRole = role;
+ emit mappingChanged();
+ }
}
QString QItemModelBarDataMapping::columnRole() const
@@ -167,8 +219,10 @@ QString QItemModelBarDataMapping::columnRole() const
*/
void QItemModelBarDataMapping::setValueRole(const QString &role)
{
- dptr()->m_valueRole = role;
- emit mappingChanged();
+ if (dptr()->m_valueRole != role) {
+ dptr()->m_valueRole = role;
+ emit mappingChanged();
+ }
}
QString QItemModelBarDataMapping::valueRole() const
@@ -183,8 +237,10 @@ QString QItemModelBarDataMapping::valueRole() const
*/
void QItemModelBarDataMapping::setRowCategories(const QStringList &categories)
{
- dptr()->m_rowCategories = categories;
- emit mappingChanged();
+ if (dptr()->m_rowCategories != categories) {
+ dptr()->m_rowCategories = categories;
+ emit mappingChanged();
+ }
}
QStringList QItemModelBarDataMapping::rowCategories() const
@@ -199,8 +255,10 @@ QStringList QItemModelBarDataMapping::rowCategories() const
*/
void QItemModelBarDataMapping::setColumnCategories(const QStringList &categories)
{
- dptr()->m_columnCategories = categories;
- emit mappingChanged();
+ if (dptr()->m_columnCategories != categories) {
+ dptr()->m_columnCategories = categories;
+ emit mappingChanged();
+ }
}
QStringList QItemModelBarDataMapping::columnCategories() const
@@ -209,6 +267,65 @@ QStringList QItemModelBarDataMapping::columnCategories() const
}
/*!
+ * \property QItemModelBarDataMapping::useModelCategories
+ *
+ * When set to true, the mapping ignores row and column roles and categories, and uses
+ * the rows and columns from the model instead. Defaults to false.
+ */
+void QItemModelBarDataMapping::setUseModelCategories(bool enable)
+{
+ if (dptr()->m_useModelCategories != enable) {
+ dptr()->m_useModelCategories = enable;
+ emit mappingChanged();
+ }
+}
+
+bool QItemModelBarDataMapping::useModelCategories() const
+{
+ return dptrc()->m_useModelCategories;
+}
+
+/*!
+ * \property QItemModelBarDataMapping::autoRowCategories
+ *
+ * When set to true, the mapping ignores any explicitly set row categories
+ * and overwrites them with automatically generated ones whenever the
+ * data from model is resolved. Defaults to true.
+ */
+void QItemModelBarDataMapping::setAutoRowCategories(bool enable)
+{
+ if (dptr()->m_autoRowCategories != enable) {
+ dptr()->m_autoRowCategories = enable;
+ emit mappingChanged();
+ }
+}
+
+bool QItemModelBarDataMapping::autoRowCategories() const
+{
+ return dptrc()->m_autoRowCategories;
+}
+
+/*!
+ * \property QItemModelBarDataMapping::autoColumnCategories
+ *
+ * When set to true, the mapping ignores any explicitly set column categories
+ * and overwrites them with automatically generated ones whenever the
+ * data from model is resolved. Defaults to true.
+ */
+void QItemModelBarDataMapping::setAutoColumnCategories(bool enable)
+{
+ if (dptr()->m_autoColumnCategories != enable) {
+ dptr()->m_autoColumnCategories = enable;
+ emit mappingChanged();
+ }
+}
+
+bool QItemModelBarDataMapping::autoColumnCategories() const
+{
+ return dptrc()->m_autoColumnCategories;
+}
+
+/*!
* Changes \a rowRole, \a columnRole, \a valueRole, \a rowCategories and \a columnCategories to the
* mapping.
*/
@@ -229,7 +346,9 @@ void QItemModelBarDataMapping::remap(const QString &rowRole,
/*!
* /return index of the specified \a category in row categories list.
- * If the category is not found, -1 is returned.
+ * If the row categories list is empty, -1 is returned.
+ * \note If the automatic row categories generation is in use, this method will
+ * not return valid index before the data in the model is resolved for the first time.
*/
int QItemModelBarDataMapping::rowCategoryIndex(const QString &category)
{
@@ -239,6 +358,8 @@ int QItemModelBarDataMapping::rowCategoryIndex(const QString &category)
/*!
* /return index of the specified \a category in column categories list.
* If the category is not found, -1 is returned.
+ * \note If the automatic column categories generation is in use, this method will
+ * not return valid index before the data in the model is resolved for the first time.
*/
int QItemModelBarDataMapping::columnCategoryIndex(const QString &category)
{
@@ -264,7 +385,10 @@ const QItemModelBarDataMappingPrivate *QItemModelBarDataMapping::dptrc() const
// QItemModelBarDataMappingPrivate
QItemModelBarDataMappingPrivate::QItemModelBarDataMappingPrivate(QItemModelBarDataMapping *q)
- : QAbstractDataMappingPrivate(q, QAbstractDataProxy::DataTypeBar)
+ : QAbstractDataMappingPrivate(q, QAbstractDataProxy::DataTypeBar),
+ m_useModelCategories(false),
+ m_autoRowCategories(true),
+ m_autoColumnCategories(true)
{
}
diff --git a/src/datavisualization/data/qitemmodelbardatamapping.h b/src/datavisualization/data/qitemmodelbardatamapping.h
index a781f020..a5ef33b8 100644
--- a/src/datavisualization/data/qitemmodelbardatamapping.h
+++ b/src/datavisualization/data/qitemmodelbardatamapping.h
@@ -35,11 +35,16 @@ class QT_DATAVISUALIZATION_EXPORT QItemModelBarDataMapping : public QAbstractDat
Q_PROPERTY(QString valueRole READ valueRole WRITE setValueRole)
Q_PROPERTY(QStringList rowCategories READ rowCategories WRITE setRowCategories)
Q_PROPERTY(QStringList columnCategories READ columnCategories WRITE setColumnCategories)
+ Q_PROPERTY(bool useModelCategories READ useModelCategories WRITE setUseModelCategories)
+ Q_PROPERTY(bool autoRowCategories READ autoRowCategories WRITE setAutoRowCategories)
+ Q_PROPERTY(bool autoColumnCategories READ autoColumnCategories WRITE setAutoColumnCategories)
public:
explicit QItemModelBarDataMapping(QObject *parent = 0);
QItemModelBarDataMapping(const QString &valueRole, QObject *parent = 0);
QItemModelBarDataMapping(const QString &rowRole, const QString &columnRole,
+ const QString &valueRole, QObject *parent = 0);
+ QItemModelBarDataMapping(const QString &rowRole, const QString &columnRole,
const QString &valueRole, const QStringList &rowCategories,
const QStringList &columnCategories, QObject *parent = 0);
virtual ~QItemModelBarDataMapping();
@@ -56,6 +61,13 @@ public:
void setColumnCategories(const QStringList &categories);
QStringList columnCategories() const;
+ void setUseModelCategories(bool enable);
+ bool useModelCategories() const;
+ void setAutoRowCategories(bool enable);
+ bool autoRowCategories() const;
+ void setAutoColumnCategories(bool enable);
+ bool autoColumnCategories() const;
+
void remap(const QString &rowRole, const QString &columnRole,
const QString &valueRole, const QStringList &rowCategories,
const QStringList &columnCategories);
@@ -69,6 +81,8 @@ protected:
private:
Q_DISABLE_COPY(QItemModelBarDataMapping)
+
+ friend class BarItemModelHandler;
};
QT_DATAVISUALIZATION_END_NAMESPACE
diff --git a/src/datavisualization/data/qitemmodelbardatamapping_p.h b/src/datavisualization/data/qitemmodelbardatamapping_p.h
index b444e384..90a17fdb 100644
--- a/src/datavisualization/data/qitemmodelbardatamapping_p.h
+++ b/src/datavisualization/data/qitemmodelbardatamapping_p.h
@@ -50,7 +50,12 @@ private:
QStringList m_rowCategories;
QStringList m_columnCategories;
+ bool m_useModelCategories;
+ bool m_autoRowCategories;
+ bool m_autoColumnCategories;
+
friend class QItemModelBarDataMapping;
+ friend class BarItemModelHandler;
};
QT_DATAVISUALIZATION_END_NAMESPACE
diff --git a/src/datavisualization/data/qitemmodelscatterdatamapping_p.h b/src/datavisualization/data/qitemmodelscatterdatamapping_p.h
index 9a8c1b6e..62ff42b4 100644
--- a/src/datavisualization/data/qitemmodelscatterdatamapping_p.h
+++ b/src/datavisualization/data/qitemmodelscatterdatamapping_p.h
@@ -26,12 +26,12 @@
//
// We mean it.
-#include "qitemmodelscatterdatamapping.h"
-#include "qabstractdatamapping_p.h"
-
#ifndef QITEMMODELSCATTERDATAMAPPING_P_H
#define QITEMMODELSCATTERDATAMAPPING_P_H
+#include "qitemmodelscatterdatamapping.h"
+#include "qabstractdatamapping_p.h"
+
QT_DATAVISUALIZATION_BEGIN_NAMESPACE
class QItemModelScatterDataMappingPrivate : public QAbstractDataMappingPrivate
diff --git a/src/datavisualization/data/qitemmodelsurfacedatamapping.cpp b/src/datavisualization/data/qitemmodelsurfacedatamapping.cpp
index 79f310ea..2fd66b30 100644
--- a/src/datavisualization/data/qitemmodelsurfacedatamapping.cpp
+++ b/src/datavisualization/data/qitemmodelsurfacedatamapping.cpp
@@ -26,7 +26,30 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE
* \brief Data model mapping for Q3DSurface.
* \since 1.0.0
*
- * DOCUMENTATION GOES HERE
+ * QItemModelSurfaceDataMapping is used to map roles of QAbstractItemModel to rows, columns, and values
+ * of Q3DSurface. There are three ways to use QItemModelSurfaceDataMapping:
+ *
+ * 1) If useModelCategories property is set to true, QItemModelSurfaceDataMapping will map rows and
+ * columns of QAbstractItemModel to rows and columns of Q3DSurface, and uses the value returned for
+ * Qt::DisplayRole as bar value by default.
+ * The value role to be used can be redefined if Qt::DisplayRole is not suitable.
+ *
+ * 2) For models that do not have data already neatly sorted into rows and columns, such as
+ * QAbstractListModel based models, you can define a role from the model to map for each of row,
+ * column and value.
+ *
+ * 3) If you do not want to include all data contained in the model, or the autogenerated rows and
+ * columns are not ordered as you wish, you can specify which rows and columns should be included
+ * and in which order by defining an explicit list of categories for either or both of rows and
+ * columns.
+ *
+ * For example, assume that you have a custom QAbstractItemModel storing surface topography data.
+ * Each item in the model has roles "longitude", "latitude" and "height". The item model already
+ * contains the data properly sorted so that longitudes and latitudes are first encountered in
+ * correct order, which enables us to utilize the row and column category autogeneration.
+ * You could do the following to display the data in a surface graph:
+ *
+ * \snippet doc_src_qtdatavisualization.cpp 5
*
* \sa QItemModelSurfaceDataProxy
*/
@@ -71,6 +94,26 @@ QT_DATAVISUALIZATION_BEGIN_NAMESPACE
*/
/*!
+ * \qmlproperty list SurfaceDataMapping::useModelCategories
+ * When set to true, the mapping ignores row and column roles and categories, and uses
+ * the rows and columns from the model instead. Defaults to false.
+ */
+
+/*!
+ * \qmlproperty list SurfaceDataMapping::autoRowCategories
+ * When set to true, the mapping ignores any explicitly set row categories
+ * and overwrites them with automatically generated ones whenever the
+ * data from model is resolved. Defaults to true.
+ */
+
+/*!
+ * \qmlproperty list SurfaceDataMapping::autoColumnCategories
+ * When set to true, the mapping ignores any explicitly set column categories
+ * and overwrites them with automatically generated ones whenever the
+ * data from model is resolved. Defaults to true.
+ */
+
+/*!
* Constructs QItemModelSurfaceDataMapping with the given \a parent.
*/
QItemModelSurfaceDataMapping::QItemModelSurfaceDataMapping(QObject *parent)
@@ -80,16 +123,35 @@ QItemModelSurfaceDataMapping::QItemModelSurfaceDataMapping(QObject *parent)
/*!
* Constructs QItemModelSurfaceDataMapping with \a valueRole and the given \a parent.
+ * This constructor is meant to be used with models that have data properly sorted
+ * in rows and columns already, so it also sets useModelCategories property to true.
*/
QItemModelSurfaceDataMapping::QItemModelSurfaceDataMapping(const QString &valueRole, QObject *parent)
: QAbstractDataMapping(new QItemModelSurfaceDataMappingPrivate(this), parent)
{
dptr()->m_valueRole = valueRole;
+ dptr()->m_useModelCategories = true;
+}
+
+/*!
+ * Constructs QItemModelSurfaceDataMapping with \a rowRole, \a columnRole, \a valueRole
+ * and the given \a parent.
+ */
+QItemModelSurfaceDataMapping::QItemModelSurfaceDataMapping(const QString &rowRole,
+ const QString &columnRole,
+ const QString &valueRole,
+ QObject *parent)
+ : QAbstractDataMapping(new QItemModelSurfaceDataMappingPrivate(this), parent)
+{
+ dptr()->m_rowRole = rowRole;
+ dptr()->m_columnRole = columnRole;
+ dptr()->m_valueRole = valueRole;
}
/*!
* Constructs QItemModelSurfaceDataMapping with \a rowRole, \a columnRole, \a valueRole,
- * \a rowCategories, \a columnCategories and the given \a parent.
+ * \a rowCategories, \a columnCategories and the given \a parent. This constructor
+ * also sets autoRowCategories and autoColumnCategories to false.
*/
QItemModelSurfaceDataMapping::QItemModelSurfaceDataMapping(const QString &rowRole,
const QString &columnRole,
@@ -104,6 +166,8 @@ QItemModelSurfaceDataMapping::QItemModelSurfaceDataMapping(const QString &rowRol
dptr()->m_valueRole = valueRole;
dptr()->m_rowCategories = rowCategories;
dptr()->m_columnCategories = columnCategories;
+ dptr()->m_autoRowCategories = false;
+ dptr()->m_autoColumnCategories = false;
}
/*!
@@ -120,8 +184,10 @@ QItemModelSurfaceDataMapping::~QItemModelSurfaceDataMapping()
*/
void QItemModelSurfaceDataMapping::setRowRole(const QString &role)
{
- dptr()->m_rowRole = role;
- emit mappingChanged();
+ if (dptr()->m_rowRole != role) {
+ dptr()->m_rowRole = role;
+ emit mappingChanged();
+ }
}
QString QItemModelSurfaceDataMapping::rowRole() const
@@ -136,8 +202,10 @@ QString QItemModelSurfaceDataMapping::rowRole() const
*/
void QItemModelSurfaceDataMapping::setColumnRole(const QString &role)
{
- dptr()->m_columnRole = role;
- emit mappingChanged();
+ if (dptr()->m_columnRole != role) {
+ dptr()->m_columnRole = role;
+ emit mappingChanged();
+ }
}
QString QItemModelSurfaceDataMapping::columnRole() const
@@ -152,8 +220,10 @@ QString QItemModelSurfaceDataMapping::columnRole() const
*/
void QItemModelSurfaceDataMapping::setValueRole(const QString &role)
{
- dptr()->m_valueRole = role;
- emit mappingChanged();
+ if (dptr()->m_valueRole != role) {
+ dptr()->m_valueRole = role;
+ emit mappingChanged();
+ }
}
QString QItemModelSurfaceDataMapping::valueRole() const
@@ -168,8 +238,10 @@ QString QItemModelSurfaceDataMapping::valueRole() const
*/
void QItemModelSurfaceDataMapping::setRowCategories(const QStringList &categories)
{
- dptr()->m_rowCategories = categories;
- emit mappingChanged();
+ if (dptr()->m_rowCategories != categories) {
+ dptr()->m_rowCategories = categories;
+ emit mappingChanged();
+ }
}
QStringList QItemModelSurfaceDataMapping::rowCategories() const
@@ -184,8 +256,10 @@ QStringList QItemModelSurfaceDataMapping::rowCategories() const
*/
void QItemModelSurfaceDataMapping::setColumnCategories(const QStringList &categories)
{
- dptr()->m_columnCategories = categories;
- emit mappingChanged();
+ if (dptr()->m_columnCategories != categories) {
+ dptr()->m_columnCategories = categories;
+ emit mappingChanged();
+ }
}
QStringList QItemModelSurfaceDataMapping::columnCategories() const
@@ -194,6 +268,65 @@ QStringList QItemModelSurfaceDataMapping::columnCategories() const
}
/*!
+ * \property QItemModelSurfaceDataMapping::useModelCategories
+ *
+ * When set to true, the mapping ignores row and column roles and categories, and uses
+ * the rows and columns from the model instead. Defaults to false.
+ */
+void QItemModelSurfaceDataMapping::setUseModelCategories(bool enable)
+{
+ if (dptr()->m_useModelCategories != enable) {
+ dptr()->m_useModelCategories = enable;
+ emit mappingChanged();
+ }
+}
+
+bool QItemModelSurfaceDataMapping::useModelCategories() const
+{
+ return dptrc()->m_useModelCategories;
+}
+
+/*!
+ * \property QItemModelSurfaceDataMapping::autoRowCategories
+ *
+ * When set to true, the mapping ignores any explicitly set row categories
+ * and overwrites them with automatically generated ones whenever the
+ * data from model is resolved. Defaults to true.
+ */
+void QItemModelSurfaceDataMapping::setAutoRowCategories(bool enable)
+{
+ if (dptr()->m_autoRowCategories != enable) {
+ dptr()->m_autoRowCategories = enable;
+ emit mappingChanged();
+ }
+}
+
+bool QItemModelSurfaceDataMapping::autoRowCategories() const
+{
+ return dptrc()->m_autoRowCategories;
+}
+
+/*!
+ * \property QItemModelSurfaceDataMapping::autoColumnCategories
+ *
+ * When set to true, the mapping ignores any explicitly set column categories
+ * and overwrites them with automatically generated ones whenever the
+ * data from model is resolved. Defaults to true.
+ */
+void QItemModelSurfaceDataMapping::setAutoColumnCategories(bool enable)
+{
+ if (dptr()->m_autoColumnCategories != enable) {
+ dptr()->m_autoColumnCategories = enable;
+ emit mappingChanged();
+ }
+}
+
+bool QItemModelSurfaceDataMapping::autoColumnCategories() const
+{
+ return dptrc()->m_autoColumnCategories;
+}
+
+/*!
* Changes \a rowRole, \a columnRole, \a valueRole, \a rowCategories and \a columnCategories to the
* mapping.
*/
@@ -214,7 +347,9 @@ void QItemModelSurfaceDataMapping::remap(const QString &rowRole,
/*!
* /return index of the specified \a category in row categories list.
- * If the category is not found, -1 is returned.
+ * If the row categories list is empty, -1 is returned.
+ * \note If the automatic row categories generation is in use, this method will
+ * not return valid index before the data in the model is resolved for the first time.
*/
int QItemModelSurfaceDataMapping::rowCategoryIndex(const QString &category)
{
@@ -223,7 +358,8 @@ int QItemModelSurfaceDataMapping::rowCategoryIndex(const QString &category)
/*!
* /return index of the specified \a category in column categories list.
- * If the category is not found, -1 is returned.
+ * \note If the automatic column categories generation is in use, this method will
+ * not return valid index before the data in the model is resolved for the first time.
*/
int QItemModelSurfaceDataMapping::columnCategoryIndex(const QString &category)
{
@@ -249,7 +385,10 @@ const QItemModelSurfaceDataMappingPrivate *QItemModelSurfaceDataMapping::dptrc()
// QItemModelSurfaceDataMappingPrivate
QItemModelSurfaceDataMappingPrivate::QItemModelSurfaceDataMappingPrivate(QItemModelSurfaceDataMapping *q)
- : QAbstractDataMappingPrivate(q, QAbstractDataProxy::DataTypeSurface)
+ : QAbstractDataMappingPrivate(q, QAbstractDataProxy::DataTypeSurface),
+ m_useModelCategories(false),
+ m_autoRowCategories(true),
+ m_autoColumnCategories(true)
{
}
diff --git a/src/datavisualization/data/qitemmodelsurfacedatamapping.h b/src/datavisualization/data/qitemmodelsurfacedatamapping.h
index 1d937806..7e8817bf 100644
--- a/src/datavisualization/data/qitemmodelsurfacedatamapping.h
+++ b/src/datavisualization/data/qitemmodelsurfacedatamapping.h
@@ -35,11 +35,16 @@ class QT_DATAVISUALIZATION_EXPORT QItemModelSurfaceDataMapping : public QAbstrac
Q_PROPERTY(QString valueRole READ valueRole WRITE setValueRole)
Q_PROPERTY(QStringList rowCategories READ rowCategories WRITE setRowCategories)
Q_PROPERTY(QStringList columnCategories READ columnCategories WRITE setColumnCategories)
+ Q_PROPERTY(bool useModelCategories READ useModelCategories WRITE setUseModelCategories)
+ Q_PROPERTY(bool autoRowCategories READ autoRowCategories WRITE setAutoRowCategories)
+ Q_PROPERTY(bool autoColumnCategories READ autoColumnCategories WRITE setAutoColumnCategories)
public:
explicit QItemModelSurfaceDataMapping(QObject *parent = 0);
QItemModelSurfaceDataMapping(const QString &valueRole, QObject *parent = 0);
QItemModelSurfaceDataMapping(const QString &rowRole, const QString &columnRole,
+ const QString &valueRole, QObject *parent = 0);
+ QItemModelSurfaceDataMapping(const QString &rowRole, const QString &columnRole,
const QString &valueRole, const QStringList &rowCategories,
const QStringList &columnCategories, QObject *parent = 0);
virtual ~QItemModelSurfaceDataMapping();
@@ -56,6 +61,13 @@ public:
void setColumnCategories(const QStringList &categories);
QStringList columnCategories() const;
+ void setUseModelCategories(bool enable);
+ bool useModelCategories() const;
+ void setAutoRowCategories(bool enable);
+ bool autoRowCategories() const;
+ void setAutoColumnCategories(bool enable);
+ bool autoColumnCategories() const;
+
void remap(const QString &rowRole, const QString &columnRole,
const QString &valueRole, const QStringList &rowCategories,
const QStringList &columnCategories);
@@ -69,6 +81,8 @@ protected:
private:
Q_DISABLE_COPY(QItemModelSurfaceDataMapping)
+
+ friend class SurfaceItemModelHandler;
};
QT_DATAVISUALIZATION_END_NAMESPACE
diff --git a/src/datavisualization/data/qitemmodelsurfacedatamapping_p.h b/src/datavisualization/data/qitemmodelsurfacedatamapping_p.h
index 69470423..9896f868 100644
--- a/src/datavisualization/data/qitemmodelsurfacedatamapping_p.h
+++ b/src/datavisualization/data/qitemmodelsurfacedatamapping_p.h
@@ -50,7 +50,12 @@ private:
QStringList m_rowCategories;
QStringList m_columnCategories;
+ bool m_useModelCategories;
+ bool m_autoRowCategories;
+ bool m_autoColumnCategories;
+
friend class QItemModelSurfaceDataMapping;
+ friend class SurfaceItemModelHandler;
};
QT_DATAVISUALIZATION_END_NAMESPACE
diff --git a/src/datavisualization/data/surfaceitemmodelhandler.cpp b/src/datavisualization/data/surfaceitemmodelhandler.cpp
index 911e2995..124fe640 100644
--- a/src/datavisualization/data/surfaceitemmodelhandler.cpp
+++ b/src/datavisualization/data/surfaceitemmodelhandler.cpp
@@ -17,7 +17,7 @@
****************************************************************************/
#include "surfaceitemmodelhandler_p.h"
-#include <QTimer>
+#include "qitemmodelsurfacedatamapping_p.h"
QT_DATAVISUALIZATION_BEGIN_NAMESPACE
@@ -40,22 +40,21 @@ void SurfaceItemModelHandler::resolveModel()
return;
}
- bool useModelRows(false);
- if (!mapping->rowCategories().size() || !mapping->columnCategories().size()) {
- useModelRows = true;
- } else if (mapping->rowRole().isEmpty() || mapping->columnRole().isEmpty()) {
+ if (!mapping->useModelCategories()
+ && (mapping->rowRole().isEmpty() || mapping->columnRole().isEmpty())) {
m_proxy->resetArray(0);
return;
}
QSurfaceDataArray *newProxyArray = new QSurfaceDataArray;
QHash<int, QByteArray> roleHash = m_itemModel->roleNames();
+
// Default to display role if no mapping
int valueRole = roleHash.key(mapping->valueRole().toLatin1(), Qt::DisplayRole);
int rowCount = m_itemModel->rowCount();
int columnCount = m_itemModel->columnCount();
- if (useModelRows) {
+ if (mapping->useModelCategories()) {
for (int i = 0; i < rowCount; i++) {
QSurfaceDataRow *newProxyRow = new QSurfaceDataRow(columnCount);
for (int j = 0; j < columnCount; j++)
@@ -65,8 +64,15 @@ void SurfaceItemModelHandler::resolveModel()
} else {
int rowRole = roleHash.key(mapping->rowRole().toLatin1());
int columnRole = roleHash.key(mapping->columnRole().toLatin1());
- const QStringList &rowList = mapping->rowCategories();
- const QStringList &columnList = mapping->columnCategories();
+
+ bool generateRows = mapping->autoRowCategories();
+ bool generateColumns = mapping->autoColumnCategories();
+ QStringList rowList;
+ QStringList columnList;
+ // For detecting duplicates in categories generation, using QHashes should be faster than
+ // simple QStringList::contains() check.
+ QHash<QString, bool> rowListHash;
+ QHash<QString, bool> columnListHash;
// Sort values into rows and columns
typedef QHash<QString, qreal> ColumnValueMap;
@@ -74,11 +80,30 @@ void SurfaceItemModelHandler::resolveModel()
for (int i = 0; i < rowCount; i++) {
for (int j = 0; j < columnCount; j++) {
QModelIndex index = m_itemModel->index(i, j);
- itemValueMap[index.data(rowRole).toString()][index.data(columnRole).toString()]
- = index.data(valueRole).toReal();
+ QString rowRoleStr = index.data(rowRole).toString();
+ QString columnRoleStr = index.data(columnRole).toString();
+ itemValueMap[rowRoleStr][columnRoleStr] = index.data(valueRole).toReal();
+ if (generateRows && !rowListHash.value(rowRoleStr, false)) {
+ rowListHash.insert(rowRoleStr, true);
+ rowList << rowRoleStr;
+ }
+ if (generateColumns && !columnListHash.value(columnRoleStr, false)) {
+ columnListHash.insert(columnRoleStr, true);
+ columnList << columnRoleStr;
+ }
}
}
+ if (generateRows)
+ mapping->dptr()->m_rowCategories = rowList;
+ else
+ rowList = mapping->rowCategories();
+
+ if (generateColumns)
+ mapping->dptr()->m_columnCategories = columnList;
+ else
+ columnList = mapping->columnCategories();
+
// Create new data array from itemValueMap
foreach (QString rowKey, rowList) {
QSurfaceDataRow *newProxyRow = new QSurfaceDataRow(columnList.size());
diff --git a/src/datavisualization/doc/snippets/doc_src_qmldatavisualization.cpp b/src/datavisualization/doc/snippets/doc_src_qmldatavisualization.cpp
index 12496168..f4446e17 100644
--- a/src/datavisualization/doc/snippets/doc_src_qmldatavisualization.cpp
+++ b/src/datavisualization/doc/snippets/doc_src_qmldatavisualization.cpp
@@ -93,8 +93,6 @@ SurfaceDataMapping {
rowRole: "latitude"
columnRole: "longitude"
valueRole: "population"
- rowCategories: ["64.5", "64.6", "64.7", "64.8", "64.9", "65.0", "65.1", "65.2", "65.3", "65.4"]
- columnCategories: ["24.5", "24.75", "25.0", "25.25", "25.5", "25.75", "26.0", "26.25", "26.5", "26.75"]
}
//! [6]
diff --git a/src/datavisualization/doc/snippets/doc_src_qtdatavisualization.cpp b/src/datavisualization/doc/snippets/doc_src_qtdatavisualization.cpp
index f4df32d5..54f64ef0 100644
--- a/src/datavisualization/doc/snippets/doc_src_qtdatavisualization.cpp
+++ b/src/datavisualization/doc/snippets/doc_src_qtdatavisualization.cpp
@@ -65,5 +65,14 @@ proxy->activeMapping()->setValueRole(QStringLiteral("expenses"));
QItemModelScatterDataMapping *mapping = new QItemModelScatterDataMapping(QStringLiteral("density"),
QStringLiteral("hardness"),
QStringLiteral("conductivity"))
+
QItemModelScatterDataProxy *proxy = new QItemModelScatterDataProxy(customModel, mapping);
//! [4]
+
+//! [5]
+QItemModelSurfaceDataMapping *mapping = new QItemModelSurfaceDataMapping(QStringLiteral("longitude"), // Row role
+ QStringLiteral("latitude"), // Column role
+ QStringLiteral("height")); // value role
+
+QItemModelSurfaceDataProxy *proxy = new QItemModelSurfaceDataProxy(customModel, mapping);
+//! [5]
diff --git a/src/datavisualizationqml2/declarativebars.cpp b/src/datavisualizationqml2/declarativebars.cpp
index 7eee3e6d..010409e8 100644
--- a/src/datavisualizationqml2/declarativebars.cpp
+++ b/src/datavisualizationqml2/declarativebars.cpp
@@ -42,6 +42,8 @@ DeclarativeBars::DeclarativeBars(QQuickItem *parent)
m_shared = new Bars3DController(boundingRect().toRect());
QObject::connect(m_shared, &Abstract3DController::shadowQualityChanged, this,
&DeclarativeBars::handleShadowQualityUpdate);
+ QObject::connect(m_shared, &Bars3DController::selectedBarPosChanged, this,
+ &DeclarativeBars::selectedBarPosChanged);
QItemModelBarDataProxy *proxy = new QItemModelBarDataProxy;
m_shared->setActiveDataProxy(proxy);
diff --git a/src/datavisualizationqml2/declarativebars_p.h b/src/datavisualizationqml2/declarativebars_p.h
index a85bc2da..ebf565fe 100644
--- a/src/datavisualizationqml2/declarativebars_p.h
+++ b/src/datavisualizationqml2/declarativebars_p.h
@@ -67,7 +67,7 @@ class DeclarativeBars : public QQuickItem
Q_PROPERTY(int rows READ rows WRITE setRows)
Q_PROPERTY(int columns READ columns WRITE setColumns)
Q_PROPERTY(QString itemLabelFormat READ itemLabelFormat WRITE setItemLabelFormat)
- Q_PROPERTY(QPointF selectedBarPos READ selectedBarPos WRITE setSelectedBarPos)
+ Q_PROPERTY(QPointF selectedBarPos READ selectedBarPos WRITE setSelectedBarPos NOTIFY selectedBarPosChanged)
Q_ENUMS(QtDataVisualization::QDataVis::SelectionMode)
Q_ENUMS(QtDataVisualization::QDataVis::ShadowQuality)
Q_ENUMS(QtDataVisualization::QDataVis::LabelTransparency)
@@ -174,6 +174,7 @@ public:
signals:
// Signals shadow quality changes.
void shadowQualityChanged(QDataVis::ShadowQuality quality);
+ void selectedBarPosChanged(const QPointF &position);
protected:
Bars3DController *m_shared;