From 4dcef4be656aedb7c6c9e222f291a1a508641007 Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen Date: Mon, 12 May 2014 11:10:46 +0300 Subject: Enable mapping single role to multiple properties for surface MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Task-number: QTRD-3074 Change-Id: If40de067526b6f24b3e55bf64ed804a79d473e5f Reviewed-by: Tomi Korpipää Reviewed-by: Titta Heikkala --- src/datavisualization/data/baritemmodelhandler.cpp | 10 +- .../data/qitemmodelsurfacedataproxy.cpp | 420 +++++++++++++++++++-- .../data/qitemmodelsurfacedataproxy.h | 43 +++ .../data/qitemmodelsurfacedataproxy_p.h | 12 + src/datavisualization/data/qsurfacedataproxy.cpp | 12 +- .../data/surfaceitemmodelhandler.cpp | 115 +++++- .../data/surfaceitemmodelhandler_p.h | 9 + .../datavisualizationqml2_plugin.cpp | 1 + tests/itemmodeltest/main.cpp | 37 +- tests/qmlmultitest/main.cpp | 47 +++ tests/qmlmultitest/qml/qmlmultitest/Data.qml | 48 +++ tests/qmlmultitest/qml/qmlmultitest/NewButton.qml | 52 +++ tests/qmlmultitest/qml/qmlmultitest/main.qml | 231 ++++++++++++ tests/qmlmultitest/qmlmultitest.pro | 12 + tests/qmlmultitest/qmlmultitest.qrc | 7 + tests/tests.pro | 3 +- 16 files changed, 990 insertions(+), 69 deletions(-) create mode 100644 tests/qmlmultitest/main.cpp create mode 100644 tests/qmlmultitest/qml/qmlmultitest/Data.qml create mode 100644 tests/qmlmultitest/qml/qmlmultitest/NewButton.qml create mode 100644 tests/qmlmultitest/qml/qmlmultitest/main.qml create mode 100644 tests/qmlmultitest/qmlmultitest.pro create mode 100644 tests/qmlmultitest/qmlmultitest.qrc diff --git a/src/datavisualization/data/baritemmodelhandler.cpp b/src/datavisualization/data/baritemmodelhandler.cpp index e8941c4b..4685be44 100644 --- a/src/datavisualization/data/baritemmodelhandler.cpp +++ b/src/datavisualization/data/baritemmodelhandler.cpp @@ -55,8 +55,9 @@ void BarItemModelHandler::handleDataChanged(const QModelIndex &topLeft, for (int i = startRow; i <= endRow; i++) { for (int j = startCol; j <= endCol; j++) { + QModelIndex index = m_itemModel->index(i, j); QBarDataItem item; - QVariant valueVar = m_itemModel->index(i, j).data(m_valueRole); + QVariant valueVar = index.data(m_valueRole); float value; if (m_haveValuePattern) value = valueVar.toString().replace(m_valuePattern, m_valueReplace).toFloat(); @@ -64,7 +65,7 @@ void BarItemModelHandler::handleDataChanged(const QModelIndex &topLeft, value = valueVar.toFloat(); item.setValue(value); if (m_rotationRole != noRoleIndex) { - QVariant rotationVar = m_itemModel->index(i, j).data(m_rotationRole); + QVariant rotationVar = index.data(m_rotationRole); float rotation; if (m_haveRotationPattern) { rotation = rotationVar.toString().replace(m_rotationPattern, @@ -133,7 +134,8 @@ void BarItemModelHandler::resolveModel() for (int i = 0; i < rowCount; i++) { QBarDataRow &newProxyRow = *m_proxyArray->at(i); for (int j = 0; j < columnCount; j++) { - QVariant valueVar = m_itemModel->index(i, j).data(m_valueRole); + QModelIndex index = m_itemModel->index(i, j); + QVariant valueVar = index.data(m_valueRole); float value; if (m_haveValuePattern) value = valueVar.toString().replace(m_valuePattern, m_valueReplace).toFloat(); @@ -141,7 +143,7 @@ void BarItemModelHandler::resolveModel() value = valueVar.toFloat(); newProxyRow[j].setValue(value); if (m_rotationRole != noRoleIndex) { - QVariant rotationVar = m_itemModel->index(i, j).data(m_rotationRole); + QVariant rotationVar = index.data(m_rotationRole); float rotation; if (m_haveRotationPattern) { rotation = rotationVar.toString().replace(m_rotationPattern, diff --git a/src/datavisualization/data/qitemmodelsurfacedataproxy.cpp b/src/datavisualization/data/qitemmodelsurfacedataproxy.cpp index 440ce2d6..77f90ed4 100644 --- a/src/datavisualization/data/qitemmodelsurfacedataproxy.cpp +++ b/src/datavisualization/data/qitemmodelsurfacedataproxy.cpp @@ -54,13 +54,24 @@ QT_BEGIN_NAMESPACE_DATAVISUALIZATION * 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 the 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: + * For example, assume that you have a custom QAbstractItemModel storing surface topography data. + * Each item in the model has the 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 + * \snippet doc_src_qtdatavisualization.cpp 5 + * + * If the fields of the model do not contain the data in the exact format you need, you can specify + * a search pattern regular expression and a replace rule for each role to get the value in a + * format you need. For more information how the replace using regular expressions works, see + * QString::replace(const QRegExp &rx, const QString &after) function documentation. Note that + * using regular expressions has an impact on the performance, so it's more efficient to utilize + * item models where doing search and replace is not necessary to get the desired values. + * + * For example about using the search patterns in conjunction with the roles, see + * ItemModelBarDataProxy usage in \l{Qt Quick 2 Bars Example}. * * \sa {Qt Data Visualization Data Handling} */ @@ -95,33 +106,35 @@ QT_BEGIN_NAMESPACE_DATAVISUALIZATION /*! * \qmlproperty string ItemModelSurfaceDataProxy::rowRole - * The row role of the mapping. + * Defines the item model role to map into row category. * In addition to defining which row the data belongs to, the value indicated by row role - * is also set as the Z-coordinate value of the QSurfaceDataItem when model data is resolved. + * is also set as the Z-coordinate value of the QSurfaceDataItem when model data is resolved, + * unless a separate zPos role is also defined. */ /*! * \qmlproperty string ItemModelSurfaceDataProxy::columnRole - * The column role of the mapping. + * Defines the item model role to map into column category. * In addition to defining which column the data belongs to, the value indicated by column role - * is also set as the X-coordinate value of the QSurfaceDataItem when model data is resolved. + * is also set as the X-coordinate value of the QSurfaceDataItem when model data is resolved, + * unless a separate xPos role is also defined. */ /*! * \qmlproperty string ItemModelSurfaceDataProxy::xPosRole - * The X position role of the mapping. If this role is not defined, columnRole is used to - * determine the X-coordinate value of resolved QSurfaceDataItems. + * Defines the item model role to map into X position. If this role is not defined, columnRole is + * used to determine the X-coordinate value of resolved QSurfaceDataItems. */ /*! * \qmlproperty string ItemModelSurfaceDataProxy::yPosRole - * The Y position role of the mapping. + * Defines the item model role to map into Y position. */ /*! * \qmlproperty string ItemModelSurfaceDataProxy::zPosRole - * The Z position role of the mapping. If this role is not defined, rowRole is used to - * determine the Z-coordinate value of resolved QSurfaceDataItems. + * Defines the item model role to map into Z position. If this role is not defined, rowRole is + * used to determine the Z-coordinate value of resolved QSurfaceDataItems. */ /*! @@ -132,8 +145,9 @@ QT_BEGIN_NAMESPACE_DATAVISUALIZATION /*! * \qmlproperty list ItemModelSurfaceDataProxy::columnCategories - * The column categories of the mapping. Only items with column roles that are found in this list are - * included when data is resolved. The columns are ordered in the same order as they are in this list. + * The column categories of the mapping. Only items with column roles that are found in this + * list are included when data is resolved. The columns are ordered in the same order as they are + * in this list. */ /*! @@ -158,6 +172,111 @@ QT_BEGIN_NAMESPACE_DATAVISUALIZATION * autogenerated from data when this is set to true. Defaults to \c{true}. */ +/*! + * \qmlproperty regExp ItemModelSurfaceDataProxy::rowRolePattern + * + * When set, a search and replace is done on the value mapped by row role before it is used as + * a row category. This property specifies the regular expression to find the portion of the + * mapped value to replace and rowRoleReplace property contains the replacement string. + * + * \sa rowRole, rowRoleReplace + */ + +/*! + * \qmlproperty regExp ItemModelSurfaceDataProxy::columnRolePattern + * + * When set, a search and replace is done on the value mapped by column role before it is used + * as a column category. This property specifies the regular expression to find the portion of the + * mapped value to replace and columnRoleReplace property contains the replacement string. + * + * \sa columnRole, columnRoleReplace + */ + +/*! + * \qmlproperty regExp ItemModelSurfaceDataProxy::xPosRolePattern + * + * When set, a search and replace is done on the value mapped by xPos role before it is used as + * a item position value. This property specifies the regular expression to find the portion of the + * mapped value to replace and xPosRoleReplace property contains the replacement string. + * + * \sa xPosRole, xPosRoleReplace + */ + +/*! + * \qmlproperty regExp ItemModelSurfaceDataProxy::yPosRolePattern + * + * When set, a search and replace is done on the value mapped by yPos role before it is used as + * a item position value. This property specifies the regular expression to find the portion of the + * mapped value to replace and yPosRoleReplace property contains the replacement string. + * + * \sa yPosRole, yPosRoleReplace + */ + +/*! + * \qmlproperty regExp ItemModelSurfaceDataProxy::zPosRolePattern + * + * When set, a search and replace is done on the value mapped by zPos role before it is used as + * a item position value. This property specifies the regular expression to find the portion of the + * mapped value to replace and zPosRoleReplace property contains the replacement string. + * + * \sa zPosRole, zPosRoleReplace + */ + +/*! + * \qmlproperty string ItemModelSurfaceDataProxy::rowRoleReplace + * + * This property defines the replace content to be used in conjunction with rowRolePattern. + * Defaults to empty string. For more information on how the search and replace using regular + * expressions works, see QString::replace(const QRegExp &rx, const QString &after) + * function documentation. + * + * \sa rowRole, rowRolePattern + */ + +/*! + * \qmlproperty string ItemModelSurfaceDataProxy::columnRoleReplace + * + * This property defines the replace content to be used in conjunction with columnRolePattern. + * Defaults to empty string. For more information on how the search and replace using regular + * expressions works, see QString::replace(const QRegExp &rx, const QString &after) + * function documentation. + * + * \sa columnRole, columnRolePattern + */ + +/*! + * \qmlproperty string ItemModelSurfaceDataProxy::xPosRoleReplace + * + * This property defines the replace content to be used in conjunction with xPosRolePattern. + * Defaults to empty string. For more information on how the search and replace using regular + * expressions works, see QString::replace(const QRegExp &rx, const QString &after) + * function documentation. + * + * \sa xPosRole, xPosRolePattern + */ + +/*! + * \qmlproperty string ItemModelSurfaceDataProxy::yPosRoleReplace + * + * This property defines the replace content to be used in conjunction with yPosRolePattern. + * Defaults to empty string. For more information on how the search and replace using regular + * expressions works, see QString::replace(const QRegExp &rx, const QString &after) + * function documentation. + * + * \sa yPosRole, yPosRolePattern + */ + +/*! + * \qmlproperty string ItemModelSurfaceDataProxy::zPosRoleReplace + * + * This property defines the replace content to be used in conjunction with zPosRolePattern. + * Defaults to empty string. For more information on how the search and replace using regular + * expressions works, see QString::replace(const QRegExp &rx, const QString &after) + * function documentation. + * + * \sa zPosRole, zPosRolePattern + */ + /*! * Constructs QItemModelSurfaceDataProxy with optional \a parent. */ @@ -331,7 +450,10 @@ const QAbstractItemModel *QItemModelSurfaceDataProxy::itemModel() const /*! * \property QItemModelSurfaceDataProxy::rowRole * - * Defines the row \a role for the mapping. + * Defines the item model role to map into row category. + * In addition to defining which row the data belongs to, the value indicated by row role + * is also set as the Z-coordinate value of the QSurfaceDataItem when model data is resolved, + * unless a separate zPos role is also defined. */ void QItemModelSurfaceDataProxy::setRowRole(const QString &role) { @@ -349,7 +471,10 @@ QString QItemModelSurfaceDataProxy::rowRole() const /*! * \property QItemModelSurfaceDataProxy::columnRole * - * Defines the column \a role for the mapping. + * Defines the item model role to map into column category. + * In addition to defining which column the data belongs to, the value indicated by column role + * is also set as the X-coordinate value of the QSurfaceDataItem when model data is resolved, + * unless a separate xPos role is also defined. */ void QItemModelSurfaceDataProxy::setColumnRole(const QString &role) { @@ -367,9 +492,8 @@ QString QItemModelSurfaceDataProxy::columnRole() const /*! * \property QItemModelSurfaceDataProxy::xPosRole * - * Defines the X position \a role for the mapping. - * If this role is not defined, columnRole is used to determine the X-coordinate - * value of resolved QSurfaceDataItems. + * Defines the item model role to map into X position. If this role is not defined, columnRole is + * used to determine the X-coordinate value of resolved QSurfaceDataItems. */ void QItemModelSurfaceDataProxy::setXPosRole(const QString &role) { @@ -387,7 +511,7 @@ QString QItemModelSurfaceDataProxy::xPosRole() const /*! * \property QItemModelSurfaceDataProxy::yPosRole * - * Defines the Y position \a role for the mapping. + * Defines the item model role to map into Y position. */ void QItemModelSurfaceDataProxy::setYPosRole(const QString &role) { @@ -405,9 +529,8 @@ QString QItemModelSurfaceDataProxy::yPosRole() const /*! * \property QItemModelSurfaceDataProxy::zPosRole * - * Defines the Z position \a role for the mapping. - * If this role is not defined, rowRole is used to determine the Z-coordinate - * value of resolved QSurfaceDataItems. + * Defines the item model role to map into Z position. If this role is not defined, rowRole is + * used to determine the Z-coordinate value of resolved QSurfaceDataItems. */ void QItemModelSurfaceDataProxy::setZPosRole(const QString &role) { @@ -560,6 +683,231 @@ int QItemModelSurfaceDataProxy::columnCategoryIndex(const QString &category) return dptr()->m_columnCategories.indexOf(category); } +/*! + * \property QItemModelSurfaceDataProxy::rowRolePattern + * + * When set, a search and replace is done on the value mapped by row role before it is used as + * a row category. This property specifies the regular expression to find the portion of the + * mapped value to replace and rowRoleReplace property contains the replacement string. + * + * \sa rowRole, rowRoleReplace + */ +void QItemModelSurfaceDataProxy::setRowRolePattern(const QRegExp &pattern) +{ + if (dptr()->m_rowRolePattern != pattern) { + dptr()->m_rowRolePattern = pattern; + emit rowRolePatternChanged(pattern); + } +} + +QRegExp QItemModelSurfaceDataProxy::rowRolePattern() const +{ + return dptrc()->m_rowRolePattern; +} + +/*! + * \property QItemModelSurfaceDataProxy::columnRolePattern + * + * When set, a search and replace is done on the value mapped by column role before it is used + * as a column category. This property specifies the regular expression to find the portion of the + * mapped value to replace and columnRoleReplace property contains the replacement string. + * + * \sa columnRole, columnRoleReplace + */ +void QItemModelSurfaceDataProxy::setColumnRolePattern(const QRegExp &pattern) +{ + if (dptr()->m_columnRolePattern != pattern) { + dptr()->m_columnRolePattern = pattern; + emit columnRolePatternChanged(pattern); + } +} + +QRegExp QItemModelSurfaceDataProxy::columnRolePattern() const +{ + return dptrc()->m_columnRolePattern; +} + +/*! + * \property QItemModelSurfaceDataProxy::xPosRolePattern + * + * When set, a search and replace is done on the value mapped by xPos role before it is used as + * a item position value. This property specifies the regular expression to find the portion of the + * mapped value to replace and xPosRoleReplace property contains the replacement string. + * + * \sa xPosRole, xPosRoleReplace + */ +void QItemModelSurfaceDataProxy::setXPosRolePattern(const QRegExp &pattern) +{ + if (dptr()->m_xPosRolePattern != pattern) { + dptr()->m_xPosRolePattern = pattern; + emit xPosRolePatternChanged(pattern); + } +} + +QRegExp QItemModelSurfaceDataProxy::xPosRolePattern() const +{ + return dptrc()->m_xPosRolePattern; +} + +/*! + * \property QItemModelSurfaceDataProxy::yPosRolePattern + * + * When set, a search and replace is done on the value mapped by yPos role before it is used as + * a item position value. This property specifies the regular expression to find the portion of the + * mapped value to replace and yPosRoleReplace property contains the replacement string. + * + * \sa yPosRole, yPosRoleReplace + */ +void QItemModelSurfaceDataProxy::setYPosRolePattern(const QRegExp &pattern) +{ + if (dptr()->m_yPosRolePattern != pattern) { + dptr()->m_yPosRolePattern = pattern; + emit yPosRolePatternChanged(pattern); + } +} + +QRegExp QItemModelSurfaceDataProxy::yPosRolePattern() const +{ + return dptrc()->m_yPosRolePattern; +} + +/*! + * \property QItemModelSurfaceDataProxy::zPosRolePattern + * + * When set, a search and replace is done on the value mapped by zPos role before it is used as + * a item position value. This property specifies the regular expression to find the portion of the + * mapped value to replace and zPosRoleReplace property contains the replacement string. + * + * \sa zPosRole, zPosRoleReplace + */ +void QItemModelSurfaceDataProxy::setZPosRolePattern(const QRegExp &pattern) +{ + if (dptr()->m_zPosRolePattern != pattern) { + dptr()->m_zPosRolePattern = pattern; + emit zPosRolePatternChanged(pattern); + } +} + +QRegExp QItemModelSurfaceDataProxy::zPosRolePattern() const +{ + return dptrc()->m_zPosRolePattern; +} + +/*! + * \property QItemModelSurfaceDataProxy::rowRoleReplace + * + * This property defines the replace content to be used in conjunction with rowRolePattern. + * Defaults to empty string. For more information on how the search and replace using regular + * expressions works, see QString::replace(const QRegExp &rx, const QString &after) + * function documentation. + * + * \sa rowRole, rowRolePattern + */ +void QItemModelSurfaceDataProxy::setRowRoleReplace(const QString &replace) +{ + if (dptr()->m_rowRoleReplace != replace) { + dptr()->m_rowRoleReplace = replace; + emit rowRoleReplaceChanged(replace); + } +} + +QString QItemModelSurfaceDataProxy::rowRoleReplace() const +{ + return dptrc()->m_rowRoleReplace; +} + +/*! + * \property QItemModelSurfaceDataProxy::columnRoleReplace + * + * This property defines the replace content to be used in conjunction with columnRolePattern. + * Defaults to empty string. For more information on how the search and replace using regular + * expressions works, see QString::replace(const QRegExp &rx, const QString &after) + * function documentation. + * + * \sa columnRole, columnRolePattern + */ +void QItemModelSurfaceDataProxy::setColumnRoleReplace(const QString &replace) +{ + if (dptr()->m_columnRoleReplace != replace) { + dptr()->m_columnRoleReplace = replace; + emit columnRoleReplaceChanged(replace); + } +} + +QString QItemModelSurfaceDataProxy::columnRoleReplace() const +{ + return dptrc()->m_columnRoleReplace; +} + +/*! + * \property QItemModelSurfaceDataProxy::xPosRoleReplace + * + * This property defines the replace content to be used in conjunction with xPosRolePattern. + * Defaults to empty string. For more information on how the search and replace using regular + * expressions works, see QString::replace(const QRegExp &rx, const QString &after) + * function documentation. + * + * \sa xPosRole, xPosRolePattern + */ +void QItemModelSurfaceDataProxy::setXPosRoleReplace(const QString &replace) +{ + if (dptr()->m_xPosRoleReplace != replace) { + dptr()->m_xPosRoleReplace = replace; + emit xPosRoleReplaceChanged(replace); + } +} + +QString QItemModelSurfaceDataProxy::xPosRoleReplace() const +{ + return dptrc()->m_xPosRoleReplace; +} + +/*! + * \property QItemModelSurfaceDataProxy::yPosRoleReplace + * + * This property defines the replace content to be used in conjunction with yPosRolePattern. + * Defaults to empty string. For more information on how the search and replace using regular + * expressions works, see QString::replace(const QRegExp &rx, const QString &after) + * function documentation. + * + * \sa yPosRole, yPosRolePattern + */ +void QItemModelSurfaceDataProxy::setYPosRoleReplace(const QString &replace) +{ + if (dptr()->m_yPosRoleReplace != replace) { + dptr()->m_yPosRoleReplace = replace; + emit yPosRoleReplaceChanged(replace); + } +} + +QString QItemModelSurfaceDataProxy::yPosRoleReplace() const +{ + return dptrc()->m_yPosRoleReplace; +} + +/*! + * \property QItemModelSurfaceDataProxy::zPosRoleReplace + * + * This property defines the replace content to be used in conjunction with zPosRolePattern. + * Defaults to empty string. For more information on how the search and replace using regular + * expressions works, see QString::replace(const QRegExp &rx, const QString &after) + * function documentation. + * + * \sa zPosRole, zPosRolePattern + */ +void QItemModelSurfaceDataProxy::setZPosRoleReplace(const QString &replace) +{ + if (dptr()->m_zPosRoleReplace != replace) { + dptr()->m_zPosRoleReplace = replace; + emit zPosRoleReplaceChanged(replace); + } +} + +QString QItemModelSurfaceDataProxy::zPosRoleReplace() const +{ + return dptrc()->m_zPosRoleReplace; +} + /*! * \internal */ @@ -621,6 +969,26 @@ void QItemModelSurfaceDataProxyPrivate::connectItemModelHandler() m_itemModelHandler, &AbstractItemModelHandler::handleMappingChanged); QObject::connect(qptr(), &QItemModelSurfaceDataProxy::autoColumnCategoriesChanged, m_itemModelHandler, &AbstractItemModelHandler::handleMappingChanged); + QObject::connect(qptr(), &QItemModelSurfaceDataProxy::rowRolePatternChanged, + m_itemModelHandler, &AbstractItemModelHandler::handleMappingChanged); + QObject::connect(qptr(), &QItemModelSurfaceDataProxy::columnRolePatternChanged, + m_itemModelHandler, &AbstractItemModelHandler::handleMappingChanged); + QObject::connect(qptr(), &QItemModelSurfaceDataProxy::xPosRolePatternChanged, + m_itemModelHandler, &AbstractItemModelHandler::handleMappingChanged); + QObject::connect(qptr(), &QItemModelSurfaceDataProxy::yPosRolePatternChanged, + m_itemModelHandler, &AbstractItemModelHandler::handleMappingChanged); + QObject::connect(qptr(), &QItemModelSurfaceDataProxy::zPosRolePatternChanged, + m_itemModelHandler, &AbstractItemModelHandler::handleMappingChanged); + QObject::connect(qptr(), &QItemModelSurfaceDataProxy::rowRoleReplaceChanged, + m_itemModelHandler, &AbstractItemModelHandler::handleMappingChanged); + QObject::connect(qptr(), &QItemModelSurfaceDataProxy::columnRoleReplaceChanged, + m_itemModelHandler, &AbstractItemModelHandler::handleMappingChanged); + QObject::connect(qptr(), &QItemModelSurfaceDataProxy::xPosRoleReplaceChanged, + m_itemModelHandler, &AbstractItemModelHandler::handleMappingChanged); + QObject::connect(qptr(), &QItemModelSurfaceDataProxy::yPosRoleReplaceChanged, + m_itemModelHandler, &AbstractItemModelHandler::handleMappingChanged); + QObject::connect(qptr(), &QItemModelSurfaceDataProxy::zPosRoleReplaceChanged, + m_itemModelHandler, &AbstractItemModelHandler::handleMappingChanged); } QT_END_NAMESPACE_DATAVISUALIZATION diff --git a/src/datavisualization/data/qitemmodelsurfacedataproxy.h b/src/datavisualization/data/qitemmodelsurfacedataproxy.h index b1ebbeed..8fe736f5 100644 --- a/src/datavisualization/data/qitemmodelsurfacedataproxy.h +++ b/src/datavisualization/data/qitemmodelsurfacedataproxy.h @@ -22,6 +22,7 @@ #include #include #include +#include QT_BEGIN_NAMESPACE_DATAVISUALIZATION @@ -41,6 +42,16 @@ class QT_DATAVISUALIZATION_EXPORT QItemModelSurfaceDataProxy : public QSurfaceDa Q_PROPERTY(bool useModelCategories READ useModelCategories WRITE setUseModelCategories NOTIFY useModelCategoriesChanged) Q_PROPERTY(bool autoRowCategories READ autoRowCategories WRITE setAutoRowCategories NOTIFY autoRowCategoriesChanged) Q_PROPERTY(bool autoColumnCategories READ autoColumnCategories WRITE setAutoColumnCategories NOTIFY autoColumnCategoriesChanged) + Q_PROPERTY(QRegExp rowRolePattern READ rowRolePattern WRITE setRowRolePattern NOTIFY rowRolePatternChanged REVISION 1) + Q_PROPERTY(QRegExp columnRolePattern READ columnRolePattern WRITE setColumnRolePattern NOTIFY columnRolePatternChanged REVISION 1) + Q_PROPERTY(QRegExp xPosRolePattern READ xPosRolePattern WRITE setXPosRolePattern NOTIFY xPosRolePatternChanged REVISION 1) + Q_PROPERTY(QRegExp yPosRolePattern READ yPosRolePattern WRITE setYPosRolePattern NOTIFY yPosRolePatternChanged REVISION 1) + Q_PROPERTY(QRegExp zPosRolePattern READ zPosRolePattern WRITE setZPosRolePattern NOTIFY zPosRolePatternChanged REVISION 1) + Q_PROPERTY(QString rowRoleReplace READ rowRoleReplace WRITE setRowRoleReplace NOTIFY rowRoleReplaceChanged REVISION 1) + Q_PROPERTY(QString columnRoleReplace READ columnRoleReplace WRITE setColumnRoleReplace NOTIFY columnRoleReplaceChanged REVISION 1) + Q_PROPERTY(QString xPosRoleReplace READ xPosRoleReplace WRITE setXPosRoleReplace NOTIFY xPosRoleReplaceChanged REVISION 1) + Q_PROPERTY(QString yPosRoleReplace READ yPosRoleReplace WRITE setYPosRoleReplace NOTIFY yPosRoleReplaceChanged REVISION 1) + Q_PROPERTY(QString zPosRoleReplace READ zPosRoleReplace WRITE setZPosRoleReplace NOTIFY zPosRoleReplaceChanged REVISION 1) public: explicit QItemModelSurfaceDataProxy(QObject *parent = 0); @@ -99,6 +110,28 @@ public: Q_INVOKABLE int rowCategoryIndex(const QString& category); Q_INVOKABLE int columnCategoryIndex(const QString& category); + void setRowRolePattern(const QRegExp &pattern); + QRegExp rowRolePattern() const; + void setColumnRolePattern(const QRegExp &pattern); + QRegExp columnRolePattern() const; + void setXPosRolePattern(const QRegExp &pattern); + QRegExp xPosRolePattern() const; + void setYPosRolePattern(const QRegExp &pattern); + QRegExp yPosRolePattern() const; + void setZPosRolePattern(const QRegExp &pattern); + QRegExp zPosRolePattern() const; + + void setRowRoleReplace(const QString &replace); + QString rowRoleReplace() const; + void setColumnRoleReplace(const QString &replace); + QString columnRoleReplace() const; + void setXPosRoleReplace(const QString &replace); + QString xPosRoleReplace() const; + void setYPosRoleReplace(const QString &replace); + QString yPosRoleReplace() const; + void setZPosRoleReplace(const QString &replace); + QString zPosRoleReplace() const; + signals: void itemModelChanged(const QAbstractItemModel* itemModel); void rowRoleChanged(const QString &role); @@ -111,6 +144,16 @@ signals: void useModelCategoriesChanged(bool enable); void autoRowCategoriesChanged(bool enable); void autoColumnCategoriesChanged(bool enable); + Q_REVISION(1) void rowRolePatternChanged(const QRegExp &pattern); + Q_REVISION(1) void columnRolePatternChanged(const QRegExp &pattern); + Q_REVISION(1) void xPosRolePatternChanged(const QRegExp &pattern); + Q_REVISION(1) void yPosRolePatternChanged(const QRegExp &pattern); + Q_REVISION(1) void zPosRolePatternChanged(const QRegExp &pattern); + Q_REVISION(1) void rowRoleReplaceChanged(const QString &replace); + Q_REVISION(1) void columnRoleReplaceChanged(const QString &replace); + Q_REVISION(1) void xPosRoleReplaceChanged(const QString &replace); + Q_REVISION(1) void yPosRoleReplaceChanged(const QString &replace); + Q_REVISION(1) void zPosRoleReplaceChanged(const QString &replace); protected: QItemModelSurfaceDataProxyPrivate *dptr(); diff --git a/src/datavisualization/data/qitemmodelsurfacedataproxy_p.h b/src/datavisualization/data/qitemmodelsurfacedataproxy_p.h index 0aaea8fd..06bfe2a1 100644 --- a/src/datavisualization/data/qitemmodelsurfacedataproxy_p.h +++ b/src/datavisualization/data/qitemmodelsurfacedataproxy_p.h @@ -64,6 +64,18 @@ private: bool m_autoRowCategories; bool m_autoColumnCategories; + QRegExp m_rowRolePattern; + QRegExp m_columnRolePattern; + QRegExp m_xPosRolePattern; + QRegExp m_yPosRolePattern; + QRegExp m_zPosRolePattern; + + QString m_rowRoleReplace; + QString m_columnRoleReplace; + QString m_xPosRoleReplace; + QString m_yPosRoleReplace; + QString m_zPosRoleReplace; + friend class SurfaceItemModelHandler; friend class QItemModelSurfaceDataProxy; }; diff --git a/src/datavisualization/data/qsurfacedataproxy.cpp b/src/datavisualization/data/qsurfacedataproxy.cpp index f8f2c900..058b0e21 100644 --- a/src/datavisualization/data/qsurfacedataproxy.cpp +++ b/src/datavisualization/data/qsurfacedataproxy.cpp @@ -521,10 +521,14 @@ void QSurfaceDataProxyPrivate::limitValues(QVector3D &minValues, QVector3D &maxV minValues.setY(min); maxValues.setY(max); if (columns) { - minValues.setX(m_dataArray->at(0)->at(0).x()); - minValues.setZ(m_dataArray->at(0)->at(0).z()); - maxValues.setX(m_dataArray->at(0)->last().x()); - maxValues.setZ(m_dataArray->last()->at(0).z()); + float xLow = m_dataArray->at(0)->at(0).x(); + float xHigh = m_dataArray->at(0)->last().x(); + float zLow = m_dataArray->at(0)->at(0).z(); + float zHigh = m_dataArray->last()->at(0).z(); + minValues.setX(qMin(xLow, xHigh)); + minValues.setZ(qMin(zLow, zHigh)); + maxValues.setX(qMax(xLow, xHigh)); + maxValues.setZ(qMax(zLow, zHigh)); } else { minValues.setX(0.0f); minValues.setZ(0.0f); diff --git a/src/datavisualization/data/surfaceitemmodelhandler.cpp b/src/datavisualization/data/surfaceitemmodelhandler.cpp index 584ddf28..fad02464 100644 --- a/src/datavisualization/data/surfaceitemmodelhandler.cpp +++ b/src/datavisualization/data/surfaceitemmodelhandler.cpp @@ -28,7 +28,10 @@ SurfaceItemModelHandler::SurfaceItemModelHandler(QItemModelSurfaceDataProxy *pro m_proxyArray(0), m_xPosRole(noRoleIndex), m_yPosRole(noRoleIndex), - m_zPosRole(noRoleIndex) + m_zPosRole(noRoleIndex), + m_haveXPosPattern(false), + m_haveYPosPattern(false), + m_haveZPosPattern(false) { } @@ -53,21 +56,38 @@ void SurfaceItemModelHandler::handleDataChanged(const QModelIndex &topLeft, for (int i = startRow; i <= endRow; i++) { for (int j = startCol; j <= endCol; j++) { + QModelIndex index = m_itemModel->index(i, j); QSurfaceDataItem item; + QVariant xValueVar = index.data(m_xPosRole); + QVariant yValueVar = index.data(m_yPosRole); + QVariant zValueVar = index.data(m_zPosRole); const QSurfaceDataItem *oldItem = m_proxy->itemAt(i, j); float xPos; + float yPos; float zPos; - if (m_xPosRole != noRoleIndex) - xPos = m_itemModel->index(i, j).data(m_xPosRole).toFloat(); - else + if (m_xPosRole != noRoleIndex) { + if (m_haveXPosPattern) + xPos = xValueVar.toString().replace(m_xPosPattern, m_xPosReplace).toFloat(); + else + xPos = xValueVar.toFloat(); + } else { xPos = oldItem->x(); - if (m_zPosRole != noRoleIndex) - zPos = m_itemModel->index(i, j).data(m_zPosRole).toFloat(); + } + + if (m_haveYPosPattern) + yPos = yValueVar.toString().replace(m_yPosPattern, m_yPosReplace).toFloat(); else + yPos = yValueVar.toFloat(); + + if (m_zPosRole != noRoleIndex) { + if (m_haveZPosPattern) + zPos = zValueVar.toString().replace(m_zPosPattern, m_zPosReplace).toFloat(); + else + zPos = zValueVar.toFloat(); + } else { zPos = oldItem->z(); - item.setPosition(QVector3D(xPos, - m_itemModel->index(i, j).data(m_yPosRole).toFloat(), - zPos)); + } + item.setPosition(QVector3D(xPos, yPos, zPos)); m_proxy->setItem(i, j, item); } } @@ -91,6 +111,23 @@ void SurfaceItemModelHandler::resolveModel() return; } + // Position patterns can be reused on single item changes, so store them to member variables. + QRegExp rowPattern(m_proxy->rowRolePattern()); + QRegExp colPattern(m_proxy->columnRolePattern()); + m_xPosPattern = m_proxy->xPosRolePattern(); + m_yPosPattern = m_proxy->yPosRolePattern(); + m_zPosPattern = m_proxy->zPosRolePattern(); + QString rowReplace = m_proxy->rowRoleReplace(); + QString colReplace = m_proxy->columnRoleReplace(); + m_xPosReplace = m_proxy->xPosRoleReplace(); + m_yPosReplace = m_proxy->yPosRoleReplace(); + m_zPosReplace = m_proxy->zPosRoleReplace(); + bool haveRowPattern = !rowPattern.isEmpty() && rowPattern.isValid(); + bool haveColPattern = !colPattern.isEmpty() && colPattern.isValid(); + m_haveXPosPattern = !m_xPosPattern.isEmpty() && m_xPosPattern.isValid(); + m_haveYPosPattern = !m_yPosPattern.isEmpty() && m_yPosPattern.isValid(); + m_haveZPosPattern = !m_zPosPattern.isEmpty() && m_zPosPattern.isValid(); + QHash roleHash = m_itemModel->roleNames(); // Default to display role if no mapping @@ -112,32 +149,49 @@ void SurfaceItemModelHandler::resolveModel() for (int i = 0; i < rowCount; i++) { QSurfaceDataRow &newProxyRow = *m_proxyArray->at(i); for (int j = 0; j < columnCount; j++) { - float xPos = float(j); - float zPos = float(i); + QModelIndex index = m_itemModel->index(i, j); + QVariant xValueVar = index.data(m_xPosRole); + QVariant yValueVar = index.data(m_yPosRole); + QVariant zValueVar = index.data(m_zPosRole); + float xPos; + float yPos; + float zPos; if (m_xPosRole != noRoleIndex) { - xPos = m_itemModel->index(i, j).data(m_xPosRole).toFloat(); + if (m_haveXPosPattern) + xPos = xValueVar.toString().replace(m_xPosPattern, m_xPosReplace).toFloat(); + else + xPos = xValueVar.toFloat(); } else { QString header = m_itemModel->headerData(j, Qt::Horizontal).toString(); bool ok = false; float headerValue = header.toFloat(&ok); if (ok) xPos = headerValue; + else + xPos = float(j); } + if (m_haveYPosPattern) + yPos = yValueVar.toString().replace(m_yPosPattern, m_yPosReplace).toFloat(); + else + yPos = yValueVar.toFloat(); + if (m_zPosRole != noRoleIndex) { - zPos = m_itemModel->index(i, j).data(m_zPosRole).toFloat(); + if (m_haveZPosPattern) + zPos = zValueVar.toString().replace(m_zPosPattern, m_zPosReplace).toFloat(); + else + zPos = zValueVar.toFloat(); } else { QString header = m_itemModel->headerData(i, Qt::Vertical).toString(); bool ok = false; float headerValue = header.toFloat(&ok); if (ok) zPos = headerValue; + else + zPos = float(i); } - newProxyRow[j].setPosition( - QVector3D(xPos, - m_itemModel->index(i, j).data(m_yPosRole).toFloat(), - zPos)); + newProxyRow[j].setPosition(QVector3D(xPos, yPos, zPos)); } } } else { @@ -165,10 +219,31 @@ void SurfaceItemModelHandler::resolveModel() for (int j = 0; j < columnCount; j++) { QModelIndex index = m_itemModel->index(i, j); QString rowRoleStr = index.data(rowRole).toString(); + if (haveRowPattern) + rowRoleStr.replace(rowPattern, rowReplace); QString columnRoleStr = index.data(columnRole).toString(); - QVector3D itemPos(index.data(m_xPosRole).toFloat(), - index.data(m_yPosRole).toFloat(), - index.data(m_zPosRole).toFloat()); + if (haveColPattern) + columnRoleStr.replace(colPattern, colReplace); + QVariant xValueVar = index.data(m_xPosRole); + QVariant yValueVar = index.data(m_yPosRole); + QVariant zValueVar = index.data(m_zPosRole); + float xPos; + float yPos; + float zPos; + if (m_haveXPosPattern) + xPos = xValueVar.toString().replace(m_xPosPattern, m_xPosReplace).toFloat(); + else + xPos = xValueVar.toFloat(); + if (m_haveYPosPattern) + yPos = yValueVar.toString().replace(m_yPosPattern, m_yPosReplace).toFloat(); + else + yPos = yValueVar.toFloat(); + if (m_haveZPosPattern) + zPos = zValueVar.toString().replace(m_zPosPattern, m_zPosReplace).toFloat(); + else + zPos = zValueVar.toFloat(); + + QVector3D itemPos(xPos, yPos, zPos); itemValueMap[rowRoleStr][columnRoleStr] = itemPos; if (generateRows && !rowListHash.value(rowRoleStr, false)) { rowListHash.insert(rowRoleStr, true); diff --git a/src/datavisualization/data/surfaceitemmodelhandler_p.h b/src/datavisualization/data/surfaceitemmodelhandler_p.h index dbed0a60..572788d6 100644 --- a/src/datavisualization/data/surfaceitemmodelhandler_p.h +++ b/src/datavisualization/data/surfaceitemmodelhandler_p.h @@ -53,6 +53,15 @@ protected: int m_xPosRole; int m_yPosRole; int m_zPosRole; + QRegExp m_xPosPattern; + QRegExp m_yPosPattern; + QRegExp m_zPosPattern; + QString m_xPosReplace; + QString m_yPosReplace; + QString m_zPosReplace; + bool m_haveXPosPattern; + bool m_haveYPosPattern; + bool m_haveZPosPattern; }; QT_END_NAMESPACE_DATAVISUALIZATION diff --git a/src/datavisualizationqml2/datavisualizationqml2_plugin.cpp b/src/datavisualizationqml2/datavisualizationqml2_plugin.cpp index d419d904..09afb6b1 100644 --- a/src/datavisualizationqml2/datavisualizationqml2_plugin.cpp +++ b/src/datavisualizationqml2/datavisualizationqml2_plugin.cpp @@ -93,6 +93,7 @@ void QtDataVisualizationQml2Plugin::registerTypes(const char *uri) qmlRegisterUncreatableType(uri, 1, 1, "AbstractGraph3D", QLatin1String("Trying to create uncreatable: AbstractGraph3D.")); qmlRegisterType(uri, 1, 1, "ItemModelBarDataProxy"); + qmlRegisterType(uri, 1, 1, "ItemModelSurfaceDataProxy"); // New types qmlRegisterType(uri, 1, 1, "ValueAxis3DFormatter"); diff --git a/tests/itemmodeltest/main.cpp b/tests/itemmodeltest/main.cpp index a607fe8d..38454948 100644 --- a/tests/itemmodeltest/main.cpp +++ b/tests/itemmodeltest/main.cpp @@ -49,9 +49,6 @@ public: void setupModel(); void addRow(); - void changeStyle(); - void changePresetCamera(); - void changeTheme(); void start(); void selectFromTable(const QPoint &selection); void selectedFromTable(int currentRow, int currentColumn, int previousRow, int previousColumn); @@ -148,12 +145,14 @@ void GraphDataGenerator::setupModel() QStringList weeks; weeks << "week 1" << "week 2" << "week 3" << "week 4" << "week 5"; - // Set up data Mon Tue Wed Thu Fri Sat Sun - const char *hours[5][7] = {{"2.0/30", "1.0/30", "3.0/30", "0.2/30", "1.0/30", "5.0/30", "10.0/30"}, // week 1 - {"0.5/45", "1.0/45", "3.0/45", "1.0/45", "2.0/45", "2.0/45", "3.0/45"}, // week 2 - {"1.0/60", "1.0/60", "2.0/60", "1.0/60", "4.0/60", "4.0/60", "4.0/60"}, // week 3 - {"0.0/75", "1.0/75", "0.0/75", "0.0/75", "2.0/75", "2.0/75", "0.3/75"}, // week 4 - {"3.0/90", "3.0/90", "6.0/90", "2.0/90", "2.0/90", "1.0/90", "1.0/90"}}; // week 5 + // Set up data + const char *hours[5][7] = + // Mon Tue Wed Thu Fri Sat Sun + {{"9/10/2.0/30", "9/11/1.0/30", "9/12/3.0/30", "9/13/0.2/30", "9/14/1.0/30", "9/15/5.0/30", "9/16/10.0/30"}, // week 1 + {"8/10/0.5/45", "8/11/1.0/45", "8/12/3.0/45", "8/13/1.0/45", "8/14/2.0/45", "8/15/2.0/45", "8/16/3.0/45"}, // week 2 + {"7/10/1.0/60", "7/11/1.0/60", "7/12/2.0/60", "7/13/1.0/60", "7/14/4.0/60", "7/15/4.0/60", "7/16/4.0/60"}, // week 3 + {"6/10/0.0/75", "6/11/1.0/75", "6/12/0.0/75", "6/13/0.0/75", "6/14/2.0/75", "6/15/2.0/75", "6/16/0.3/75"}, // week 4 + {"5/10/3.0/90", "5/11/3.0/90", "5/12/6.0/90", "5/13/2.0/90", "5/14/2.0/90", "5/15/1.0/90", "5/16/1.0/90"}}; // week 5 // Add labels m_barGraph->rowAxis()->setTitle("Week of year"); @@ -275,17 +274,27 @@ int main(int argc, char **argv) barProxy->setUseModelCategories(true); surfaceProxy->setUseModelCategories(true); barProxy->setRotationRole(tableWidget->model()->roleNames().value(Qt::DisplayRole)); - barProxy->setValueRolePattern(QRegExp(QStringLiteral("^(\\d*[\\.\\,]?\\d*)\\/(\\d*[\\.\\,]?\\d*)$"))); - barProxy->setRotationRolePattern(QRegExp(QStringLiteral("^(\\d*[\\.\\,]?\\d*)\\/(\\d*[\\.\\,]?\\d*)$"))); - barProxy->setValueRoleReplace(QStringLiteral("\\1")); - barProxy->setRotationRoleReplace(QStringLiteral("\\2")); - // TODO surface proxy test + barProxy->setValueRolePattern(QRegExp(QStringLiteral("^(\\d*)(\\/)(\\d*)\\/(\\d*[\\.\\,]?\\d*)\\/\\d*[\\.\\,]?\\d*$"))); + barProxy->setRotationRolePattern(QRegExp(QStringLiteral("^(\\d*)(\\/)\\d*\\/\\d*([\\.\\,]?)\\d*(\\/)(\\d*[\\.\\,]?\\d*)$"))); + barProxy->setValueRoleReplace(QStringLiteral("\\4")); + barProxy->setRotationRoleReplace(QStringLiteral("\\5")); + surfaceProxy->setXPosRole(tableWidget->model()->roleNames().value(Qt::DisplayRole)); + surfaceProxy->setZPosRole(tableWidget->model()->roleNames().value(Qt::DisplayRole)); + surfaceProxy->setXPosRolePattern(QRegExp(QStringLiteral("^(\\d*)\\/(\\d*)\\/\\d*[\\.\\,]?\\d*\\/\\d*[\\.\\,]?\\d*$"))); + surfaceProxy->setXPosRoleReplace(QStringLiteral("\\2")); + surfaceProxy->setYPosRolePattern(QRegExp(QStringLiteral("^\\d*(\\/)(\\d*)\\/(\\d*[\\.\\,]?\\d*)\\/\\d*[\\.\\,]?\\d*$"))); + surfaceProxy->setYPosRoleReplace(QStringLiteral("\\3")); + surfaceProxy->setZPosRolePattern(QRegExp(QStringLiteral("^(\\d*)(\\/)(\\d*)\\/\\d*[\\.\\,]?\\d*\\/\\d*[\\.\\,]?\\d*$"))); + surfaceProxy->setZPosRoleReplace(QStringLiteral("\\1")); QBar3DSeries *barSeries = new QBar3DSeries(barProxy); QSurface3DSeries *surfaceSeries = new QSurface3DSeries(surfaceProxy); barSeries->setMesh(QAbstract3DSeries::MeshPyramid); barGraph->addSeries(barSeries); surfaceGraph->addSeries(surfaceSeries); + barGraph->scene()->activeCamera()->setCameraPreset(Q3DCamera::CameraPresetBehind); + surfaceGraph->scene()->activeCamera()->setCameraPreset(Q3DCamera::CameraPresetFront); + GraphDataGenerator generator(barGraph, surfaceGraph, tableWidget); QObject::connect(barSeries, &QBar3DSeries::selectedBarChanged, &generator, &GraphDataGenerator::selectFromTable); diff --git a/tests/qmlmultitest/main.cpp b/tests/qmlmultitest/main.cpp new file mode 100644 index 00000000..a4754f56 --- /dev/null +++ b/tests/qmlmultitest/main.cpp @@ -0,0 +1,47 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVisualization module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +#include +#include +#include +#include + +int main(int argc, char *argv[]) +{ + QGuiApplication app(argc, argv); + + QQuickView viewer; + + // The following are needed to make examples run without having to install the module + // in desktop environments. +#ifdef Q_OS_WIN + QString extraImportPath(QStringLiteral("%1/../../../%2")); +#else + QString extraImportPath(QStringLiteral("%1/../../%2")); +#endif + viewer.engine()->addImportPath(extraImportPath.arg(QGuiApplication::applicationDirPath(), + QString::fromLatin1("qml"))); + QObject::connect(viewer.engine(), &QQmlEngine::quit, &viewer, &QWindow::close); + + viewer.setTitle(QStringLiteral("QML multitest")); + viewer.setSource(QUrl("qrc:/qml/qmlmultitest/main.qml")); + viewer.setResizeMode(QQuickView::SizeRootObjectToView); + viewer.show(); + + return app.exec(); +} diff --git a/tests/qmlmultitest/qml/qmlmultitest/Data.qml b/tests/qmlmultitest/qml/qmlmultitest/Data.qml new file mode 100644 index 00000000..ddc0aad8 --- /dev/null +++ b/tests/qmlmultitest/qml/qmlmultitest/Data.qml @@ -0,0 +1,48 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVisualization module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +import QtQuick 2.1 + +Item { + property alias sharedData: dataModel + + ListModel { + id: dataModel + ListElement{ coords: "0,0"; data: "20.0/10.0/4.75"; } + ListElement{ coords: "1,0"; data: "21.1/10.3/3.00"; } + ListElement{ coords: "2,0"; data: "22.5/10.7/1.24"; } + ListElement{ coords: "3,0"; data: "24.0/10.5/2.53"; } + ListElement{ coords: "0,1"; data: "20.2/11.2/3.55"; } + ListElement{ coords: "1,1"; data: "21.3/11.5/3.03"; } + ListElement{ coords: "2,1"; data: "22.6/11.7/3.46"; } + ListElement{ coords: "3,1"; data: "23.4/11.5/4.12"; } + ListElement{ coords: "0,2"; data: "20.2/12.3/3.37"; } + ListElement{ coords: "1,2"; data: "21.1/12.4/2.98"; } + ListElement{ coords: "2,2"; data: "22.5/12.1/3.33"; } + ListElement{ coords: "3,2"; data: "23.3/12.7/3.23"; } + ListElement{ coords: "0,3"; data: "20.7/13.3/5.34"; } + ListElement{ coords: "1,3"; data: "21.5/13.2/4.54"; } + ListElement{ coords: "2,3"; data: "22.4/13.6/4.65"; } + ListElement{ coords: "3,3"; data: "23.2/13.4/6.67"; } + ListElement{ coords: "0,4"; data: "20.6/15.0/6.01"; } + ListElement{ coords: "1,4"; data: "21.3/14.6/5.83"; } + ListElement{ coords: "2,4"; data: "22.5/14.8/7.32"; } + ListElement{ coords: "3,4"; data: "23.7/14.3/6.90"; } + } +} + diff --git a/tests/qmlmultitest/qml/qmlmultitest/NewButton.qml b/tests/qmlmultitest/qml/qmlmultitest/NewButton.qml new file mode 100644 index 00000000..e4fb99d2 --- /dev/null +++ b/tests/qmlmultitest/qml/qmlmultitest/NewButton.qml @@ -0,0 +1,52 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVisualization module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +import QtQuick 2.1 +import QtQuick.Controls 1.0 +import QtQuick.Controls.Styles 1.0 + +Item { + id: newbutton + + property alias text: buttonText.text + + signal clicked + + implicitWidth: buttonText.implicitWidth + 5 + implicitHeight: buttonText.implicitHeight + 10 + + Button { + id: buttonText + width: parent.width + height: parent.height + + style: ButtonStyle { + label: Component { + Text { + text: buttonText.text + clip: true + wrapMode: Text.WordWrap + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + anchors.fill: parent + } + } + } + onClicked: newbutton.clicked() + } +} diff --git a/tests/qmlmultitest/qml/qmlmultitest/main.qml b/tests/qmlmultitest/qml/qmlmultitest/main.qml new file mode 100644 index 00000000..da34c0bf --- /dev/null +++ b/tests/qmlmultitest/qml/qmlmultitest/main.qml @@ -0,0 +1,231 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use contact form at http://qt.digia.com +** +** This file is part of the QtDataVisualization module. +** +** Licensees holding valid Qt Enterprise licenses may use this file in +** accordance with the Qt Enterprise License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. +** +** If you have questions regarding the use of this file, please use +** contact form at http://qt.digia.com +** +****************************************************************************/ + +import QtQuick 2.1 +import QtQuick.Layouts 1.0 +import QtDataVisualization 1.1 +import "." + +Rectangle { + id: mainView + width: 800 + height: 600 + + Data { + id: data + } + + GridLayout { + id: gridLayout + columns: 2 + Layout.fillHeight: true + Layout.fillWidth: true + anchors.top: mainView.top + anchors.bottom: mainView.bottom + anchors.left: mainView.left + anchors.right: mainView.right + + Rectangle { + Layout.fillHeight: true + Layout.fillWidth: true + border.color: surfaceGraph.theme.gridLineColor + border.width: 2 + + Surface3D { + id: surfaceGraph + anchors.fill: parent + anchors.margins: parent.border.width + theme: Theme3D { + type: Theme3D.ThemePrimaryColors + font.pointSize: 60 + } + scene.activeCamera.cameraPreset: Camera3D.CameraPresetIsometricLeftHigh + + Surface3DSeries { + itemLabelFormat: "Pop density at (@xLabel N, @zLabel E): @yLabel" + ItemModelSurfaceDataProxy { + itemModel: data.sharedData + // The surface data points are not neatly lined up in rows and columns, + // so we define explicit row and column roles. + rowRole: "coords" + columnRole: "coords" + xPosRole: "data" + zPosRole: "data" + yPosRole: "data" + rowRolePattern: /(\d),\d/ + columnRolePattern: /(\d),(\d)/ + xPosRolePattern: /^([asd]*)([fgh]*)([jkl]*)[^\/]*\/([^\/]*)\/.*$/ + yPosRolePattern: /^([^\/]*)\/([^\/]*)\/(.*)$/ + zPosRolePattern: /^([asd]*)([qwe]*)([tyu]*)([fgj]*)([^\/]*)\/[^\/]*\/.*$/ + rowRoleReplace: "\\1" + columnRoleReplace: "\\2" + xPosRoleReplace: "\\4" + yPosRoleReplace: "\\3" + zPosRoleReplace: "\\5" + } + } + } + } + + // We'll use one grid cell for buttons + Rectangle { + Layout.fillHeight: true + Layout.fillWidth: true + + GridLayout { + anchors.right: parent.right + anchors.left: parent.left + anchors.top: parent.top + anchors.bottom: parent.bottom + columns: 2 + + NewButton { + Layout.minimumWidth: parent.width / 2 + Layout.fillHeight: true + Layout.fillWidth: true + text: "Clear Selections" + onClicked: clearSelections() // call a helper function to keep button itself simpler + } + + NewButton { + Layout.minimumWidth: parent.width / 2 + Layout.fillHeight: true + Layout.fillWidth: true + text: "Quit" + onClicked: Qt.quit(0); + } + + NewButton { + Layout.fillHeight: true + Layout.fillWidth: true + text: "Reset Cameras" + onClicked: resetCameras() // call a helper function to keep button itself simpler + } + + NewButton { + Layout.fillHeight: true + Layout.fillWidth: true + text: "Toggle Mesh Styles" + onClicked: toggleMeshStyle() // call a helper function to keep button itself simpler + } + } + } + + Rectangle { + Layout.fillHeight: true + Layout.fillWidth: true + border.color: scatterGraph.theme.gridLineColor + border.width: 2 + + Scatter3D { + id: scatterGraph + anchors.fill: parent + anchors.margins: parent.border.width + theme: Theme3D { + type: Theme3D.ThemeDigia + font.pointSize: 60 + } + scene.activeCamera.cameraPreset: Camera3D.CameraPresetIsometricLeftHigh + + Scatter3DSeries { + itemLabelFormat: "Pop density at (@xLabel N, @zLabel E): @yLabel" + ItemModelScatterDataProxy { + itemModel: data.sharedData + // Mapping model roles to scatter series item coordinates. + xPosRole: "data" + zPosRole: "data" + yPosRole: "data" + // TODO scatter test +// xPosRolePattern: /^([asd]*)([fgh]*)([jkl]*)[^\/]*\/([^\/]*)\/.*$/ +// yPosRolePattern: /^([^\/]*)\/([^\/]*)\/(.*)$/ +// zPosRolePattern: /^([asd]*)([qwe]*)([tyu]*)([fgj]*)([^\/]*)\/[^\/]*\/.*$/ +// xPosRoleReplace: "\\4" +// yPosRoleReplace: "\\3" +// zPosRoleReplace: "\\5" + } + } + } + } + + Rectangle { + Layout.fillHeight: true + Layout.fillWidth: true + border.color: barGraph.theme.gridLineColor + border.width: 2 + + Bars3D { + id: barGraph + anchors.fill: parent + anchors.margins: parent.border.width + theme: Theme3D { + type: Theme3D.ThemeQt + font.pointSize: 60 + } + selectionMode: AbstractGraph3D.SelectionItemAndRow | AbstractGraph3D.SelectionSlice + scene.activeCamera.cameraPreset: Camera3D.CameraPresetIsometricLeftHigh + + Bar3DSeries { + itemLabelFormat: "@seriesName: @valueLabel" + name: "Population density" + + ItemModelBarDataProxy { + itemModel: data.sharedData + // Mapping model roles to bar series rows, columns, and values. + rowRole: "coords" + columnRole: "coords" + valueRole: "data" + rowRolePattern: /(\d),\d/ + columnRolePattern: /(\d),(\d)/ + valueRolePattern: /^([^\/]*)\/([^\/]*)\/(.*)$/ + rowRoleReplace: "\\1" + columnRoleReplace: "\\2" + valueRoleReplace: "\\3" + } + } + } + } + } + + function clearSelections() { + barGraph.clearSelection() + scatterGraph.clearSelection() + surfaceGraph.clearSelection() + } + + function resetCameras() { + surfaceGraph.scene.activeCamera.cameraPreset = Camera3D.CameraPresetIsometricLeftHigh + scatterGraph.scene.activeCamera.cameraPreset = Camera3D.CameraPresetIsometricLeftHigh + barGraph.scene.activeCamera.cameraPreset = Camera3D.CameraPresetIsometricLeftHigh + surfaceGraph.scene.activeCamera.zoomLevel = 100.0 + scatterGraph.scene.activeCamera.zoomLevel = 100.0 + barGraph.scene.activeCamera.zoomLevel = 100.0 + } + + function toggleMeshStyle() { + if (barGraph.seriesList[0].meshSmooth === true) { + barGraph.seriesList[0].meshSmooth = false + if (surfaceGraph.seriesList[0].flatShadingSupported) + surfaceGraph.seriesList[0].flatShadingEnabled = true + scatterGraph.seriesList[0].meshSmooth = false + } else { + barGraph.seriesList[0].meshSmooth = true + surfaceGraph.seriesList[0].flatShadingEnabled = false + scatterGraph.seriesList[0].meshSmooth = true + } + } +} diff --git a/tests/qmlmultitest/qmlmultitest.pro b/tests/qmlmultitest/qmlmultitest.pro new file mode 100644 index 00000000..6e5e1b98 --- /dev/null +++ b/tests/qmlmultitest/qmlmultitest.pro @@ -0,0 +1,12 @@ +!include( ../tests.pri ) { + error( "Couldn't find the tests.pri file!" ) +} + +# The .cpp file which was generated for your project. Feel free to hack it. +SOURCES += main.cpp + +RESOURCES += qmlmultitest.qrc + +OTHER_FILES += doc/src/* \ + doc/images/* \ + qml/qmlmultitest/* diff --git a/tests/qmlmultitest/qmlmultitest.qrc b/tests/qmlmultitest/qmlmultitest.qrc new file mode 100644 index 00000000..7fc9ade2 --- /dev/null +++ b/tests/qmlmultitest/qmlmultitest.qrc @@ -0,0 +1,7 @@ + + + qml/qmlmultitest/Data.qml + qml/qmlmultitest/main.qml + qml/qmlmultitest/NewButton.qml + + diff --git a/tests/tests.pro b/tests/tests.pro index 7b690c7d..8bbdc3f2 100644 --- a/tests/tests.pro +++ b/tests/tests.pro @@ -15,7 +15,8 @@ SUBDIRS += barstest \ multigraphs \ directional \ qmlmultiwindow \ - itemmodeltest + itemmodeltest \ + qmlmultitest #SUBDIRS += kinectsurface -- cgit v1.2.3