summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiikka Heikkinen <miikka.heikkinen@digia.com>2014-01-29 12:51:55 +0200
committerMiikka Heikkinen <miikka.heikkinen@digia.com>2014-01-29 13:07:16 +0200
commit201a480af6ad2d36896570683ab87014827b9697 (patch)
tree3c12f6cf9c5a13a758e0e056515a05c96164b8d0
parente616a4737c932546ab5eadee8f4f766d35d260d7 (diff)
Rotation support for item models
Task-number: QTRD-2654 Change-Id: Ie919c3032731724f750fc0ccb237379454009585 Reviewed-by: Tomi Korpipää <tomi.korpipaa@digia.com>
-rw-r--r--src/datavisualization/data/baritemmodelhandler.cpp18
-rw-r--r--src/datavisualization/data/qbar3dseries.cpp58
-rw-r--r--src/datavisualization/data/qbar3dseries.h5
-rw-r--r--src/datavisualization/data/qbar3dseries_p.h4
-rw-r--r--src/datavisualization/data/qitemmodelbardataproxy.cpp74
-rw-r--r--src/datavisualization/data/qitemmodelbardataproxy.h11
-rw-r--r--src/datavisualization/data/qitemmodelbardataproxy_p.h1
-rw-r--r--src/datavisualization/data/qitemmodelscatterdataproxy.cpp46
-rw-r--r--src/datavisualization/data/qitemmodelscatterdataproxy.h8
-rw-r--r--src/datavisualization/data/qitemmodelscatterdataproxy_p.h1
-rw-r--r--src/datavisualization/data/scatteritemmodelhandler.cpp27
-rw-r--r--src/datavisualization/data/scatteritemmodelhandler_p.h1
-rw-r--r--tests/qmlcamera/qml/qmlcamera/Data.qml147
-rw-r--r--tests/qmlcamera/qml/qmlcamera/main.qml16
-rw-r--r--tests/qmldynamicdata/qml/qmldynamicdata/main.qml5
15 files changed, 335 insertions, 87 deletions
diff --git a/src/datavisualization/data/baritemmodelhandler.cpp b/src/datavisualization/data/baritemmodelhandler.cpp
index 611fbcb9..4f44fe1d 100644
--- a/src/datavisualization/data/baritemmodelhandler.cpp
+++ b/src/datavisualization/data/baritemmodelhandler.cpp
@@ -20,6 +20,8 @@
QT_BEGIN_NAMESPACE_DATAVISUALIZATION
+static const int noRoleIndex = -1;
+
BarItemModelHandler::BarItemModelHandler(QItemModelBarDataProxy *proxy, QObject *parent)
: AbstractItemModelHandler(parent),
m_proxy(proxy),
@@ -51,8 +53,9 @@ void BarItemModelHandler::resolveModel()
QHash<int, QByteArray> roleHash = m_itemModel->roleNames();
- // Default to display role if no mapping
+ // Default value role to display role if no mapping
int valueRole = roleHash.key(m_proxy->valueRole().toLatin1(), Qt::DisplayRole);
+ int rotationRole = roleHash.key(m_proxy->rotationRole().toLatin1(), noRoleIndex);
int rowCount = m_itemModel->rowCount();
int columnCount = m_itemModel->columnCount();
@@ -67,8 +70,11 @@ void BarItemModelHandler::resolveModel()
}
for (int i = 0; i < rowCount; i++) {
QBarDataRow &newProxyRow = *m_proxyArray->at(i);
- for (int j = 0; j < columnCount; j++)
+ for (int j = 0; j < columnCount; j++) {
newProxyRow[j].setValue(m_itemModel->index(i, j).data(valueRole).toReal());
+ if (rotationRole != noRoleIndex)
+ newProxyRow[j].setRotation(m_itemModel->index(i, j).data(rotationRole).toReal());
+ }
}
// Generate labels from headers if using model rows/columns
for (int i = 0; i < rowCount; i++)
@@ -92,12 +98,15 @@ void BarItemModelHandler::resolveModel()
// Sort values into rows and columns
typedef QHash<QString, float> ColumnValueMap;
QHash <QString, ColumnValueMap> itemValueMap;
+ QHash <QString, ColumnValueMap> itemRotationMap;
for (int i = 0; i < rowCount; i++) {
for (int j = 0; j < columnCount; j++) {
QModelIndex index = m_itemModel->index(i, j);
QString rowRoleStr = index.data(rowRole).toString();
QString columnRoleStr = index.data(columnRole).toString();
itemValueMap[rowRoleStr][columnRoleStr] = index.data(valueRole).toReal();
+ if (rotationRole != noRoleIndex)
+ itemRotationMap[rowRoleStr][columnRoleStr] = index.data(rotationRole).toReal();
if (generateRows && !rowListHash.value(rowRoleStr, false)) {
rowListHash.insert(rowRoleStr, true);
rowList << rowRoleStr;
@@ -131,8 +140,11 @@ void BarItemModelHandler::resolveModel()
for (int i = 0; i < rowList.size(); i++) {
QString rowKey = rowList.at(i);
QBarDataRow &newProxyRow = *m_proxyArray->at(i);
- for (int j = 0; j < columnList.size(); j++)
+ for (int j = 0; j < columnList.size(); j++) {
newProxyRow[j].setValue(itemValueMap[rowKey][columnList.at(j)]);
+ if (rotationRole != noRoleIndex)
+ newProxyRow[j].setRotation(itemRotationMap[rowKey][columnList.at(j)]);
+ }
}
rowLabels = rowList;
diff --git a/src/datavisualization/data/qbar3dseries.cpp b/src/datavisualization/data/qbar3dseries.cpp
index 1440476b..25ff505f 100644
--- a/src/datavisualization/data/qbar3dseries.cpp
+++ b/src/datavisualization/data/qbar3dseries.cpp
@@ -18,6 +18,7 @@
#include "qbar3dseries_p.h"
#include "bars3dcontroller_p.h"
+#include <QtCore/qmath.h>
QT_BEGIN_NAMESPACE_DATAVISUALIZATION
@@ -114,6 +115,17 @@ QT_BEGIN_NAMESPACE_DATAVISUALIZATION
*/
/*!
+ * \qmlproperty real Bar3DSeries::meshAngle
+ *
+ * A convenience property for defining the series rotation \a angle in degrees.
+ *
+ * \note: When reading this property, it is calculated from Abstract3DSeries::meshRotation value and
+ * always returns a value from zero to 360 degrees. It may also have small rounding errors.
+ *
+ * \sa Abstract3DSeries::meshRotation
+ */
+
+/*!
* Constructs QBar3DSeries with the given \a parent.
*/
QBar3DSeries::QBar3DSeries(QObject *parent) :
@@ -121,6 +133,7 @@ QBar3DSeries::QBar3DSeries(QObject *parent) :
{
// Default proxy
dptr()->setDataProxy(new QBarDataProxy);
+ dptr()->connectSignals();
}
/*!
@@ -130,6 +143,7 @@ QBar3DSeries::QBar3DSeries(QBarDataProxy *dataProxy, QObject *parent) :
QAbstract3DSeries(new QBar3DSeriesPrivate(this), parent)
{
dptr()->setDataProxy(dataProxy);
+ dptr()->connectSignals();
}
/*!
@@ -138,6 +152,7 @@ QBar3DSeries::QBar3DSeries(QBarDataProxy *dataProxy, QObject *parent) :
QBar3DSeries::QBar3DSeries(QBar3DSeriesPrivate *d, QObject *parent) :
QAbstract3DSeries(d, parent)
{
+ dptr()->connectSignals();
}
/*!
@@ -204,6 +219,38 @@ QPoint QBar3DSeries::invalidSelectionPosition()
return Bars3DController::invalidSelectionPosition();
}
+static inline float quaternionAngle(const QQuaternion &rotation)
+{
+ return qAcos(rotation.scalar()) * 360.0f / M_PI;
+}
+
+/*!
+ * \property QBar3DSeries::meshAngle
+ *
+ * A convenience property for defining the series rotation \a angle in degrees.
+ * Setting this property is equivalent to the following call:
+ * \code setMeshRotation(QQuaternion::fromAxisAndAngle(0.0f, 1.0f, 0.0f, angle)) \endcode
+ *
+ * \note: When reading this property, it is calculated from QAbstract3DSeries::meshRotation value
+ * and always returns a value from zero to 360 degrees. It may also have small rounding errors.
+ *
+ * \sa QAbstract3DSeries::meshRotation
+ */
+void QBar3DSeries::setMeshAngle(float angle)
+{
+ setMeshRotation(QQuaternion::fromAxisAndAngle(upVector, angle));
+}
+
+float QBar3DSeries::meshAngle() const
+{
+ QQuaternion rotation = meshRotation();
+
+ if (rotation.isIdentity() || rotation.x() != 0.0f || rotation.z() != 0.0f)
+ return 0.0f;
+ else
+ return quaternionAngle(rotation);
+}
+
/*!
* \internal
*/
@@ -279,6 +326,11 @@ void QBar3DSeriesPrivate::connectControllerAndProxy(Abstract3DController *newCon
}
}
+void QBar3DSeriesPrivate::handleMeshRotationChanged(const QQuaternion &rotation)
+{
+ emit qptr()->meshAngleChanged(quaternionAngle(rotation));
+}
+
void QBar3DSeriesPrivate::setSelectedBar(const QPoint &position)
{
if (position != m_selectedBar) {
@@ -287,4 +339,10 @@ void QBar3DSeriesPrivate::setSelectedBar(const QPoint &position)
}
}
+void QBar3DSeriesPrivate::connectSignals()
+{
+ QObject::connect(q_ptr, &QAbstract3DSeries::meshRotationChanged, this,
+ &QBar3DSeriesPrivate::handleMeshRotationChanged);
+}
+
QT_END_NAMESPACE_DATAVISUALIZATION
diff --git a/src/datavisualization/data/qbar3dseries.h b/src/datavisualization/data/qbar3dseries.h
index be748516..aa67dadb 100644
--- a/src/datavisualization/data/qbar3dseries.h
+++ b/src/datavisualization/data/qbar3dseries.h
@@ -32,6 +32,7 @@ class QT_DATAVISUALIZATION_EXPORT QBar3DSeries : public QAbstract3DSeries
Q_OBJECT
Q_PROPERTY(QBarDataProxy *dataProxy READ dataProxy WRITE setDataProxy NOTIFY dataProxyChanged)
Q_PROPERTY(QPoint selectedBar READ selectedBar WRITE setSelectedBar NOTIFY selectedBarChanged)
+ Q_PROPERTY(float meshAngle READ meshAngle WRITE setMeshAngle NOTIFY meshAngleChanged)
public:
explicit QBar3DSeries(QObject *parent = 0);
@@ -45,9 +46,13 @@ public:
QPoint selectedBar() const;
static QPoint invalidSelectionPosition();
+ void setMeshAngle(float angle);
+ float meshAngle() const;
+
signals:
void dataProxyChanged(QBarDataProxy *proxy);
void selectedBarChanged(QPoint position);
+ void meshAngleChanged(float angle);
protected:
explicit QBar3DSeries(QBar3DSeriesPrivate *d, QObject *parent = 0);
diff --git a/src/datavisualization/data/qbar3dseries_p.h b/src/datavisualization/data/qbar3dseries_p.h
index 173f1cd9..718f1237 100644
--- a/src/datavisualization/data/qbar3dseries_p.h
+++ b/src/datavisualization/data/qbar3dseries_p.h
@@ -44,8 +44,12 @@ public:
virtual void setDataProxy(QAbstractDataProxy *proxy);
virtual void connectControllerAndProxy(Abstract3DController *newController);
+ void handleMeshRotationChanged(const QQuaternion &rotation);
+
void setSelectedBar(const QPoint &position);
+ void connectSignals();
+
private:
QBar3DSeries *qptr();
diff --git a/src/datavisualization/data/qitemmodelbardataproxy.cpp b/src/datavisualization/data/qitemmodelbardataproxy.cpp
index 97289da1..6a1e9c15 100644
--- a/src/datavisualization/data/qitemmodelbardataproxy.cpp
+++ b/src/datavisualization/data/qitemmodelbardataproxy.cpp
@@ -105,6 +105,12 @@ QT_BEGIN_NAMESPACE_DATAVISUALIZATION
*/
/*!
+ * \qmlproperty string ItemModelBarDataProxy::rotationRole
+ *
+ * Defines the rotation role for the mapping.
+ */
+
+/*!
* \qmlproperty list ItemModelBarDataProxy::rowCategories
* The row categories of the mapping. Only items with row roles that are found in this list are
* included when the data is resolved. The rows are ordered in the same order as they are in this list.
@@ -195,6 +201,27 @@ QItemModelBarDataProxy::QItemModelBarDataProxy(const QAbstractItemModel *itemMod
/*!
* Constructs QItemModelBarDataProxy with \a itemModel and optional \a parent. Proxy doesn't take
* ownership of the \a itemModel, as typically item models are owned by other controls.
+ * The role mappings are set with \a rowRole, \a columnRole, \a valueRole, and \a rotationRole.
+ */
+QItemModelBarDataProxy::QItemModelBarDataProxy(const QAbstractItemModel *itemModel,
+ const QString &rowRole,
+ const QString &columnRole,
+ const QString &valueRole,
+ const QString &rotationRole,
+ QObject *parent)
+ : QBarDataProxy(new QItemModelBarDataProxyPrivate(this), parent)
+{
+ dptr()->m_itemModelHandler->setItemModel(itemModel);
+ dptr()->m_rowRole = rowRole;
+ dptr()->m_columnRole = columnRole;
+ dptr()->m_valueRole = valueRole;
+ dptr()->m_rotationRole = rotationRole;
+ dptr()->connectItemModelHandler();
+}
+
+/*!
+ * Constructs QItemModelBarDataProxy with \a itemModel and optional \a parent. Proxy doesn't take
+ * ownership of the \a itemModel, as typically item models are owned by other controls.
* The role mappings are set with \a rowRole, \a columnRole, and \a valueRole.
* Row and column categories are set with \a rowCategories and \a columnCategories.
* This constructor also sets autoRowCategories and autoColumnCategories to false.
@@ -220,6 +247,35 @@ QItemModelBarDataProxy::QItemModelBarDataProxy(const QAbstractItemModel *itemMod
}
/*!
+ * Constructs QItemModelBarDataProxy with \a itemModel and optional \a parent. Proxy doesn't take
+ * ownership of the \a itemModel, as typically item models are owned by other controls.
+ * The role mappings are set with \a rowRole, \a columnRole, \a valueRole, and \a rotationRole.
+ * Row and column categories are set with \a rowCategories and \a columnCategories.
+ * This constructor also sets autoRowCategories and autoColumnCategories to false.
+ */
+QItemModelBarDataProxy::QItemModelBarDataProxy(const QAbstractItemModel *itemModel,
+ const QString &rowRole,
+ const QString &columnRole,
+ const QString &valueRole,
+ const QString &rotationRole,
+ const QStringList &rowCategories,
+ const QStringList &columnCategories,
+ QObject *parent)
+ : QBarDataProxy(new QItemModelBarDataProxyPrivate(this), parent)
+{
+ dptr()->m_itemModelHandler->setItemModel(itemModel);
+ dptr()->m_rowRole = rowRole;
+ dptr()->m_columnRole = columnRole;
+ dptr()->m_valueRole = valueRole;
+ dptr()->m_rotationRole = rotationRole;
+ dptr()->m_rowCategories = rowCategories;
+ dptr()->m_columnCategories = columnCategories;
+ dptr()->m_autoRowCategories = false;
+ dptr()->m_autoColumnCategories = false;
+ dptr()->connectItemModelHandler();
+}
+
+/*!
* Destroys QItemModelBarDataProxy.
*/
QItemModelBarDataProxy::~QItemModelBarDataProxy()
@@ -297,6 +353,24 @@ QString QItemModelBarDataProxy::valueRole() const
}
/*!
+ * \property QItemModelBarDataProxy::rotationRole
+ *
+ * Defines the rotation role for the mapping.
+ */
+void QItemModelBarDataProxy::setRotationRole(const QString &role)
+{
+ if (dptr()->m_rotationRole != role) {
+ dptr()->m_rotationRole = role;
+ emit rotationRoleChanged(role);
+ }
+}
+
+QString QItemModelBarDataProxy::rotationRole() const
+{
+ return dptrc()->m_rotationRole;
+}
+
+/*!
* \property QItemModelBarDataProxy::rowCategories
*
* Defines the row categories for the mapping.
diff --git a/src/datavisualization/data/qitemmodelbardataproxy.h b/src/datavisualization/data/qitemmodelbardataproxy.h
index 4e62b4c3..f6b0b64f 100644
--- a/src/datavisualization/data/qitemmodelbardataproxy.h
+++ b/src/datavisualization/data/qitemmodelbardataproxy.h
@@ -34,6 +34,7 @@ class QT_DATAVISUALIZATION_EXPORT QItemModelBarDataProxy : public QBarDataProxy
Q_PROPERTY(QString rowRole READ rowRole WRITE setRowRole NOTIFY rowRoleChanged)
Q_PROPERTY(QString columnRole READ columnRole WRITE setColumnRole NOTIFY columnRoleChanged)
Q_PROPERTY(QString valueRole READ valueRole WRITE setValueRole NOTIFY valueRoleChanged)
+ Q_PROPERTY(QString rotationRole READ rotationRole WRITE setRotationRole NOTIFY rotationRoleChanged)
Q_PROPERTY(QStringList rowCategories READ rowCategories WRITE setRowCategories NOTIFY rowCategoriesChanged)
Q_PROPERTY(QStringList columnCategories READ columnCategories WRITE setColumnCategories NOTIFY columnCategoriesChanged)
Q_PROPERTY(bool useModelCategories READ useModelCategories WRITE setUseModelCategories NOTIFY useModelCategoriesChanged)
@@ -50,8 +51,15 @@ public:
QObject *parent = 0);
QItemModelBarDataProxy(const QAbstractItemModel *itemModel, const QString &rowRole,
const QString &columnRole, const QString &valueRole,
+ const QString &rotationRole, QObject *parent = 0);
+ QItemModelBarDataProxy(const QAbstractItemModel *itemModel, const QString &rowRole,
+ const QString &columnRole, const QString &valueRole,
const QStringList &rowCategories, const QStringList &columnCategories,
QObject *parent = 0);
+ QItemModelBarDataProxy(const QAbstractItemModel *itemModel, const QString &rowRole,
+ const QString &columnRole, const QString &valueRole,
+ const QString &rotationRole, const QStringList &rowCategories,
+ const QStringList &columnCategories, QObject *parent = 0);
virtual ~QItemModelBarDataProxy();
void setItemModel(const QAbstractItemModel *itemModel);
@@ -63,6 +71,8 @@ public:
QString columnRole() const;
void setValueRole(const QString &role);
QString valueRole() const;
+ void setRotationRole(const QString &role);
+ QString rotationRole() const;
void setRowCategories(const QStringList &categories);
QStringList rowCategories() const;
@@ -88,6 +98,7 @@ signals:
void rowRoleChanged(QString role);
void columnRoleChanged(QString role);
void valueRoleChanged(QString role);
+ void rotationRoleChanged(QString role);
void rowCategoriesChanged(QStringList categories);
void columnCategoriesChanged(QStringList categories);
void useModelCategoriesChanged(bool enable);
diff --git a/src/datavisualization/data/qitemmodelbardataproxy_p.h b/src/datavisualization/data/qitemmodelbardataproxy_p.h
index 0c987a00..2fd74bb2 100644
--- a/src/datavisualization/data/qitemmodelbardataproxy_p.h
+++ b/src/datavisualization/data/qitemmodelbardataproxy_p.h
@@ -53,6 +53,7 @@ private:
QString m_rowRole;
QString m_columnRole;
QString m_valueRole;
+ QString m_rotationRole;
// For row/column items, sort items into these categories. Other categories are ignored.
QStringList m_rowCategories;
diff --git a/src/datavisualization/data/qitemmodelscatterdataproxy.cpp b/src/datavisualization/data/qitemmodelscatterdataproxy.cpp
index 1edee53c..489f8da7 100644
--- a/src/datavisualization/data/qitemmodelscatterdataproxy.cpp
+++ b/src/datavisualization/data/qitemmodelscatterdataproxy.cpp
@@ -93,6 +93,12 @@ QT_BEGIN_NAMESPACE_DATAVISUALIZATION
*/
/*!
+ * \qmlproperty string ItemModelScatterDataProxy::rotationRole
+ *
+ * Defines the rotation role for the mapping.
+ */
+
+/*!
* Constructs QItemModelScatterDataProxy with optional \a parent.
*/
QItemModelScatterDataProxy::QItemModelScatterDataProxy(QObject *parent)
@@ -134,6 +140,28 @@ QItemModelScatterDataProxy::QItemModelScatterDataProxy(const QAbstractItemModel
}
/*!
+ * Constructs QItemModelScatterDataProxy with \a itemModel and optional \a parent. Proxy doesn't take
+ * ownership of the \a itemModel, as typically item models are owned by other controls.
+ * The xPosRole property is set to \a xPosRole, yPosRole property to \a yPosRole, zPosRole property
+ * to \a zPosRole, and rotationRole property to \a rotationRole.
+ */
+QItemModelScatterDataProxy::QItemModelScatterDataProxy(const QAbstractItemModel *itemModel,
+ const QString &xPosRole,
+ const QString &yPosRole,
+ const QString &zPosRole,
+ const QString &rotationRole,
+ QObject *parent)
+ : QScatterDataProxy(new QItemModelScatterDataProxyPrivate(this), parent)
+{
+ dptr()->m_itemModelHandler->setItemModel(itemModel);
+ dptr()->m_xPosRole = xPosRole;
+ dptr()->m_yPosRole = yPosRole;
+ dptr()->m_zPosRole = zPosRole;
+ dptr()->m_rotationRole = rotationRole;
+ dptr()->connectItemModelHandler();
+}
+
+/*!
* Destroys QItemModelScatterDataProxy.
*/
QItemModelScatterDataProxy::~QItemModelScatterDataProxy()
@@ -211,6 +239,24 @@ QString QItemModelScatterDataProxy::zPosRole() const
}
/*!
+ * \property QItemModelScatterDataProxy::rotationRole
+ *
+ * Defines the rotation role for the mapping.
+ */
+void QItemModelScatterDataProxy::setRotationRole(const QString &role)
+{
+ if (dptr()->m_rotationRole != role) {
+ dptr()->m_rotationRole = role;
+ emit rotationRoleChanged(role);
+ }
+}
+
+QString QItemModelScatterDataProxy::rotationRole() const
+{
+ return dptrc()->m_rotationRole;
+}
+
+/*!
* Changes \a xPosRole, \a yPosRole and \a zPosRole mapping.
*/
void QItemModelScatterDataProxy::remap(const QString &xPosRole, const QString &yPosRole,
diff --git a/src/datavisualization/data/qitemmodelscatterdataproxy.h b/src/datavisualization/data/qitemmodelscatterdataproxy.h
index 0f69afa7..accfeb18 100644
--- a/src/datavisualization/data/qitemmodelscatterdataproxy.h
+++ b/src/datavisualization/data/qitemmodelscatterdataproxy.h
@@ -34,6 +34,7 @@ class QT_DATAVISUALIZATION_EXPORT QItemModelScatterDataProxy : public QScatterDa
Q_PROPERTY(QString xPosRole READ xPosRole WRITE setXPosRole NOTIFY xPosRoleChanged)
Q_PROPERTY(QString yPosRole READ yPosRole WRITE setYPosRole NOTIFY yPosRoleChanged)
Q_PROPERTY(QString zPosRole READ zPosRole WRITE setZPosRole NOTIFY zPosRoleChanged)
+ Q_PROPERTY(QString rotationRole READ rotationRole WRITE setRotationRole NOTIFY rotationRoleChanged)
public:
explicit QItemModelScatterDataProxy(QObject *parent = 0);
@@ -41,6 +42,10 @@ public:
QItemModelScatterDataProxy(const QAbstractItemModel *itemModel,
const QString &xPosRole, const QString &yPosRole,
const QString &zPosRole, QObject *parent = 0);
+ QItemModelScatterDataProxy(const QAbstractItemModel *itemModel,
+ const QString &xPosRole, const QString &yPosRole,
+ const QString &zPosRole, const QString &rotationRole,
+ QObject *parent = 0);
virtual ~QItemModelScatterDataProxy();
void setItemModel(const QAbstractItemModel *itemModel);
@@ -52,6 +57,8 @@ public:
QString yPosRole() const;
void setZPosRole(const QString &role);
QString zPosRole() const;
+ void setRotationRole(const QString &role);
+ QString rotationRole() const;
void remap(const QString &xPosRole, const QString &yPosRole, const QString &zPosRole);
@@ -60,6 +67,7 @@ signals:
void xPosRoleChanged(QString role);
void yPosRoleChanged(QString role);
void zPosRoleChanged(QString role);
+ void rotationRoleChanged(QString role);
protected:
QItemModelScatterDataProxyPrivate *dptr();
diff --git a/src/datavisualization/data/qitemmodelscatterdataproxy_p.h b/src/datavisualization/data/qitemmodelscatterdataproxy_p.h
index b8804c5c..4e1f321f 100644
--- a/src/datavisualization/data/qitemmodelscatterdataproxy_p.h
+++ b/src/datavisualization/data/qitemmodelscatterdataproxy_p.h
@@ -52,6 +52,7 @@ private:
QString m_xPosRole;
QString m_yPosRole;
QString m_zPosRole;
+ QString m_rotationRole;
friend class ScatterItemModelHandler;
friend class QItemModelScatterDataProxy;
diff --git a/src/datavisualization/data/scatteritemmodelhandler.cpp b/src/datavisualization/data/scatteritemmodelhandler.cpp
index 1c936d08..1b1aaefe 100644
--- a/src/datavisualization/data/scatteritemmodelhandler.cpp
+++ b/src/datavisualization/data/scatteritemmodelhandler.cpp
@@ -92,6 +92,30 @@ void ScatterItemModelHandler::handleRowsRemoved(const QModelIndex &parent, int s
}
}
+static inline QQuaternion toQuaternion(const QVariant &variant)
+{
+ if (variant.canConvert<QQuaternion>()) {
+ return variant.value<QQuaternion>();
+ } else if (variant.canConvert<QString>()) {
+ QString s = variant.toString();
+ if (!s.isEmpty() && s.count(QLatin1Char(',')) == 3) {
+ int index = s.indexOf(QLatin1Char(','));
+ int index2 = s.indexOf(QLatin1Char(','), index + 1);
+ int index3 = s.indexOf(QLatin1Char(','), index2 + 1);
+
+ bool sGood, xGood, yGood, zGood;
+ float sCoord = s.left(index).toFloat(&sGood);
+ float xCoord = s.mid(index + 1, index2 - index - 1).toFloat(&xGood);
+ float yCoord = s.mid(index2 + 1, index3 - index2 - 1).toFloat(&yGood);
+ float zCoord = s.mid(index3 + 1).toFloat(&zGood);
+
+ if (sGood && xGood && yGood && zGood)
+ return QQuaternion(sCoord, xCoord, yCoord, zCoord);
+ }
+ }
+ return QQuaternion();
+}
+
void ScatterItemModelHandler::modelPosToScatterItem(int modelRow, int modelColumn,
QScatterDataItem &item)
{
@@ -105,6 +129,8 @@ void ScatterItemModelHandler::modelPosToScatterItem(int modelRow, int modelColum
yPos = index.data(m_yPosRole).toFloat();
if (m_zPosRole != noRoleIndex)
zPos = index.data(m_zPosRole).toFloat();
+ if (m_rotationRole != noRoleIndex)
+ item.setRotation(toQuaternion(index.data(m_rotationRole)));
item.setPosition(QVector3D(xPos, yPos, zPos));
}
@@ -121,6 +147,7 @@ void ScatterItemModelHandler::resolveModel()
m_xPosRole = roleHash.key(m_proxy->xPosRole().toLatin1(), noRoleIndex);
m_yPosRole = roleHash.key(m_proxy->yPosRole().toLatin1(), noRoleIndex);
m_zPosRole = roleHash.key(m_proxy->zPosRole().toLatin1(), noRoleIndex);
+ m_rotationRole = roleHash.key(m_proxy->rotationRole().toLatin1(), noRoleIndex);
const int columnCount = m_itemModel->columnCount();
const int rowCount = m_itemModel->rowCount();
const int totalCount = rowCount * columnCount;
diff --git a/src/datavisualization/data/scatteritemmodelhandler_p.h b/src/datavisualization/data/scatteritemmodelhandler_p.h
index f0e4fa84..0661d734 100644
--- a/src/datavisualization/data/scatteritemmodelhandler_p.h
+++ b/src/datavisualization/data/scatteritemmodelhandler_p.h
@@ -58,6 +58,7 @@ private:
int m_xPosRole;
int m_yPosRole;
int m_zPosRole;
+ int m_rotationRole;
};
QT_END_NAMESPACE_DATAVISUALIZATION
diff --git a/tests/qmlcamera/qml/qmlcamera/Data.qml b/tests/qmlcamera/qml/qmlcamera/Data.qml
index 3c787186..bab6bf78 100644
--- a/tests/qmlcamera/qml/qmlcamera/Data.qml
+++ b/tests/qmlcamera/qml/qmlcamera/Data.qml
@@ -30,41 +30,44 @@ Item {
rowRole: "year"
columnRole: "month"
valueRole: "expenses"
+ rotationRole: "angle"
}
Bar3DSeries {
id: barSeries
dataProxy: modelProxy
itemLabelFormat: "@valueTitle for @colLabel, @rowLabel: @valueLabel"
+
+ onMeshAngleChanged: console.log("angle changed:", angle)
}
ListModel {
id: dataModel
- ListElement{ year: "2006"; month: "Jan"; expenses: "4"; income: "5" }
- ListElement{ year: "2006"; month: "Feb"; expenses: "5"; income: "6" }
- ListElement{ year: "2006"; month: "Mar"; expenses: "7"; income: "4" }
- ListElement{ year: "2006"; month: "Apr"; expenses: "3"; income: "2" }
- ListElement{ year: "2006"; month: "May"; expenses: "4"; income: "1" }
- ListElement{ year: "2006"; month: "Jun"; expenses: "2"; income: "2" }
- ListElement{ year: "2006"; month: "Jul"; expenses: "1"; income: "3" }
- ListElement{ year: "2006"; month: "Aug"; expenses: "5"; income: "1" }
- ListElement{ year: "2006"; month: "Sep"; expenses: "2"; income: "3" }
- ListElement{ year: "2006"; month: "Oct"; expenses: "5"; income: "2" }
- ListElement{ year: "2006"; month: "Nov"; expenses: "8"; income: "5" }
- ListElement{ year: "2006"; month: "Dec"; expenses: "3"; income: "3" }
+ ListElement{ year: "2006"; month: "Jan"; expenses: "4"; angle: "1"; income: "5" }
+ ListElement{ year: "2006"; month: "Feb"; expenses: "5"; angle: "2"; income: "6" }
+ ListElement{ year: "2006"; month: "Mar"; expenses: "7"; angle: "3"; income: "4" }
+ ListElement{ year: "2006"; month: "Apr"; expenses: "3"; angle: "4"; income: "2" }
+ ListElement{ year: "2006"; month: "May"; expenses: "4"; angle: "5"; income: "1" }
+ ListElement{ year: "2006"; month: "Jun"; expenses: "2"; angle: "6"; income: "2" }
+ ListElement{ year: "2006"; month: "Jul"; expenses: "1"; angle: "7"; income: "3" }
+ ListElement{ year: "2006"; month: "Aug"; expenses: "5"; angle: "8"; income: "1" }
+ ListElement{ year: "2006"; month: "Sep"; expenses: "2"; angle: "9"; income: "3" }
+ ListElement{ year: "2006"; month: "Oct"; expenses: "5"; angle: "10"; income: "2" }
+ ListElement{ year: "2006"; month: "Nov"; expenses: "8"; angle: "11"; income: "5" }
+ ListElement{ year: "2006"; month: "Dec"; expenses: "3"; angle: "12"; income: "3" }
- ListElement{ year: "2007"; month: "Jan"; expenses: "3"; income: "1" }
- ListElement{ year: "2007"; month: "Feb"; expenses: "4"; income: "2" }
- ListElement{ year: "2007"; month: "Mar"; expenses: "12"; income: "4" }
- ListElement{ year: "2007"; month: "Apr"; expenses: "13"; income: "6" }
- ListElement{ year: "2007"; month: "May"; expenses: "14"; income: "11" }
- ListElement{ year: "2007"; month: "Jun"; expenses: "7"; income: "7" }
- ListElement{ year: "2007"; month: "Jul"; expenses: "6"; income: "4" }
- ListElement{ year: "2007"; month: "Aug"; expenses: "4"; income: "15" }
- ListElement{ year: "2007"; month: "Sep"; expenses: "2"; income: "18" }
- ListElement{ year: "2007"; month: "Oct"; expenses: "29"; income: "25" }
- ListElement{ year: "2007"; month: "Nov"; expenses: "23"; income: "29" }
- ListElement{ year: "2007"; month: "Dec"; expenses: "5"; income: "9" }
+ ListElement{ year: "2007"; month: "Jan"; expenses: "3"; angle: "13"; income: "1" }
+ ListElement{ year: "2007"; month: "Feb"; expenses: "4"; angle: "14"; income: "2" }
+ ListElement{ year: "2007"; month: "Mar"; expenses: "12";angle: "15"; income: "4" }
+ ListElement{ year: "2007"; month: "Apr"; expenses: "13";angle: "16"; income: "6" }
+ ListElement{ year: "2007"; month: "May"; expenses: "14";angle: "17"; income: "11" }
+ ListElement{ year: "2007"; month: "Jun"; expenses: "7"; angle: "18"; income: "7" }
+ ListElement{ year: "2007"; month: "Jul"; expenses: "6"; angle: "19"; income: "4" }
+ ListElement{ year: "2007"; month: "Aug"; expenses: "4"; angle: "20"; income: "15" }
+ ListElement{ year: "2007"; month: "Sep"; expenses: "2"; angle: "21"; income: "18" }
+ ListElement{ year: "2007"; month: "Oct"; expenses: "29";angle: "22"; income: "25" }
+ ListElement{ year: "2007"; month: "Nov"; expenses: "23";angle: "23"; income: "29" }
+ ListElement{ year: "2007"; month: "Dec"; expenses: "5"; angle: "24"; income: "9" }
ListElement{ year: "2008"; month: "Jan"; expenses: "3"; income: "8" }
ListElement{ year: "2008"; month: "Feb"; expenses: "8"; income: "14" }
@@ -79,56 +82,56 @@ Item {
ListElement{ year: "2008"; month: "Nov"; expenses: "16"; income: "25" }
ListElement{ year: "2008"; month: "Dec"; expenses: "2"; income: "7" }
- ListElement{ year: "2009"; month: "Jan"; expenses: "4"; income: "5" }
- ListElement{ year: "2009"; month: "Feb"; expenses: "4"; income: "7" }
- ListElement{ year: "2009"; month: "Mar"; expenses: "11"; income: "14" }
- ListElement{ year: "2009"; month: "Apr"; expenses: "16"; income: "22" }
- ListElement{ year: "2009"; month: "May"; expenses: "3"; income: "5" }
- ListElement{ year: "2009"; month: "Jun"; expenses: "4"; income: "8" }
- ListElement{ year: "2009"; month: "Jul"; expenses: "7"; income: "9" }
- ListElement{ year: "2009"; month: "Aug"; expenses: "9"; income: "13" }
- ListElement{ year: "2009"; month: "Sep"; expenses: "1"; income: "6" }
- ListElement{ year: "2009"; month: "Oct"; expenses: "14"; income: "25" }
- ListElement{ year: "2009"; month: "Nov"; expenses: "19"; income: "29" }
- ListElement{ year: "2009"; month: "Dec"; expenses: "5"; income: "7" }
+ ListElement{ year: "2009"; month: "Jan"; expenses: "4"; angle: "37"; income: "5" }
+ ListElement{ year: "2009"; month: "Feb"; expenses: "4"; angle: "38"; income: "7" }
+ ListElement{ year: "2009"; month: "Mar"; expenses: "11";angle: "39"; income: "14" }
+ ListElement{ year: "2009"; month: "Apr"; expenses: "16";angle: "40"; income: "22" }
+ ListElement{ year: "2009"; month: "May"; expenses: "3"; angle: "41"; income: "5" }
+ ListElement{ year: "2009"; month: "Jun"; expenses: "4"; angle: "42"; income: "8" }
+ ListElement{ year: "2009"; month: "Jul"; expenses: "7"; angle: "43"; income: "9" }
+ ListElement{ year: "2009"; month: "Aug"; expenses: "9"; angle: "44"; income: "13" }
+ ListElement{ year: "2009"; month: "Sep"; expenses: "1"; angle: "45"; income: "6" }
+ ListElement{ year: "2009"; month: "Oct"; expenses: "14";angle: "46"; income: "25" }
+ ListElement{ year: "2009"; month: "Nov"; expenses: "19";angle: "47"; income: "29" }
+ ListElement{ year: "2009"; month: "Dec"; expenses: "5"; angle: "48"; income: "7" }
- ListElement{ year: "2010"; month: "Jan"; expenses: "14"; income: "22" }
- ListElement{ year: "2010"; month: "Feb"; expenses: "5"; income: "7" }
- ListElement{ year: "2010"; month: "Mar"; expenses: "1"; income: "9" }
- ListElement{ year: "2010"; month: "Apr"; expenses: "1"; income: "12" }
- ListElement{ year: "2010"; month: "May"; expenses: "5"; income: "9" }
- ListElement{ year: "2010"; month: "Jun"; expenses: "5"; income: "8" }
- ListElement{ year: "2010"; month: "Jul"; expenses: "3"; income: "7" }
- ListElement{ year: "2010"; month: "Aug"; expenses: "1"; income: "5" }
- ListElement{ year: "2010"; month: "Sep"; expenses: "2"; income: "4" }
- ListElement{ year: "2010"; month: "Oct"; expenses: "10"; income: "13" }
- ListElement{ year: "2010"; month: "Nov"; expenses: "12"; income: "17" }
- ListElement{ year: "2010"; month: "Dec"; expenses: "6"; income: "9" }
+ ListElement{ year: "2010"; month: "Jan"; expenses: "14";angle: "49"; income: "22" }
+ ListElement{ year: "2010"; month: "Feb"; expenses: "5"; angle: "50"; income: "7" }
+ ListElement{ year: "2010"; month: "Mar"; expenses: "1"; angle: "51"; income: "9" }
+ ListElement{ year: "2010"; month: "Apr"; expenses: "1"; angle: "52"; income: "12" }
+ ListElement{ year: "2010"; month: "May"; expenses: "5"; angle: "53"; income: "9" }
+ ListElement{ year: "2010"; month: "Jun"; expenses: "5"; angle: "54"; income: "8" }
+ ListElement{ year: "2010"; month: "Jul"; expenses: "3"; angle: "55"; income: "7" }
+ ListElement{ year: "2010"; month: "Aug"; expenses: "1"; angle: "56"; income: "5" }
+ ListElement{ year: "2010"; month: "Sep"; expenses: "2"; angle: "57"; income: "4" }
+ ListElement{ year: "2010"; month: "Oct"; expenses: "10";angle: "58"; income: "13" }
+ ListElement{ year: "2010"; month: "Nov"; expenses: "12";angle: "59"; income: "17" }
+ ListElement{ year: "2010"; month: "Dec"; expenses: "6"; angle: "60"; income: "9" }
- ListElement{ year: "2011"; month: "Jan"; expenses: "2"; income: "6" }
- ListElement{ year: "2011"; month: "Feb"; expenses: "4"; income: "8" }
- ListElement{ year: "2011"; month: "Mar"; expenses: "7"; income: "12" }
- ListElement{ year: "2011"; month: "Apr"; expenses: "9"; income: "15" }
- ListElement{ year: "2011"; month: "May"; expenses: "7"; income: "19" }
- ListElement{ year: "2011"; month: "Jun"; expenses: "9"; income: "18" }
- ListElement{ year: "2011"; month: "Jul"; expenses: "13"; income: "17" }
- ListElement{ year: "2011"; month: "Aug"; expenses: "5"; income: "9" }
- ListElement{ year: "2011"; month: "Sep"; expenses: "3"; income: "8" }
- ListElement{ year: "2011"; month: "Oct"; expenses: "13"; income: "15" }
- ListElement{ year: "2011"; month: "Nov"; expenses: "8"; income: "17" }
- ListElement{ year: "2011"; month: "Dec"; expenses: "7"; income: "10" }
+ ListElement{ year: "2011"; month: "Jan"; expenses: "2"; angle: "61"; income: "6" }
+ ListElement{ year: "2011"; month: "Feb"; expenses: "4"; angle: "62"; income: "8" }
+ ListElement{ year: "2011"; month: "Mar"; expenses: "7"; angle: "63"; income: "12" }
+ ListElement{ year: "2011"; month: "Apr"; expenses: "9"; angle: "64"; income: "15" }
+ ListElement{ year: "2011"; month: "May"; expenses: "7"; angle: "65"; income: "19" }
+ ListElement{ year: "2011"; month: "Jun"; expenses: "9"; angle: "66"; income: "18" }
+ ListElement{ year: "2011"; month: "Jul"; expenses: "13";angle: "67"; income: "17" }
+ ListElement{ year: "2011"; month: "Aug"; expenses: "5"; angle: "68"; income: "9" }
+ ListElement{ year: "2011"; month: "Sep"; expenses: "3"; angle: "69"; income: "8" }
+ ListElement{ year: "2011"; month: "Oct"; expenses: "13";angle: "70"; income: "15" }
+ ListElement{ year: "2011"; month: "Nov"; expenses: "8"; angle: "71"; income: "17" }
+ ListElement{ year: "2011"; month: "Dec"; expenses: "7"; angle: "72"; income: "10" }
- ListElement{ year: "2012"; month: "Jan"; expenses: "12"; income: "16" }
- ListElement{ year: "2012"; month: "Feb"; expenses: "24"; income: "28" }
- ListElement{ year: "2012"; month: "Mar"; expenses: "27"; income: "22" }
- ListElement{ year: "2012"; month: "Apr"; expenses: "29"; income: "25" }
- ListElement{ year: "2012"; month: "May"; expenses: "27"; income: "29" }
- ListElement{ year: "2012"; month: "Jun"; expenses: "19"; income: "18" }
- ListElement{ year: "2012"; month: "Jul"; expenses: "13"; income: "17" }
- ListElement{ year: "2012"; month: "Aug"; expenses: "15"; income: "19" }
- ListElement{ year: "2012"; month: "Sep"; expenses: "3"; income: "8" }
- ListElement{ year: "2012"; month: "Oct"; expenses: "3"; income: "6" }
- ListElement{ year: "2012"; month: "Nov"; expenses: "4"; income: "8" }
- ListElement{ year: "2012"; month: "Dec"; expenses: "5"; income: "9" }
+ ListElement{ year: "2012"; month: "Jan"; expenses: "12";angle: "73"; income: "16" }
+ ListElement{ year: "2012"; month: "Feb"; expenses: "24";angle: "74"; income: "28" }
+ ListElement{ year: "2012"; month: "Mar"; expenses: "27";angle: "75"; income: "22" }
+ ListElement{ year: "2012"; month: "Apr"; expenses: "29";angle: "76"; income: "25" }
+ ListElement{ year: "2012"; month: "May"; expenses: "27";angle: "77"; income: "29" }
+ ListElement{ year: "2012"; month: "Jun"; expenses: "19";angle: "78"; income: "18" }
+ ListElement{ year: "2012"; month: "Jul"; expenses: "13";angle: "79"; income: "17" }
+ ListElement{ year: "2012"; month: "Aug"; expenses: "15";angle: "80"; income: "19" }
+ ListElement{ year: "2012"; month: "Sep"; expenses: "3"; angle: "81"; income: "8" }
+ ListElement{ year: "2012"; month: "Oct"; expenses: "3"; angle: "82"; income: "6" }
+ ListElement{ year: "2012"; month: "Nov"; expenses: "4"; angle: "83"; income: "8" }
+ ListElement{ year: "2012"; month: "Dec"; expenses: "5"; angle: "84"; income: "9" }
}
}
diff --git a/tests/qmlcamera/qml/qmlcamera/main.qml b/tests/qmlcamera/qml/qmlcamera/main.qml
index a5176553..4aa85728 100644
--- a/tests/qmlcamera/qml/qmlcamera/main.qml
+++ b/tests/qmlcamera/qml/qmlcamera/main.qml
@@ -133,24 +133,20 @@ Item {
}
Button {
- id: shadowToggle
+ id: angleAdjust
anchors.bottom: mappingToggle.top
width: camControlArea.width
- text: "Hide Shadows"
+ text: "Adjust angle"
+ property real currentAngle: 0
onClicked: {
- if (testChart.shadowQuality == AbstractGraph3D.ShadowQualityNone) {
- testChart.shadowQuality = AbstractGraph3D.ShadowQualityMedium;
- text = "Hide Shadows"
- } else {
- testChart.shadowQuality = AbstractGraph3D.ShadowQualityNone;
- text = "Show Shadows"
- }
+ currentAngle += 5
+ chartData.series.meshAngle = currentAngle
}
}
Button {
id: dataToggle
- anchors.bottom: shadowToggle.top
+ anchors.bottom: angleAdjust.top
width: camControlArea.width
text: "Show 2010 - 2012"
onClicked: {
diff --git a/tests/qmldynamicdata/qml/qmldynamicdata/main.qml b/tests/qmldynamicdata/qml/qmldynamicdata/main.qml
index 6f0032ac..d384c3ee 100644
--- a/tests/qmldynamicdata/qml/qmldynamicdata/main.qml
+++ b/tests/qmldynamicdata/qml/qmldynamicdata/main.qml
@@ -28,8 +28,8 @@ Item {
ListModel {
id: graphModel
- ListElement{ xPos: 0.0; yPos: 0.0; zPos: 0.0 }
- ListElement{ xPos: 1.0; yPos: 1.0; zPos: 1.0 }
+ ListElement{ xPos: 0.0; yPos: 0.0; zPos: 0.0; rotation: "0.92388, 0.220942, 0.220942, 0.220942"}
+ ListElement{ xPos: 1.0; yPos: 1.0; zPos: 1.0; rotation: "0.953717, 0.173613, 0.173613, 0.173613"}
}
Timer {
@@ -114,6 +114,7 @@ Item {
xPosRole: "xPos"
yPosRole: "yPos"
zPosRole: "zPos"
+ rotationRole: "rotation"
}
}
}