diff options
Diffstat (limited to 'src/datavisualization/data')
62 files changed, 7529 insertions, 0 deletions
diff --git a/src/datavisualization/data/abstractitemmodelhandler.cpp b/src/datavisualization/data/abstractitemmodelhandler.cpp new file mode 100644 index 00000000..0ad0ac0b --- /dev/null +++ b/src/datavisualization/data/abstractitemmodelhandler.cpp @@ -0,0 +1,250 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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 "abstractitemmodelhandler_p.h" +#include "qabstractdatamapping.h" +#include <QTimer> + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +AbstractItemModelHandler::AbstractItemModelHandler(QObject *parent) + : QObject(parent), + m_activeMapping(0), + resolvePending(0) +{ + m_resolveTimer.setSingleShot(true); + QObject::connect(&m_resolveTimer, &QTimer::timeout, + this, &AbstractItemModelHandler::handlePendingResolve); +} + +AbstractItemModelHandler::~AbstractItemModelHandler() +{ +} + +void AbstractItemModelHandler::setItemModel(const QAbstractItemModel *itemModel) +{ + if (!m_itemModel.isNull()) + QObject::disconnect(m_itemModel, 0, this, 0); + + m_itemModel = itemModel; + + if (!m_itemModel.isNull()) { + QObject::connect(m_itemModel.data(), &QAbstractItemModel::columnsInserted, + this, &AbstractItemModelHandler::handleColumnsInserted); + QObject::connect(m_itemModel.data(), &QAbstractItemModel::columnsMoved, + this, &AbstractItemModelHandler::handleColumnsMoved); + QObject::connect(m_itemModel.data(), &QAbstractItemModel::columnsRemoved, + this, &AbstractItemModelHandler::handleColumnsRemoved); + QObject::connect(m_itemModel.data(), &QAbstractItemModel::dataChanged, + this, &AbstractItemModelHandler::handleDataChanged); + QObject::connect(m_itemModel.data(), &QAbstractItemModel::layoutChanged, + this, &AbstractItemModelHandler::handleLayoutChanged); + QObject::connect(m_itemModel.data(), &QAbstractItemModel::modelReset, + this, &AbstractItemModelHandler::handleModelReset); + QObject::connect(m_itemModel.data(), &QAbstractItemModel::rowsInserted, + this, &AbstractItemModelHandler::handleRowsInserted); + QObject::connect(m_itemModel.data(), &QAbstractItemModel::rowsMoved, + this, &AbstractItemModelHandler::handleRowsMoved); + QObject::connect(m_itemModel.data(), &QAbstractItemModel::rowsRemoved, + this, &AbstractItemModelHandler::handleRowsRemoved); + } + if (!m_resolveTimer.isActive()) + m_resolveTimer.start(0); +} + +const QAbstractItemModel *AbstractItemModelHandler::itemModel() const +{ + return m_itemModel.data(); +} + +void AbstractItemModelHandler::setActiveMapping(QAbstractDataMapping *mapping) +{ + if (m_activeMapping) + QObject::disconnect(m_activeMapping, 0, this, 0); + + if (mapping) + addMapping(mapping); + + m_activeMapping = mapping; + + if (m_activeMapping) { + QObject::connect(m_activeMapping, &QAbstractDataMapping::mappingChanged, + this, &AbstractItemModelHandler::handleMappingChanged); + } + + if (!m_resolveTimer.isActive()) + m_resolveTimer.start(0); +} + +QAbstractDataMapping *AbstractItemModelHandler::activeMapping() const +{ + return m_activeMapping; +} + +void AbstractItemModelHandler::addMapping(QAbstractDataMapping *mapping) +{ + Q_ASSERT(mapping); + AbstractItemModelHandler *owner = qobject_cast<AbstractItemModelHandler *>(mapping->parent()); + if (owner != this) { + Q_ASSERT_X(!owner, "addMapping", "Mapping already attached to a proxy."); + mapping->setParent(this); + } + if (!m_mappings.contains(mapping)) + m_mappings.append(mapping); +} + +void AbstractItemModelHandler::releaseMapping(QAbstractDataMapping *mapping) +{ + if (mapping && m_mappings.contains(mapping)) { + // If the mapping is in use, clear the existing mapping + if (m_activeMapping == mapping) + setActiveMapping(0); + + m_mappings.removeAll(mapping); + mapping->setParent(0); + } +} + +QList<QAbstractDataMapping *> AbstractItemModelHandler::mappings() const +{ + return m_mappings; +} + +void AbstractItemModelHandler::handleColumnsInserted(const QModelIndex &parent, + int start, int end) +{ + Q_UNUSED(parent) + Q_UNUSED(start) + Q_UNUSED(end) + + // Resolve new items + if (!m_resolveTimer.isActive()) + m_resolveTimer.start(0); // TODO Resolving entire model is inefficient +} + +void AbstractItemModelHandler::handleColumnsMoved(const QModelIndex &sourceParent, + int sourceStart, + int sourceEnd, + const QModelIndex &destinationParent, + int destinationColumn) +{ + Q_UNUSED(sourceParent) + Q_UNUSED(sourceStart) + Q_UNUSED(sourceEnd) + Q_UNUSED(destinationParent) + Q_UNUSED(destinationColumn) + + // Resolve moved items + if (!m_resolveTimer.isActive()) + m_resolveTimer.start(0); // TODO Resolving entire model is inefficient +} + +void AbstractItemModelHandler::handleColumnsRemoved(const QModelIndex &parent, + int start, int end) +{ + Q_UNUSED(parent) + Q_UNUSED(start) + Q_UNUSED(end) + + // Remove old items + if (!m_resolveTimer.isActive()) + m_resolveTimer.start(0); // TODO Resolving entire model is inefficient +} + +void AbstractItemModelHandler::handleDataChanged(const QModelIndex &topLeft, + const QModelIndex &bottomRight, + const QVector<int> &roles) +{ + Q_UNUSED(topLeft) + Q_UNUSED(bottomRight) + Q_UNUSED(roles) + + // Resolve changed items + if (!m_resolveTimer.isActive()) + m_resolveTimer.start(0); // TODO Resolving entire model is inefficient +} + +void AbstractItemModelHandler::handleLayoutChanged(const QList<QPersistentModelIndex> &parents, + QAbstractItemModel::LayoutChangeHint hint) +{ + Q_UNUSED(parents) + Q_UNUSED(hint) + + // Resolve moved items + if (!m_resolveTimer.isActive()) + m_resolveTimer.start(0); // TODO Resolving entire model is inefficient +} + +void AbstractItemModelHandler::handleModelReset() +{ + // Data cleared, reset array + if (!m_resolveTimer.isActive()) + m_resolveTimer.start(0); // TODO Resolving entire model is inefficient +} + +void AbstractItemModelHandler::handleRowsInserted(const QModelIndex &parent, int start, int end) +{ + Q_UNUSED(parent) + Q_UNUSED(start) + Q_UNUSED(end) + + // Resolve new items + if (!m_resolveTimer.isActive()) + m_resolveTimer.start(0); // TODO Resolving entire model is inefficient +} + +void AbstractItemModelHandler::handleRowsMoved(const QModelIndex &sourceParent, + int sourceStart, + int sourceEnd, + const QModelIndex &destinationParent, + int destinationRow) +{ + Q_UNUSED(sourceParent) + Q_UNUSED(sourceStart) + Q_UNUSED(sourceEnd) + Q_UNUSED(destinationParent) + Q_UNUSED(destinationRow) + + // Resolve moved items + if (!m_resolveTimer.isActive()) + m_resolveTimer.start(0); // TODO Resolving entire model is inefficient +} + +void AbstractItemModelHandler::handleRowsRemoved(const QModelIndex &parent, int start, int end) +{ + Q_UNUSED(parent) + Q_UNUSED(start) + Q_UNUSED(end) + + // Resolve removed items + if (!m_resolveTimer.isActive()) + m_resolveTimer.start(0); // TODO Resolving entire model is inefficient +} + +void AbstractItemModelHandler::handleMappingChanged() +{ + if (!m_resolveTimer.isActive()) + m_resolveTimer.start(0); +} + +void AbstractItemModelHandler::handlePendingResolve() +{ + resolveModel(); +} + +QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavisualization/data/abstractitemmodelhandler_p.h b/src/datavisualization/data/abstractitemmodelhandler_p.h new file mode 100644 index 00000000..fbaaa1f9 --- /dev/null +++ b/src/datavisualization/data/abstractitemmodelhandler_p.h @@ -0,0 +1,90 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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 +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVisualization API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. + +#ifndef ABSTRACTITEMMODELHANDLER_P_H +#define ABSTRACTITEMMODELHANDLER_P_H + +#include "datavisualizationglobal_p.h" +#include <QAbstractItemModel> +#include <QPointer> +#include <QTimer> + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +class QAbstractDataMapping; + +class AbstractItemModelHandler : public QObject +{ + Q_OBJECT +public: + AbstractItemModelHandler(QObject *parent = 0); + virtual ~AbstractItemModelHandler(); + + virtual void setItemModel(const QAbstractItemModel *itemModel); + virtual const QAbstractItemModel *itemModel() const; + virtual void setActiveMapping(QAbstractDataMapping *mapping); + virtual QAbstractDataMapping *activeMapping() const; + virtual void addMapping(QAbstractDataMapping *mapping); + virtual void releaseMapping(QAbstractDataMapping *mapping); + virtual QList<QAbstractDataMapping *> mappings() const; + +public slots: + virtual void handleColumnsInserted(const QModelIndex &parent, int start, int end); + virtual void handleColumnsMoved(const QModelIndex &sourceParent, int sourceStart, + int sourceEnd, const QModelIndex &destinationParent, + int destinationColumn); + virtual void handleColumnsRemoved(const QModelIndex &parent, int start, int end); + virtual void handleDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, + const QVector<int> &roles = QVector<int> ()); + virtual void handleLayoutChanged(const QList<QPersistentModelIndex> &parents = QList<QPersistentModelIndex>(), + QAbstractItemModel::LayoutChangeHint hint = QAbstractItemModel::NoLayoutChangeHint); + virtual void handleModelReset(); + virtual void handleRowsInserted(const QModelIndex &parent, int start, int end); + virtual void handleRowsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, + const QModelIndex &destinationParent, int destinationRow); + virtual void handleRowsRemoved(const QModelIndex &parent, int start, int end); + + virtual void handleMappingChanged(); + virtual void handlePendingResolve(); + +protected: + virtual void resolveModel() = 0; + + QPointer<const QAbstractItemModel> m_itemModel; // Not owned + QAbstractDataMapping *m_activeMapping; + bool resolvePending; + QTimer m_resolveTimer; + QList<QAbstractDataMapping *> m_mappings; + +private: + Q_DISABLE_COPY(AbstractItemModelHandler) +}; + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif diff --git a/src/datavisualization/data/abstractrenderitem.cpp b/src/datavisualization/data/abstractrenderitem.cpp new file mode 100644 index 00000000..22a1c6de --- /dev/null +++ b/src/datavisualization/data/abstractrenderitem.cpp @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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 "abstractrenderitem_p.h" + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +AbstractRenderItem::AbstractRenderItem() + : m_selectionLabelItem(0) +{ +} + +AbstractRenderItem::AbstractRenderItem(const AbstractRenderItem &other) +{ + m_selectionLabel = other.m_selectionLabel; + m_translation = other.m_translation; + m_selectionLabelItem = 0; +} + +AbstractRenderItem::~AbstractRenderItem() +{ + delete m_selectionLabelItem; +} + +LabelItem &AbstractRenderItem::selectionLabelItem() +{ + if (!m_selectionLabelItem) + m_selectionLabelItem = new LabelItem; + return *m_selectionLabelItem; +} + +void AbstractRenderItem::setSelectionLabel(const QString &label) +{ + if (m_selectionLabelItem) + m_selectionLabelItem->clear(); + m_selectionLabel = label; +} + +QString &AbstractRenderItem::selectionLabel() +{ + return m_selectionLabel; +} + + +QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavisualization/data/abstractrenderitem_p.h b/src/datavisualization/data/abstractrenderitem_p.h new file mode 100644 index 00000000..5f623c41 --- /dev/null +++ b/src/datavisualization/data/abstractrenderitem_p.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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 +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVisualization API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. + +#ifndef ABSTRACTRENDERITEM_P_H +#define ABSTRACTRENDERITEM_P_H + +#include "datavisualizationglobal_p.h" +#include "labelitem_p.h" + +#include <QOpenGLFunctions> +#include <QString> +#include <QVector3D> + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +class AbstractRenderItem +{ +public: + AbstractRenderItem(); + AbstractRenderItem(const AbstractRenderItem &other); + virtual ~AbstractRenderItem(); + + // Position in 3D scene + inline void setTranslation(const QVector3D &translation) { m_translation = translation; } + inline const QVector3D &translation() const {return m_translation; } + + // Selection label item (containing special selection texture, if mode is activated) + LabelItem &selectionLabelItem(); + + // Formatted selection label for item. + void setSelectionLabel(const QString &label); + QString &selectionLabel(); // Formats selection label if not previously formatted + +protected: + QString m_selectionLabel; + QVector3D m_translation; + LabelItem *m_selectionLabelItem; + + friend class QAbstractDataItem; +}; + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif diff --git a/src/datavisualization/data/baritemmodelhandler.cpp b/src/datavisualization/data/baritemmodelhandler.cpp new file mode 100644 index 00000000..f7611668 --- /dev/null +++ b/src/datavisualization/data/baritemmodelhandler.cpp @@ -0,0 +1,148 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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 "baritemmodelhandler_p.h" +#include "qitemmodelbardatamapping_p.h" + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +BarItemModelHandler::BarItemModelHandler(QItemModelBarDataProxy *proxy, QObject *parent) + : AbstractItemModelHandler(parent), + m_proxy(proxy), + m_proxyArray(0), + m_columnCount(0) +{ +} + +BarItemModelHandler::~BarItemModelHandler() +{ +} + +// Resolve entire item model into QBarDataArray. +void BarItemModelHandler::resolveModel() +{ + QItemModelBarDataMapping *mapping = static_cast<QItemModelBarDataMapping *>(m_activeMapping); + if (m_itemModel.isNull() || !mapping) { + m_proxy->resetArray(0); + return; + } + + if (!mapping->useModelCategories() + && (mapping->rowRole().isEmpty() || mapping->columnRole().isEmpty())) { + m_proxy->resetArray(0); + return; + } + + QStringList rowLabels; + QStringList columnLabels; + + QHash<int, QByteArray> roleHash = m_itemModel->roleNames(); + + // Default to display role if no mapping + int valueRole = roleHash.key(mapping->valueRole().toLatin1(), Qt::DisplayRole); + int rowCount = m_itemModel->rowCount(); + int columnCount = m_itemModel->columnCount(); + + if (mapping->useModelCategories()) { + // If dimensions have changed, recreate the array + if (m_proxyArray != m_proxy->array() || columnCount != m_columnCount + || rowCount != m_proxyArray->size()) { + m_proxyArray = new QBarDataArray; + m_proxyArray->reserve(rowCount); + for (int i = 0; i < rowCount; i++) + m_proxyArray->append(new QBarDataRow(columnCount)); + } + for (int i = 0; i < rowCount; i++) { + QBarDataRow &newProxyRow = *m_proxyArray->at(i); + for (int j = 0; j < columnCount; j++) + newProxyRow[j].setValue(m_itemModel->index(i, j).data(valueRole).toReal()); + } + // Generate labels from headers if using model rows/columns + for (int i = 0; i < rowCount; i++) + rowLabels << m_itemModel->headerData(i, Qt::Vertical).toString(); + for (int i = 0; i < columnCount; i++) + columnLabels << m_itemModel->headerData(i, Qt::Horizontal).toString(); + m_columnCount = columnCount; + } else { + int rowRole = roleHash.key(mapping->rowRole().toLatin1()); + int columnRole = roleHash.key(mapping->columnRole().toLatin1()); + + bool generateRows = mapping->autoRowCategories(); + bool generateColumns = mapping->autoColumnCategories(); + QStringList rowList; + QStringList columnList; + // For detecting duplicates in categories generation, using QHashes should be faster than + // simple QStringList::contains() check. + QHash<QString, bool> rowListHash; + QHash<QString, bool> columnListHash; + + // Sort values into rows and columns + typedef QHash<QString, qreal> ColumnValueMap; + QHash <QString, ColumnValueMap> itemValueMap; + 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 (generateRows && !rowListHash.value(rowRoleStr, false)) { + rowListHash.insert(rowRoleStr, true); + rowList << rowRoleStr; + } + if (generateColumns && !columnListHash.value(columnRoleStr, false)) { + columnListHash.insert(columnRoleStr, true); + columnList << columnRoleStr; + } + } + } + + if (generateRows) + mapping->dptr()->m_rowCategories = rowList; + else + rowList = mapping->rowCategories(); + + if (generateColumns) + mapping->dptr()->m_columnCategories = columnList; + else + columnList = mapping->columnCategories(); + + // If dimensions have changed, recreate the array + if (m_proxyArray != m_proxy->array() || columnList.size() != m_columnCount + || rowList.size() != m_proxyArray->size()) { + m_proxyArray = new QBarDataArray; + m_proxyArray->reserve(rowList.size()); + for (int i = 0; i < rowList.size(); i++) + m_proxyArray->append(new QBarDataRow(columnList.size())); + } + // Create new data array from itemValueMap + 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++) + newProxyRow[j].setValue(itemValueMap[rowKey][columnList.at(j)]); + } + + rowLabels = rowList; + columnLabels = columnList; + m_columnCount = columnList.size(); + } + + m_proxy->resetArray(m_proxyArray, rowLabels, columnLabels); +} + +QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavisualization/data/baritemmodelhandler_p.h b/src/datavisualization/data/baritemmodelhandler_p.h new file mode 100644 index 00000000..54b45f2e --- /dev/null +++ b/src/datavisualization/data/baritemmodelhandler_p.h @@ -0,0 +1,54 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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 +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVisualization API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. + +#ifndef BARITEMMODELHANDLER_P_H +#define BARITEMMODELHANDLER_P_H + +#include "abstractitemmodelhandler_p.h" +#include "qitemmodelbardataproxy.h" + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +class BarItemModelHandler : public AbstractItemModelHandler +{ + Q_OBJECT +public: + BarItemModelHandler(QItemModelBarDataProxy *proxy, QObject *parent = 0); + virtual ~BarItemModelHandler(); + +protected: + void virtual resolveModel(); + + QItemModelBarDataProxy *m_proxy; // Not owned + QBarDataArray *m_proxyArray; // Not owned + int m_columnCount; +}; + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif diff --git a/src/datavisualization/data/barrenderitem.cpp b/src/datavisualization/data/barrenderitem.cpp new file mode 100644 index 00000000..558e2f96 --- /dev/null +++ b/src/datavisualization/data/barrenderitem.cpp @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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 "barrenderitem_p.h" +#include "bars3drenderer_p.h" + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +BarRenderItem::BarRenderItem() + : AbstractRenderItem(), + m_value(0), + m_height(0.0f), + m_sliceLabelItem(0) +{ +} + +BarRenderItem::BarRenderItem(const BarRenderItem &other) + : AbstractRenderItem(other) +{ + m_value = other.m_value; + m_position = other.m_position; + m_height = other.m_height; + m_sliceLabel = other.m_sliceLabel; + m_sliceLabelItem = 0; +} + +BarRenderItem::~BarRenderItem() +{ + delete m_sliceLabelItem; +} + +LabelItem &BarRenderItem::sliceLabelItem() +{ + if (!m_sliceLabelItem) + m_sliceLabelItem = new LabelItem; + return *m_sliceLabelItem; +} + +void BarRenderItem::setSliceLabel(const QString &label) +{ + if (m_sliceLabelItem) + m_sliceLabelItem->clear(); + m_sliceLabel = label; +} + +QString &BarRenderItem::sliceLabel() +{ + return m_sliceLabel; +} + + +QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavisualization/data/barrenderitem_p.h b/src/datavisualization/data/barrenderitem_p.h new file mode 100644 index 00000000..6cd2b0fa --- /dev/null +++ b/src/datavisualization/data/barrenderitem_p.h @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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 +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVisualization API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. + +#ifndef BARRENDERITEM_P_H +#define BARRENDERITEM_P_H + +#include "abstractrenderitem_p.h" + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +class Bars3DRenderer; + +class BarRenderItem : public AbstractRenderItem +{ +public: + BarRenderItem(); + BarRenderItem(const BarRenderItem &other); + virtual ~BarRenderItem(); + + // Position relative to data window (for bar label generation) + inline void setPosition(const QPoint &pos) { m_position = pos; } + inline const QPoint &position() const { return m_position; } + + // Actual cached data value of the bar (needed to trigger label reformats) + inline void setValue(qreal value); + inline qreal value() const { return m_value; } + + // Normalized bar height + inline void setHeight(GLfloat height) { m_height = height; } + inline GLfloat height() const { return m_height; } + + // Label item for formatted label + LabelItem &sliceLabelItem(); + + // Formatted label for item. + void setSliceLabel(const QString &label); + QString &sliceLabel(); // Formats label if not previously formatted + +protected: + qreal m_value; + QPoint m_position; // x = row, y = column + GLfloat m_height; + QString m_sliceLabel; + LabelItem *m_sliceLabelItem; + + friend class QBarDataItem; +}; + +void BarRenderItem::setValue(qreal value) +{ + m_value = value; + // Force reformatting on next access by setting label string to null string + if (!m_sliceLabel.isNull()) + setSliceLabel(QString()); + if (!m_selectionLabel.isNull()) + setSelectionLabel(QString()); +} + +typedef QVector<BarRenderItem> BarRenderItemRow; +typedef QVector<BarRenderItemRow> BarRenderItemArray; + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif diff --git a/src/datavisualization/data/data.pri b/src/datavisualization/data/data.pri new file mode 100644 index 00000000..770d2bd1 --- /dev/null +++ b/src/datavisualization/data/data.pri @@ -0,0 +1,64 @@ +HEADERS += \ + $$PWD/labelitem_p.h \ + $$PWD/qabstractdataproxy.h \ + $$PWD/qabstractdataproxy_p.h \ + $$PWD/qbardataproxy.h \ + $$PWD/qbardataproxy_p.h \ + $$PWD/abstractrenderitem_p.h \ + $$PWD/barrenderitem_p.h \ + $$PWD/qbardataitem.h \ + $$PWD/qbardataitem_p.h \ + $$PWD/qitemmodelbardatamapping.h \ + $$PWD/qitemmodelbardatamapping_p.h \ + $$PWD/qitemmodelbardataproxy_p.h \ + $$PWD/qitemmodelbardataproxy.h \ + $$PWD/scatterrenderitem_p.h \ + $$PWD/qscatterdataitem.h \ + $$PWD/qscatterdataitem_p.h \ + $$PWD/qscatterdataproxy.h \ + $$PWD/qscatterdataproxy_p.h \ + $$PWD/qitemmodelscatterdatamapping.h \ + $$PWD/qitemmodelscatterdatamapping_p.h \ + $$PWD/qitemmodelscatterdataproxy.h \ + $$PWD/qitemmodelscatterdataproxy_p.h \ + $$PWD/abstractitemmodelhandler_p.h \ + $$PWD/baritemmodelhandler_p.h \ + $$PWD/qabstractdatamapping.h \ + $$PWD/qabstractdatamapping_p.h \ + $$PWD/scatteritemmodelhandler_p.h \ + $$PWD/qsurfacedataproxy.h \ + $$PWD/qsurfacedataproxy_p.h \ + $$PWD/qheightmapsurfacedataproxy.h \ + $$PWD/qheightmapsurfacedataproxy_p.h \ + $$PWD/qitemmodelsurfacedatamapping.h \ + $$PWD/qitemmodelsurfacedatamapping_p.h \ + $$PWD/qitemmodelsurfacedataproxy.h \ + $$PWD/qitemmodelsurfacedataproxy_p.h \ + $$PWD/surfaceitemmodelhandler_p.h \ + $$PWD/qsurfacedataitem.h \ + $$PWD/qsurfacedataitem_p.h + +SOURCES += \ + $$PWD/labelitem.cpp \ + $$PWD/qabstractdataproxy.cpp \ + $$PWD/qbardataproxy.cpp \ + $$PWD/abstractrenderitem.cpp \ + $$PWD/barrenderitem.cpp \ + $$PWD/qbardataitem.cpp \ + $$PWD/qitemmodelbardatamapping.cpp \ + $$PWD/qitemmodelbardataproxy.cpp \ + $$PWD/scatterrenderitem.cpp \ + $$PWD/qscatterdataitem.cpp \ + $$PWD/qscatterdataproxy.cpp \ + $$PWD/qitemmodelscatterdatamapping.cpp \ + $$PWD/qitemmodelscatterdataproxy.cpp \ + $$PWD/abstractitemmodelhandler.cpp \ + $$PWD/baritemmodelhandler.cpp \ + $$PWD/qabstractdatamapping.cpp \ + $$PWD/scatteritemmodelhandler.cpp \ + $$PWD/qsurfacedataproxy.cpp \ + $$PWD/qheightmapsurfacedataproxy.cpp \ + $$PWD/qitemmodelsurfacedatamapping.cpp \ + $$PWD/qitemmodelsurfacedataproxy.cpp \ + $$PWD/surfaceitemmodelhandler.cpp \ + $$PWD/qsurfacedataitem.cpp diff --git a/src/datavisualization/data/labelitem.cpp b/src/datavisualization/data/labelitem.cpp new file mode 100644 index 00000000..5e27a50e --- /dev/null +++ b/src/datavisualization/data/labelitem.cpp @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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 "labelitem_p.h" + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +LabelItem::LabelItem() + : m_size(QSize(0, 0)), + m_textureId(0) +{ +} + +LabelItem::~LabelItem() +{ + glDeleteTextures(1, &m_textureId); +} + +void LabelItem::setSize(const QSize &size) +{ + m_size = size; +} + +QSize LabelItem::size() const +{ + return m_size; +} + +void LabelItem::setTextureId(GLuint textureId) +{ + glDeleteTextures(1, &m_textureId); + m_textureId = textureId; +} + +GLuint LabelItem::textureId() const +{ + return m_textureId; +} + +void LabelItem::clear() +{ + if (m_textureId) { + glDeleteTextures(1, &m_textureId); + m_textureId = 0; + } + m_size = QSize(0, 0); +} + +QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavisualization/data/labelitem_p.h b/src/datavisualization/data/labelitem_p.h new file mode 100644 index 00000000..c10c1f12 --- /dev/null +++ b/src/datavisualization/data/labelitem_p.h @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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 +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVisualization API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. + +#ifndef LABELITEM_P_H +#define LABELITEM_P_H + +#include "datavisualizationglobal_p.h" +#include <QOpenGLFunctions> +#include <QSize> + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +class LabelItem +{ +public: + explicit LabelItem(); + ~LabelItem(); + + void setSize(const QSize &size); + QSize size() const; + void setTextureId(GLuint textureId); + GLuint textureId() const; + void clear(); + +private: + Q_DISABLE_COPY(LabelItem); + + QSize m_size; + GLuint m_textureId; +}; + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif diff --git a/src/datavisualization/data/qabstractdatamapping.cpp b/src/datavisualization/data/qabstractdatamapping.cpp new file mode 100644 index 00000000..892d2f94 --- /dev/null +++ b/src/datavisualization/data/qabstractdatamapping.cpp @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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 "qabstractdatamapping_p.h" + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +/*! + * \class QAbstractDataMapping + * \inmodule QtDataVisualization + * \brief Abstract base class for QtDataVisualization data mapping classes. + * \since 1.0.0 + * + * Data mapping classes provide a way to map data from an external data source to one of + * QtDataVisualization data proxies. + * \sa QItemModelBarDataMapping, QItemModelScatterDataMapping + */ + +/*! + * \internal + */ +QAbstractDataMapping::QAbstractDataMapping(QAbstractDataMappingPrivate *d, QObject *parent) + : QObject(parent), + d_ptr(d) +{ +} + +/*! + * Destroys QAbstractDataMapping. + */ +QAbstractDataMapping::~QAbstractDataMapping() +{ +} + +/*! + * \fn void QAbstractDataMapping::mappingChanged() + * + * Emitted when any mapping has changed. + */ + +// QItemModelBarDataMappingPrivate + +QAbstractDataMappingPrivate::QAbstractDataMappingPrivate(QAbstractDataMapping *q, + QAbstractDataProxy::DataType type) + : QObject(0), + q_ptr(q), + m_type(type) +{ +} + +QAbstractDataMappingPrivate::~QAbstractDataMappingPrivate() +{ +} + +QT_DATAVISUALIZATION_END_NAMESPACE + diff --git a/src/datavisualization/data/qabstractdatamapping.h b/src/datavisualization/data/qabstractdatamapping.h new file mode 100644 index 00000000..eb892cb7 --- /dev/null +++ b/src/datavisualization/data/qabstractdatamapping.h @@ -0,0 +1,53 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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 +** +****************************************************************************/ + +#ifndef QABSTRACTDATAMAPPING_H +#define QABSTRACTDATAMAPPING_H + +#include <QtDataVisualization/qdatavisualizationenums.h> +#include <QtDataVisualization/qabstractdataproxy.h> + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +class QAbstractDataMappingPrivate; + +class QT_DATAVISUALIZATION_EXPORT QAbstractDataMapping : public QObject +{ + Q_OBJECT + +public: + explicit QAbstractDataMapping(QAbstractDataMappingPrivate *d, QObject *parent = 0); + virtual ~QAbstractDataMapping(); + +signals: + void mappingChanged(); + +private: + QScopedPointer<QAbstractDataMappingPrivate> d_ptr; + + Q_DISABLE_COPY(QAbstractDataMapping) + + friend class QItemModelBarDataMapping; + friend class QItemModelScatterDataMapping; + friend class QItemModelSurfaceDataMapping; +}; + + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif diff --git a/src/datavisualization/data/qabstractdatamapping_p.h b/src/datavisualization/data/qabstractdatamapping_p.h new file mode 100644 index 00000000..39012237 --- /dev/null +++ b/src/datavisualization/data/qabstractdatamapping_p.h @@ -0,0 +1,50 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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 +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVisualization API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. + +#include "qabstractdatamapping.h" + +#ifndef QABSTRACTDATAMAPPING_P_H +#define QABSTRACTDATAMAPPING_P_H + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +class QAbstractDataMappingPrivate : public QObject +{ + Q_OBJECT +public: + QAbstractDataMappingPrivate(QAbstractDataMapping *q, QAbstractDataProxy::DataType type); + virtual ~QAbstractDataMappingPrivate(); + +private: + QAbstractDataMapping *q_ptr; + QAbstractDataProxy::DataType m_type; +}; + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif diff --git a/src/datavisualization/data/qabstractdataproxy.cpp b/src/datavisualization/data/qabstractdataproxy.cpp new file mode 100644 index 00000000..8ccb0d7a --- /dev/null +++ b/src/datavisualization/data/qabstractdataproxy.cpp @@ -0,0 +1,148 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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 "qabstractdataproxy.h" +#include "qabstractdataproxy_p.h" + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +/*! + * \class QAbstractDataProxy + * \inmodule QtDataVisualization + * \brief Base class for all QtDataVisualization data proxies. + * \since 1.0.0 + * + * You use the visualization type specific inherited classes instead of the base class. + * \sa QBarDataProxy, QScatterDataProxy, QSurfaceDataProxy, {Qt Data Visualization Data Handling} + */ + +/*! + * \qmltype AbstractDataProxy + * \inqmlmodule com.digia.QtDataVisualization 1.0 + * \since com.digia.QtDataVisualization 1.0 + * \ingroup datavisualization_qml + * \instantiates QAbstractDataProxy + * \brief Base type for all QtDataVisualization data proxies. + * + * This type is uncreatable, but contains properties that are exposed via subtypes. + * \sa BarDataProxy, ScatterDataProxy, SurfaceDataProxy, {Qt Data Visualization Data Handling} + */ + +/*! + * \qmlproperty AbstractDataProxy.DataType AbstractDataProxy::type + * The type of the proxy. + */ + +/*! + * \qmlproperty string AbstractDataProxy::itemLabelFormat + * + * Label format for data items in this proxy. This format is used for single item labels, + * e.g. when an item is selected. How the format is interpreted depends on proxy type. See + * each proxy class documentation for more information. + */ + +/*! + * \enum QAbstractDataProxy::DataType + * + * Data type of the proxy. + * + * \value DataTypeNone + * No data type. + * \value DataTypeBar + * Data type for Q3DBars. + * \value DataTypeScatter + * Data type for Q3DScatter. + * \value DataTypeSurface + * Data type for Q3DSurface. + */ + +/*! + * \internal + */ +QAbstractDataProxy::QAbstractDataProxy(QAbstractDataProxyPrivate *d, QObject *parent) : + QObject(parent), + d_ptr(d) +{ +} + +/*! + * Destroys QAbstractDataProxy. + */ +QAbstractDataProxy::~QAbstractDataProxy() +{ +} + +/*! + * \property QAbstractDataProxy::type + * + * The type of the proxy. + */ +QAbstractDataProxy::DataType QAbstractDataProxy::type() const +{ + return d_ptr->m_type; +} + +/*! + * \property QAbstractDataProxy::itemLabelFormat + * + * Sets label \a format for data items in this proxy. This format is used for single item labels, + * e.g. when an item is selected. How the format is interpreted depends on proxy type. See + * each proxy class documentation for more information. + * + * \sa QBarDataProxy, QScatterDataProxy, QSurfaceDataProxy + */ +void QAbstractDataProxy::setItemLabelFormat(const QString &format) +{ + d_ptr->setItemLabelFormat(format); + emit itemLabelFormatChanged(); +} + +/*! + * \return label format for data items in this proxy. + */ +QString QAbstractDataProxy::itemLabelFormat() const +{ + return d_ptr->m_itemLabelFormat; +} + +/*! + * \fn void QAbstractDataProxy::itemLabelFormatChanged() + * + * Emitted when label format changes. + */ + +// QAbstractDataProxyPrivate + +QAbstractDataProxyPrivate::QAbstractDataProxyPrivate(QAbstractDataProxy *q, QAbstractDataProxy::DataType type) + : QObject(0), + q_ptr(q), + m_type(type), + m_isDefaultProxy(false) +{ +} + +QAbstractDataProxyPrivate::~QAbstractDataProxyPrivate() +{ +} + +void QAbstractDataProxyPrivate::setItemLabelFormat(const QString &format) +{ + m_itemLabelFormat = format; +} + +QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavisualization/data/qabstractdataproxy.h b/src/datavisualization/data/qabstractdataproxy.h new file mode 100644 index 00000000..db0e0863 --- /dev/null +++ b/src/datavisualization/data/qabstractdataproxy.h @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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 +** +****************************************************************************/ + +#ifndef QABSTRACTDATAPROXY_H +#define QABSTRACTDATAPROXY_H + +#include <QtDataVisualization/qdatavisualizationenums.h> +#include <QObject> +#include <QScopedPointer> + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +class QAbstractDataProxyPrivate; + +class QT_DATAVISUALIZATION_EXPORT QAbstractDataProxy : public QObject +{ + Q_OBJECT + Q_ENUMS(DataType) + Q_PROPERTY(DataType type READ type) + Q_PROPERTY(QString itemLabelFormat READ itemLabelFormat WRITE setItemLabelFormat NOTIFY itemLabelFormatChanged) + +public: + enum DataType { + DataTypeNone = 0, + DataTypeBar = 1, + DataTypeScatter = 2, + DataTypeSurface = 4 + }; + +protected: + explicit QAbstractDataProxy(QAbstractDataProxyPrivate *d, QObject *parent = 0); + +public: + virtual ~QAbstractDataProxy(); + + DataType type() const; + + void setItemLabelFormat(const QString &format); + QString itemLabelFormat() const; + +signals: + void itemLabelFormatChanged(); + +protected: + QScopedPointer<QAbstractDataProxyPrivate> d_ptr; + +private: + Q_DISABLE_COPY(QAbstractDataProxy) + + friend class Abstract3DController; + friend class Bars3DController; + friend class Scatter3DController; + friend class Surface3DController; +}; + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif // QABSTRACTDATAPROXY_H diff --git a/src/datavisualization/data/qabstractdataproxy_p.h b/src/datavisualization/data/qabstractdataproxy_p.h new file mode 100644 index 00000000..4aa1b678 --- /dev/null +++ b/src/datavisualization/data/qabstractdataproxy_p.h @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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 +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVisualization API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. + +#include "datavisualizationglobal_p.h" +#include "qabstractdataproxy.h" +#include <QString> + +#ifndef QABSTRACTDATAPROXY_P_H +#define QABSTRACTDATAPROXY_P_H + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +class QAbstractDataProxyPrivate : public QObject +{ + Q_OBJECT +public: + QAbstractDataProxyPrivate(QAbstractDataProxy *q, QAbstractDataProxy::DataType type); + virtual ~QAbstractDataProxyPrivate(); + + void setItemLabelFormat(const QString &format); + + inline bool isDefaultProxy() { return m_isDefaultProxy; } + inline void setDefaultProxy(bool isDefault) { m_isDefaultProxy = isDefault; } + +protected: + QAbstractDataProxy *q_ptr; + QAbstractDataProxy::DataType m_type; + QString m_itemLabelFormat; + bool m_isDefaultProxy; + +private: + friend class QAbstractDataProxy; +}; + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif // QABSTRACTDATAPROXY_P_H diff --git a/src/datavisualization/data/qbardataitem.cpp b/src/datavisualization/data/qbardataitem.cpp new file mode 100644 index 00000000..2803c01a --- /dev/null +++ b/src/datavisualization/data/qbardataitem.cpp @@ -0,0 +1,110 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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 "qbardataitem_p.h" + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +/*! + * \class QBarDataItem + * \inmodule QtDataVisualization + * \brief The QBarDataItem class provides a container for resolved data to be added to bar graphs. + * \since 1.0.0 + * + * A QBarDataItem holds data for a single rendered bar in a graph. + * Bar data proxies parse data into QBarDataItem instances for visualizing. + * + * \sa QBarDataProxy, {Qt Data Visualization C++ Classes} + */ + +/*! + * Constructs QBarDataItem. + */ +QBarDataItem::QBarDataItem() + : d_ptr(0), // private data doesn't exist by default (optimization) + m_value(0.0) +{ +} + +/*! + * Constructs QBarDataItem with \a value. + */ +QBarDataItem::QBarDataItem(qreal value) + : d_ptr(0), + m_value(value) +{ +} + +/*! + * Constructs a copy of \a other. + */ +QBarDataItem::QBarDataItem(const QBarDataItem &other) +{ + operator=(other); +} + +/*! + * Destroys QBarDataItem. + */ +QBarDataItem::~QBarDataItem() +{ + delete d_ptr; +} + +/*! + * Assigns a copy of \a other to this object. + */ +QBarDataItem &QBarDataItem::operator=(const QBarDataItem &other) +{ + m_value = other.m_value; + if (other.d_ptr) + createExtraData(); + else + d_ptr = 0; + // TODO set extra data + return *this; +} + +/*! + * \fn void QBarDataItem::setValue(qreal value) + * Sets \a value to this data item. + */ + +/*! + * \fn qreal QBarDataItem::value() const + * \return value of this data item. + */ + +/*! + * \internal + */ +void QBarDataItem::createExtraData() +{ + if (!d_ptr) + d_ptr = new QBarDataItemPrivate; +} + +QBarDataItemPrivate::QBarDataItemPrivate() +{ +} + +QBarDataItemPrivate::~QBarDataItemPrivate() +{ +} + +QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavisualization/data/qbardataitem.h b/src/datavisualization/data/qbardataitem.h new file mode 100644 index 00000000..68bbcedf --- /dev/null +++ b/src/datavisualization/data/qbardataitem.h @@ -0,0 +1,54 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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 +** +****************************************************************************/ + +#ifndef QBARDATAITEM_H +#define QBARDATAITEM_H + +#include <QtDataVisualization/qdatavisualizationenums.h> + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +class QBarDataItemPrivate; + +class QT_DATAVISUALIZATION_EXPORT QBarDataItem +{ +public: + QBarDataItem(); + QBarDataItem(qreal value); + QBarDataItem(const QBarDataItem &other); + ~QBarDataItem(); + + QBarDataItem &operator=(const QBarDataItem &other); + + void setValue(qreal value) { m_value = value; } + qreal value() const { return m_value; } + + // TODO Set color, label format, ...? + +protected: + virtual void createExtraData(); + + QBarDataItemPrivate *d_ptr; + +private: + qreal m_value; +}; + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif diff --git a/src/datavisualization/data/qbardataitem_p.h b/src/datavisualization/data/qbardataitem_p.h new file mode 100644 index 00000000..20b7ea69 --- /dev/null +++ b/src/datavisualization/data/qbardataitem_p.h @@ -0,0 +1,51 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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 +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVisualization API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. + +#ifndef QBARDATAITEM_P_H +#define QBARDATAITEM_P_H + +#include "datavisualizationglobal_p.h" +#include "qbardataitem.h" + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +class QBarDataItemPrivate +{ +public: + QBarDataItemPrivate(); + virtual ~QBarDataItemPrivate(); + + // TODO stores other data for bars besides value + +protected: + friend class QBarDataItem; +}; + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif diff --git a/src/datavisualization/data/qbardataproxy.cpp b/src/datavisualization/data/qbardataproxy.cpp new file mode 100644 index 00000000..2ec38980 --- /dev/null +++ b/src/datavisualization/data/qbardataproxy.cpp @@ -0,0 +1,707 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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 "qbardataproxy.h" +#include "qbardataproxy_p.h" + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +/*! + * \class QBarDataProxy + * \inmodule QtDataVisualization + * \brief Base proxy class for Q3DBars. + * \since 1.0.0 + * + * QBarDataProxy handles adding, inserting, changing and removing rows of data. + * + * The data array is a list of vectors (rows) of QBarDataItem instances. + * Each row can contain different amount of items or even be null. + * + * QBarDataProxy takes ownership of all QBarDataRows passed to it, whether directly or + * in a QBarDataArray container. + * If you use QBarDataRow pointers to directly modify data after adding the array to the proxy, + * you must also emit proper signal to make the graph update. + * + * QBarDataProxy optionally keeps track of row and column labels, which Q3DCategoryAxis can utilize + * to show axis labels. The row and column labels are stored in separate array from the data and + * row manipulation methods provide an alternate versions that don't affect the row labels. + * This enables the option of having row labels that relate to the position of the data in the + * array rather than the data itself. + * + * QBarDataProxy supports the following format tags for QAbstractDataProxy::setItemLabelFormat(): + * \table + * \row + * \li @rowTitle \li Title from row axis + * \row + * \li @colTitle \li Title from column axis + * \row + * \li @valueTitle \li Title from value axis + * \row + * \li @rowIdx \li Visible row index + * \row + * \li @colIdx \li Visible Column index + * \row + * \li @rowLabel \li Label from row axis + * \row + * \li @colLabel \li Label from column axis + * \row + * \li @valueLabel \li Item value formatted using the same format the value axis attached to the graph uses, + * see \l{Q3DValueAxis::setLabelFormat()} for more information. + * \row + * \li %<format spec> \li Item value in specified format. + * \endtable + * + * For example: + * \snippet doc_src_qtdatavisualization.cpp 1 + * + * \sa {Qt Data Visualization Data Handling} + */ + +/*! + * \qmltype BarDataProxy + * \inqmlmodule com.digia.QtDataVisualization 1.0 + * \since com.digia.QtDataVisualization 1.0 + * \ingroup datavisualization_qml + * \instantiates QBarDataProxy + * \inherits AbstractDataProxy + * \brief Base proxy type for Bars3D. + * + * This type handles adding, inserting, changing and removing rows of data with Qt Quick 2. + * + * This type is uncreatable, but contains properties that are exposed via subtypes. + * + * For more complete description, see QBarDataProxy. + * + * \sa ItemModelBarDataProxy, {Qt Data Visualization Data Handling} + */ + +/*! + * \qmlproperty int BarDataProxy::rowCount + * Row count in the array. + */ + +/*! + * \qmlproperty list BarDataProxy::rowLabels + * + * Optional row labels for the array. Indexes in this array match row indexes in data array. + * If the list is shorter than row count, all rows will not get labels. + */ + +/*! + * \qmlproperty list BarDataProxy::columnLabels + * + * Optional column labels for the array. Indexes in this array match column indexes in rows. + * If the list is shorter than the longest row, all columns will not get labels. + */ + +/*! + * Constructs QBarDataProxy with the given \a parent. + */ +QBarDataProxy::QBarDataProxy(QObject *parent) : + QAbstractDataProxy(new QBarDataProxyPrivate(this), parent) +{ +} + +/*! + * \internal + */ +QBarDataProxy::QBarDataProxy(QBarDataProxyPrivate *d, QObject *parent) : + QAbstractDataProxy(d, parent) +{ +} + +/*! + * Destroys QBarDataProxy. + */ +QBarDataProxy::~QBarDataProxy() +{ +} + +/*! + * Clears the existing array and row and column labels. + */ +void QBarDataProxy::resetArray() +{ + resetArray(0, QStringList(), QStringList()); +} + +/*! + * Takes ownership of the \a newArray. Clears the existing array and if the \a newArray is + * different than the existing array. If it's the same array, this just triggers arrayReset() + * signal. + * Passing null array deletes the old array and creates a new empty array. + * Row and column labels are not affected. + */ +void QBarDataProxy::resetArray(QBarDataArray *newArray) +{ + dptr()->resetArray(newArray, 0, 0); + emit arrayReset(); +} + +/*! + * Takes ownership of the \a newArray. Clears the existing array and if the \a newArray is + * different than the existing array. If it's the same array, this just triggers arrayReset() + * signal. + * Passing null array deletes the old array and creates a new empty array. + * The \a rowLabels and \a columnLabels lists specify the new labels for rows and columns. + */ +void QBarDataProxy::resetArray(QBarDataArray *newArray, const QStringList &rowLabels, + const QStringList &columnLabels) +{ + dptr()->resetArray(newArray, &rowLabels, &columnLabels); + emit arrayReset(); +} + +/*! + * Changes existing rows by replacing a row at \a rowIndex with \a row. The \a row can be + * the same as the existing row already stored at the \a rowIndex. + * Existing row labels are not affected. + */ +void QBarDataProxy::setRow(int rowIndex, QBarDataRow *row) +{ + dptr()->setRow(rowIndex, row, 0); + emit rowsChanged(rowIndex, 1); +} + +/*! + * Changes existing rows by replacing a row at \a rowIndex with \a row. The \a row can be + * the same as the existing row already stored at the \a rowIndex. + * Changes the row label to the \a label. + */ +void QBarDataProxy::setRow(int rowIndex, QBarDataRow *row, const QString &label) +{ + dptr()->setRow(rowIndex, row, &label); + emit rowsChanged(rowIndex, 1); +} + +/*! + * Changes existing rows by replacing a rows starting at \a rowIndex with \a rows. + * Existing row labels are not affected. The rows in the \a rows array can be + * the same as the existing rows already stored at the \a rowIndex. + */ +void QBarDataProxy::setRows(int rowIndex, const QBarDataArray &rows) +{ + dptr()->setRows(rowIndex, rows, 0); + emit rowsChanged(rowIndex, rows.size()); +} + +/*! + * Changes existing rows by replacing a rows starting at \a rowIndex with \a rows. + * The row labels are changed to \a labels. The rows in the \a rows array can be + * the same as the existing rows already stored at the \a rowIndex. + */ +void QBarDataProxy::setRows(int rowIndex, const QBarDataArray &rows, const QStringList &labels) +{ + dptr()->setRows(rowIndex, rows, &labels); + emit rowsChanged(rowIndex, rows.size()); +} + +/*! + * Changes a single item at \a rowIndex, \a columnIndex to the \a item. + */ +void QBarDataProxy::setItem(int rowIndex, int columnIndex, const QBarDataItem &item) +{ + dptr()->setItem(rowIndex, columnIndex, item); + emit itemChanged(rowIndex, columnIndex); +} + +/*! + * Adds a new \a row to the end of array. + * Existing row labels are not affected. + * + * \return index of the added row. + */ +int QBarDataProxy::addRow(QBarDataRow *row) +{ + int addIndex = dptr()->addRow(row, 0); + emit rowsAdded(addIndex, 1); + return addIndex; +} + +/*! + * Adds a new \a row with the \a label to the end of array. + * + * \return index of the added row. + */ +int QBarDataProxy::addRow(QBarDataRow *row, const QString &label) +{ + int addIndex = dptr()->addRow(row, &label); + emit rowsAdded(addIndex, 1); + return addIndex; +} + +/*! + * Adds new \a rows to the end of array. + * Existing row labels are not affected. + * + * \return index of the first added row. + */ +int QBarDataProxy::addRows(const QBarDataArray &rows) +{ + int addIndex = dptr()->addRows(rows, 0); + emit rowsAdded(addIndex, rows.size()); + return addIndex; +} + +/*! + * Adds new \a rows with \a labels to the end of array. + * + * \return index of the first added row. + */ +int QBarDataProxy::addRows(const QBarDataArray &rows, const QStringList &labels) +{ + int addIndex = dptr()->addRows(rows, &labels); + emit rowsAdded(addIndex, rows.size()); + return addIndex; +} + +/*! + * Inserts a new \a row into \a rowIndex. + * If rowIndex is equal to array size, rows are added to end of the array. + * Any existing row labels are not affected. + * \note Row labels array will be out of sync with row array after this call, + * if there were labeled rows beyond the inserted row. + */ +void QBarDataProxy::insertRow(int rowIndex, QBarDataRow *row) +{ + dptr()->insertRow(rowIndex, row, 0); + emit rowsInserted(rowIndex, 1); +} + +/*! + * Inserts a new \a row with the \a label into \a rowIndex. + * If rowIndex is equal to array size, rows are added to end of the array. + */ +void QBarDataProxy::insertRow(int rowIndex, QBarDataRow *row, const QString &label) +{ + dptr()->insertRow(rowIndex, row, &label); + emit rowsInserted(rowIndex, 1); +} + +/*! + * Inserts new \a rows into \a rowIndex. + * If rowIndex is equal to array size, rows are added to end of the array. + * Any existing row labels are not affected. + * \note Row labels array will be out of sync with row array after this call, + * if there were labeled rows beyond the inserted rows. + */ +void QBarDataProxy::insertRows(int rowIndex, const QBarDataArray &rows) +{ + dptr()->insertRows(rowIndex, rows, 0); + emit rowsInserted(rowIndex, rows.size()); +} + +/*! + * Inserts new \a rows with \a labels into \a rowIndex. + * If rowIndex is equal to array size, rows are added to end of the array. + */ +void QBarDataProxy::insertRows(int rowIndex, const QBarDataArray &rows, const QStringList &labels) +{ + dptr()->insertRows(rowIndex, rows, &labels); + emit rowsInserted(rowIndex, rows.size()); +} + +/*! + * Removes \a removeCount rows staring at \a rowIndex. Attempting to remove rows past the end of the + * array does nothing. If \a removeLabels is true, corresponding row labels are also removed. Otherwise + * the row labels are not affected. + * \note If \a removeLabels is false, the row labels array will be out of sync with the row array + * if there are labeled rows beyond the removed rows. + */ +void QBarDataProxy::removeRows(int rowIndex, int removeCount, bool removeLabels) +{ + if (rowIndex < rowCount() && removeCount >= 1) { + dptr()->removeRows(rowIndex, removeCount, removeLabels); + emit rowsRemoved(rowIndex, removeCount); + } +} + +/*! + * \property QBarDataProxy::rowCount + * + * Row count in the array. + */ +int QBarDataProxy::rowCount() const +{ + return dptrc()->m_dataArray->size(); +} + +/*! + * \property QBarDataProxy::rowLabels + * + * Optional row labels for the array. Indexes in this array match row indexes in data array. + * If the list is shorter than row count, all rows will not get labels. + */ +QStringList QBarDataProxy::rowLabels() const +{ + return dptrc()->m_rowLabels; +} + +void QBarDataProxy::setRowLabels(const QStringList &labels) +{ + if (dptr()->m_rowLabels != labels) { + dptr()->m_rowLabels = labels; + emit rowLabelsChanged(); + } +} + +/*! + * \property QBarDataProxy::columnLabels + * + * Optional column labels for the array. Indexes in this array match column indexes in rows. + * If the list is shorter than the longest row, all columns will not get labels. + */ +QStringList QBarDataProxy::columnLabels() const +{ + return dptrc()->m_columnLabels; +} + +void QBarDataProxy::setColumnLabels(const QStringList &labels) +{ + if (dptr()->m_columnLabels != labels) { + dptr()->m_columnLabels = labels; + emit columnLabelsChanged(); + } +} + +/*! + * \return pointer to the data array. + */ +const QBarDataArray *QBarDataProxy::array() const +{ + return dptrc()->m_dataArray; +} + +/*! + * \return pointer to the row at \a rowIndex. It is guaranteed to be valid only until next call + * that modifies data. + */ +const QBarDataRow *QBarDataProxy::rowAt(int rowIndex) const +{ + const QBarDataArray &dataArray = *dptrc()->m_dataArray; + Q_ASSERT(rowIndex >= 0 && rowIndex < dataArray.size()); + return dataArray[rowIndex]; +} + +/*! + * \return pointer to the item at \a rowIndex, \a columnIndex. It is guaranteed to be valid only + * until next call that modifies data. + */ +const QBarDataItem *QBarDataProxy::itemAt(int rowIndex, int columnIndex) const +{ + const QBarDataArray &dataArray = *dptrc()->m_dataArray; + Q_ASSERT(rowIndex >= 0 && rowIndex < dataArray.size()); + const QBarDataRow &dataRow = *dataArray[rowIndex]; + Q_ASSERT(columnIndex >= 0 && columnIndex < dataRow.size()); + return &dataRow.at(columnIndex); +} + +/*! + * \internal + */ +QBarDataProxyPrivate *QBarDataProxy::dptr() +{ + return static_cast<QBarDataProxyPrivate *>(d_ptr.data()); +} + +/*! + * \internal + */ +const QBarDataProxyPrivate *QBarDataProxy::dptrc() const +{ + return static_cast<const QBarDataProxyPrivate *>(d_ptr.data()); +} + +/*! + * \fn void QBarDataProxy::arrayReset() + * + * Emitted when data array is reset. + * If you change the whole array contents without calling resetArray(), you need to + * emit this signal yourself or the graph won't get updated. + */ + +/*! + * \fn void QBarDataProxy::rowsAdded(int startIndex, int count) + * + * Emitted when rows have been added. Provides \a startIndex and \a count of rows added. + * If you add rows directly to the array without calling addRow() or addRows(), you + * need to emit this signal yourself or the graph won't get updated. + */ + +/*! + * \fn void QBarDataProxy::rowsChanged(int startIndex, int count) + * + * Emitted when rows have changed. Provides \a startIndex and \a count of changed rows. + * If you change rows directly in the array without calling setRow() or setRows(), you + * need to emit this signal yourself or the graph won't get updated. + */ + +/*! + * \fn void QBarDataProxy::rowsRemoved(int startIndex, int count) + * + * Emitted when rows have been removed. Provides \a startIndex and \a count of rows removed. + * Index is the current array size if rows were removed from the end of the array. + * If you remove rows directly from the array without calling removeRows(), you + * need to emit this signal yourself or the graph won't get updated. + */ + +/*! + * \fn void QBarDataProxy::rowsInserted(int startIndex, int count) + * + * Emitted when rows have been inserted. Provides \a startIndex and \a count of inserted rows. + * If you insert rows directly into the array without calling insertRow() or insertRows(), you + * need to emit this signal yourself or the graph won't get updated. + */ + +/*! + * \fn void QBarDataProxy::itemChanged(int rowIndex, int columnIndex) + * + * Emitted when an item has changed. Provides \a rowIndex and \a columnIndex of changed item. + * If you change an item directly in the array without calling setItem(), you + * need to emit this signal yourself or the graph won't get updated. + */ + +// QBarDataProxyPrivate + +QBarDataProxyPrivate::QBarDataProxyPrivate(QBarDataProxy *q) + : QAbstractDataProxyPrivate(q, QAbstractDataProxy::DataTypeBar), + m_dataArray(new QBarDataArray) +{ + m_itemLabelFormat = QStringLiteral("@valueTitle: @valueLabel"); +} + +QBarDataProxyPrivate::~QBarDataProxyPrivate() +{ + clearArray(); +} + +void QBarDataProxyPrivate::resetArray(QBarDataArray *newArray, const QStringList *rowLabels, + const QStringList *columnLabels) +{ + if (rowLabels) + qptr()->setRowLabels(*rowLabels); + if (columnLabels) + qptr()->setColumnLabels(*columnLabels); + + if (!newArray) + newArray = new QBarDataArray; + + if (newArray != m_dataArray) { + clearArray(); + m_dataArray = newArray; + } +} + +void QBarDataProxyPrivate::setRow(int rowIndex, QBarDataRow *row, const QString *label) +{ + Q_ASSERT(rowIndex >= 0 && rowIndex < m_dataArray->size()); + + if (label) + fixRowLabels(rowIndex, 1, QStringList(*label), false); + if (row != m_dataArray->at(rowIndex)) { + clearRow(rowIndex); + (*m_dataArray)[rowIndex] = row; + } +} + +void QBarDataProxyPrivate::setRows(int rowIndex, const QBarDataArray &rows, const QStringList *labels) +{ + QBarDataArray &dataArray = *m_dataArray; + Q_ASSERT(rowIndex >= 0 && (rowIndex + rows.size()) <= dataArray.size()); + if (labels) + fixRowLabels(rowIndex, rows.size(), *labels, false); + for (int i = 0; i < rows.size(); i++) { + if (rows.at(i) != dataArray.at(rowIndex)) { + clearRow(rowIndex); + dataArray[rowIndex] = rows.at(i); + } + rowIndex++; + } +} + +void QBarDataProxyPrivate::setItem(int rowIndex, int columnIndex, const QBarDataItem &item) +{ + Q_ASSERT(rowIndex >= 0 && rowIndex < m_dataArray->size()); + QBarDataRow &row = *(*m_dataArray)[rowIndex]; + Q_ASSERT(columnIndex < row.size()); + row[columnIndex] = item; +} + +int QBarDataProxyPrivate::addRow(QBarDataRow *row, const QString *label) +{ + int currentSize = m_dataArray->size(); + if (label) + fixRowLabels(currentSize, 1, QStringList(*label), false); + m_dataArray->append(row); + return currentSize; +} + +int QBarDataProxyPrivate::addRows(const QBarDataArray &rows, const QStringList *labels) +{ + int currentSize = m_dataArray->size(); + if (labels) + fixRowLabels(currentSize, rows.size(), *labels, false); + for (int i = 0; i < rows.size(); i++) + m_dataArray->append(rows.at(i)); + return currentSize; +} + +void QBarDataProxyPrivate::insertRow(int rowIndex, QBarDataRow *row, const QString *label) +{ + Q_ASSERT(rowIndex >= 0 && rowIndex <= m_dataArray->size()); + if (label) + fixRowLabels(rowIndex, 1, QStringList(*label), true); + m_dataArray->insert(rowIndex, row); +} + +void QBarDataProxyPrivate::insertRows(int rowIndex, const QBarDataArray &rows, const QStringList *labels) +{ + Q_ASSERT(rowIndex >= 0 && rowIndex <= m_dataArray->size()); + if (labels) + fixRowLabels(rowIndex, rows.size(), *labels, true); + for (int i = 0; i < rows.size(); i++) + m_dataArray->insert(rowIndex++, rows.at(i)); +} + +void QBarDataProxyPrivate::removeRows(int rowIndex, int removeCount, bool removeLabels) +{ + Q_ASSERT(rowIndex >= 0); + int maxRemoveCount = m_dataArray->size() - rowIndex; + removeCount = qMin(removeCount, maxRemoveCount); + bool labelsChanged = false; + for (int i = 0; i < removeCount; i++) { + clearRow(rowIndex); + m_dataArray->removeAt(rowIndex); + if (removeLabels && m_rowLabels.size() > rowIndex) { + m_rowLabels.removeAt(rowIndex); + labelsChanged = true; + } + } + if (labelsChanged) + emit qptr()->rowLabelsChanged(); +} + +QBarDataProxy *QBarDataProxyPrivate::qptr() +{ + return static_cast<QBarDataProxy *>(q_ptr); +} + +void QBarDataProxyPrivate::clearRow(int rowIndex) +{ + if (m_dataArray->at(rowIndex)) { + delete m_dataArray->at(rowIndex); + (*m_dataArray)[rowIndex] = 0; + } +} + +void QBarDataProxyPrivate::clearArray() +{ + for (int i = 0; i < m_dataArray->size(); i++) + clearRow(i); + m_dataArray->clear(); + delete m_dataArray; +} + +/*! + * \internal + * Fixes the row label array to include specified labels. + */ +void QBarDataProxyPrivate::fixRowLabels(int startIndex, int count, const QStringList &newLabels, bool isInsert) +{ + bool changed = false; + int currentSize = m_rowLabels.size(); + + int newSize = newLabels.size(); + if (startIndex >= currentSize) { + // Adding labels past old label array, create empty strings to fill intervening space + if (newSize) { + for (int i = currentSize; i < startIndex; i++) + m_rowLabels << QString(); + // Doesn't matter if insert, append, or just change when there were no existing + // strings, just append new strings. + m_rowLabels << newLabels; + changed = true; + } + } else { + if (isInsert) { + int insertIndex = startIndex; + if (count) + changed = true; + for (int i = 0; i < count; i++) { + if (i < newSize) + m_rowLabels.insert(insertIndex++, newLabels.at(i)); + else + m_rowLabels.insert(insertIndex++, QString()); + } + } else { + // Either append or change, replace labels up to array end and then add new ones + int lastChangeIndex = count + startIndex; + int newIndex = 0; + for (int i = startIndex; i < lastChangeIndex; i++) { + if (i >= currentSize) { + // Label past the current size, so just append the new label + if (newSize < newIndex) { + changed = true; + m_rowLabels << newLabels.at(newIndex); + } else { + break; // No point appending empty strings, so just exit + } + } else if (newSize > newIndex) { + // Replace existing label + if (m_rowLabels.at(i) != newLabels.at(newIndex)) { + changed = true; + m_rowLabels[i] = newLabels.at(newIndex); + } + } else { + // No more new labels, so clear existing label + if (!m_rowLabels.at(i).isEmpty()) { + changed = true; + m_rowLabels[i] = QString(); + } + } + newIndex++; + } + } + } + if (changed) + emit qptr()->rowLabelsChanged(); +} + +QPair<GLfloat, GLfloat> QBarDataProxyPrivate::limitValues(int startRow, int endRow, + int startColumn, int endColumn) const +{ + QPair<GLfloat, GLfloat> limits = qMakePair(0.0f, 0.0f); + endRow = qMin(endRow, m_dataArray->size() - 1); + for (int i = startRow; i <= endRow; i++) { + QBarDataRow *row = m_dataArray->at(i); + if (row) { + endColumn = qMin(endColumn, row->size() - 1); + for (int j = startColumn; j <= endColumn; j++) { + const QBarDataItem &item = m_dataArray->at(i)->at(j); + qreal itemValue = item.value(); + if (limits.second < itemValue) + limits.second = itemValue; + if (limits.first > itemValue) + limits.first = itemValue; + } + } + } + return limits; +} + +QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavisualization/data/qbardataproxy.h b/src/datavisualization/data/qbardataproxy.h new file mode 100644 index 00000000..758700df --- /dev/null +++ b/src/datavisualization/data/qbardataproxy.h @@ -0,0 +1,130 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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 +** +****************************************************************************/ + +#ifndef QBARDATAPROXY_H +#define QBARDATAPROXY_H + +#include <QtDataVisualization/qabstractdataproxy.h> +#include <QtDataVisualization/qbardataitem.h> +#include <QVector> +#include <QStringList> + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +typedef QVector<QBarDataItem> QBarDataRow; +typedef QList<QBarDataRow *> QBarDataArray; + +class QBarDataProxyPrivate; + +class QT_DATAVISUALIZATION_EXPORT QBarDataProxy : public QAbstractDataProxy +{ + Q_OBJECT + + Q_PROPERTY(int rowCount READ rowCount) + Q_PROPERTY(QStringList rowLabels READ rowLabels WRITE setRowLabels NOTIFY rowLabelsChanged) + Q_PROPERTY(QStringList columnLabels READ columnLabels WRITE setColumnLabels NOTIFY columnLabelsChanged) +public: + explicit QBarDataProxy(QObject *parent = 0); + virtual ~QBarDataProxy(); + + // TODO: Replace first part of class description in docs with this once all TODOs are done: + /* + * QBarDataProxy is optimized for adding, inserting, and removing rows of data. + * Adding a column essentially means modifying every row, which is comparatively very inefficient. + * Proxy is also optimized to use cases where the only defining characteristic of an individual + * bar is its value. Modifying other data that might be added in the future such as color of + * individual bar requires allocating additional data object for the bar. + */ + + int rowCount() const; + + QStringList rowLabels() const; + void setRowLabels(const QStringList &labels); + QStringList columnLabels() const; + void setColumnLabels(const QStringList &labels); + + const QBarDataArray *array() const; + const QBarDataRow *rowAt(int rowIndex) const; + const QBarDataItem *itemAt(int rowIndex, int columnIndex) const; + + void resetArray(); + void resetArray(QBarDataArray *newArray); + void resetArray(QBarDataArray *newArray, const QStringList &rowLabels, + const QStringList &columnLabels); + + void setRow(int rowIndex, QBarDataRow *row); + void setRow(int rowIndex, QBarDataRow *row, const QString &label); + void setRows(int rowIndex, const QBarDataArray &rows); + void setRows(int rowIndex, const QBarDataArray &rows, const QStringList &labels); + + // Setting a column is comparatively inefficient as it changes all rows. + // Can resize rows that are shorter than columnIndex. + // TODO void setColumn(int columnIndex, const QBarDataRow &column); + // TODO void setColumns(int columnIndex, const QBarDataArray &columns); + + void setItem(int rowIndex, int columnIndex, const QBarDataItem &item); + // Change block of items + // TODO setItems(int rowIndex, int columnIndex, QBarDataArray *items); + + int addRow(QBarDataRow *row); + int addRow(QBarDataRow *row, const QString &label); + int addRows(const QBarDataArray &rows); + int addRows(const QBarDataArray &rows, const QStringList &labels); + // TODO int addColumn(const QBarDataRow &column); // returns the index of the added column + // TODO int addColumns(const QBarDataArray &columns); // returns the index of the first added column + + void insertRow(int rowIndex, QBarDataRow *row); + void insertRow(int rowIndex, QBarDataRow *row, const QString &label); + void insertRows(int rowIndex, const QBarDataArray &rows); + void insertRows(int rowIndex, const QBarDataArray &rows, const QStringList &labels); + // TODO void insertColumn(int columnIndex, const QBarDataRow &column); + // TODO void insertColumns(int columnIndex, const QBarDataArray &columns); + + void removeRows(int rowIndex, int removeCount, bool removeLabels = true); + // TODO void removeColumns(int columnIndex, int removeCount); + +signals: + void arrayReset(); + void rowsAdded(int startIndex, int count); + void rowsChanged(int startIndex, int count); + void rowsRemoved(int startIndex, int count); + void rowsInserted(int startIndex, int count); + // TODO void columnsChanged(int startIndex, int count); + // TODO void columnsAdded(int startIndex, int count); + // TODO void columnsRemoved(int startIndex, int count); + // TODO void columnsInserted(int startIndex, int count); + void itemChanged(int rowIndex, int columnIndex); // TODO remove once itemsChanged is added? + // TODO void itemsChanged(int rowIndex, int columnIndex, int rowCount, int columnCount); + + void rowLabelsChanged(); + void columnLabelsChanged(); + +protected: + explicit QBarDataProxy(QBarDataProxyPrivate *d, QObject *parent = 0); + QBarDataProxyPrivate *dptr(); + const QBarDataProxyPrivate *dptrc() const; + +private: + Q_DISABLE_COPY(QBarDataProxy) + + friend class Bars3DController; +}; + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif // QBARDATAPROXY_H diff --git a/src/datavisualization/data/qbardataproxy_p.h b/src/datavisualization/data/qbardataproxy_p.h new file mode 100644 index 00000000..4d51bd5b --- /dev/null +++ b/src/datavisualization/data/qbardataproxy_p.h @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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 +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVisualization API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. + +#ifndef QBARDATAPROXY_P_H +#define QBARDATAPROXY_P_H + +#include "qbardataproxy.h" +#include "qabstractdataproxy_p.h" +#include "qbardataitem.h" + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +class QBarDataProxyPrivate : public QAbstractDataProxyPrivate +{ + Q_OBJECT +public: + QBarDataProxyPrivate(QBarDataProxy *q); + virtual ~QBarDataProxyPrivate(); + + void resetArray(QBarDataArray *newArray, const QStringList *rowLabels, + const QStringList *columnLabels); + void setRow(int rowIndex, QBarDataRow *row, const QString *label); + void setRows(int rowIndex, const QBarDataArray &rows, const QStringList *labels); + void setItem(int rowIndex, int columnIndex, const QBarDataItem &item); + int addRow(QBarDataRow *row, const QString *label); + int addRows(const QBarDataArray &rows, const QStringList *labels); + void insertRow(int rowIndex, QBarDataRow *row, const QString *label); + void insertRows(int rowIndex, const QBarDataArray &rows, const QStringList *labels); + void removeRows(int rowIndex, int removeCount, bool removeLabels); + + QPair<GLfloat, GLfloat> limitValues(int startRow, int startColumn, int rowCount, + int columnCount) const; + +private: + QBarDataProxy *qptr(); + void clearRow(int rowIndex); + void clearArray(); + void fixRowLabels(int startIndex, int count, const QStringList &newLabels, bool isInsert); + + QBarDataArray *m_dataArray; + QStringList m_rowLabels; + QStringList m_columnLabels; + +private: + friend class QBarDataProxy; +}; + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif // QBARDATAPROXY_P_H diff --git a/src/datavisualization/data/qheightmapsurfacedataproxy.cpp b/src/datavisualization/data/qheightmapsurfacedataproxy.cpp new file mode 100644 index 00000000..518e69eb --- /dev/null +++ b/src/datavisualization/data/qheightmapsurfacedataproxy.cpp @@ -0,0 +1,489 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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 "qheightmapsurfacedataproxy_p.h" + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +// Default ranges correspond value axis defaults +const float defaultMinValue = 0.0f; +const float defaultMaxValue = 10.0f; + +/*! + * \class QHeightMapSurfaceDataProxy + * \inmodule QtDataVisualization + * \brief Base proxy class for Q3DSurface. + * \since 1.0.0 + * + * QHeightMapSurfaceDataProxy takes care of surface related height map data handling. It provides a + * way for giving the surface plot a height map to be visualized. + * + * Since height maps do not contain values for X or Z axes, those values need to be given + * separately using minXValue, maxXValue, minZValue, and maxZValue properties. X-value corresponds + * to image horizontal direction and Z-value to the vertical. Setting any of these + * properties triggers asynchronous re-resolving of any existing height map. + * + * \sa QSurfaceDataProxy, {Qt Data Visualization Data Handling} + */ + +/*! + * \qmltype HeightMapSurfaceDataProxy + * \inqmlmodule com.digia.QtDataVisualization 1.0 + * \since com.digia.QtDataVisualization 1.0 + * \ingroup datavisualization_qml + * \instantiates QHeightMapSurfaceDataProxy + * \inherits SurfaceDataProxy + * \brief Base proxy type for Surface3D. + * + * HeightMapSurfaceDataProxy takes care of surface related height map data handling. It provides a + * way for giving the surface plot a height map to be visualized. + * + * For more complete description, see QHeightMapSurfaceDataProxy. + * + * \sa {Qt Data Visualization Data Handling} + */ + +/*! + * \qmlproperty image HeightMapSurfaceDataProxy::heightMap + * + * A height map to be visualized. Setting this property replaces current data with height map data. + * + * There are several formats the image can be given in, but if it is not in a directly usable + * format, a conversion is made. \note If the result seems wrong, the automatic conversion failed + * and you should try converting the image yourself before setting it. Preferred format is + * QImage::Format_RGB32 in grayscale. + * + * The height of the image is read from the red component of the pixels if the image is in grayscale, + * otherwise it is an average calculated from red, green and blue components of the pixels. Using + * grayscale images may improve data conversion speed for large images. + * + * Since height maps do not contain values for X or Z axes, those values need to be given + * separately using minXValue, maxXValue, minZValue, and maxZValue properties. X-value corresponds + * to image horizontal direction and Z-value to the vertical. Setting any of these + * properties triggers asynchronous re-resolving of any existing height map. + * + * Not recommended formats: all mono formats (for example QImage::Format_Mono). + */ + +/*! + * \qmlproperty string HeightMapSurfaceDataProxy::heightMapFile + * + * A file with a height map image to be visualized. Setting this property replaces current data + * with height map data. + * + * \sa heightMap + */ + +/*! + * \qmlproperty qreal HeightMapSurfaceDataProxy::minXValue + * + * The minimum X value for the generated surface points. + * When setting this property the corresponding maximum value is adjusted if necessary, + * to ensure that the range remains valid. + */ + +/*! + * \qmlproperty qreal HeightMapSurfaceDataProxy::maxXValue + * + * The maximum X value for the generated surface points. + * When setting this property the corresponding minimum value is adjusted if necessary, + * to ensure that the range remains valid. + */ + +/*! + * \qmlproperty qreal HeightMapSurfaceDataProxy::minZValue + * + * The minimum Z value for the generated surface points. + * When setting this property the corresponding maximum value is adjusted if necessary, + * to ensure that the range remains valid. + */ + +/*! + * \qmlproperty qreal HeightMapSurfaceDataProxy::maxZValue + * + * The maximum Z value for the generated surface points. + * When setting this property the corresponding minimum value is adjusted if necessary, + * to ensure that the range remains valid. + */ + +/*! + * Constructs QHeightMapSurfaceDataProxy with the given \a parent. + */ +QHeightMapSurfaceDataProxy::QHeightMapSurfaceDataProxy(QObject *parent) : + QSurfaceDataProxy(new QHeightMapSurfaceDataProxyPrivate(this), parent) +{ +} + +/*! + * Constructs QHeightMapSurfaceDataProxy with the given \a image and \a parent. Height map is set + * by calling setHeighMap() with \a image. + * + * \sa heightMap + */ +QHeightMapSurfaceDataProxy::QHeightMapSurfaceDataProxy(const QImage &image, QObject *parent) : + QSurfaceDataProxy(new QHeightMapSurfaceDataProxyPrivate(this), parent) +{ + setHeightMap(image); +} + +/*! + * \internal + */ +QHeightMapSurfaceDataProxy::QHeightMapSurfaceDataProxy( + QHeightMapSurfaceDataProxyPrivate *d, QObject *parent) : + QSurfaceDataProxy(d, parent) +{ +} + +/*! + * Destroys QHeightMapSurfaceDataProxy. + */ +QHeightMapSurfaceDataProxy::~QHeightMapSurfaceDataProxy() +{ +} + +/*! + * \property QHeightMapSurfaceDataProxy::heightMap + * + * A height map to be visualized. Setting this property replaces current data with height map data. + * + * There are several formats the image can be given in, but if it is not in a directly usable + * format, a conversion is made. \note If the result seems wrong, the automatic conversion failed + * and you should try converting the image yourself before setting it. Preferred format is + * QImage::Format_RGB32 in grayscale. + * + * The height of the image is read from the red component of the pixels if the image is in grayscale, + * otherwise it is an average calculated from red, green and blue components of the pixels. Using + * grayscale images may improve data conversion speed for large images. + * + * Not recommended formats: all mono formats (for example QImage::Format_Mono). + * + * The height map is resolved asynchronously. QSurfaceDataProxy::arrayReset() is emitted when the + * data has been resolved. + */ +void QHeightMapSurfaceDataProxy::setHeightMap(const QImage &image) +{ + dptr()->m_heightMap = image; + + // We do resolving asynchronously to make qml onArrayReset handlers actually get the initial reset + if (!dptr()->m_resolveTimer.isActive()) + dptr()->m_resolveTimer.start(0); +} + +QImage QHeightMapSurfaceDataProxy::heightMap() const +{ + return dptrc()->m_heightMap; +} + +/*! + * \property QHeightMapSurfaceDataProxy::heightMapFile + * + * A file with a height map image to be visualized. Setting this property replaces current data + * with height map data. + * + * \sa heightMap + */ +void QHeightMapSurfaceDataProxy::setHeightMapFile(const QString &filename) +{ + dptr()->m_heightMapFile = filename; + setHeightMap(QImage(filename)); +} + +QString QHeightMapSurfaceDataProxy::heightMapFile() const +{ + return dptrc()->m_heightMapFile; +} + +/*! + * A convenience function for setting all minimum (\a minX and \a minZ) and maximum + * (\a maxX and \a maxZ) values at the same time. The minimum values must be smaller than the + * corresponding maximum value. Otherwise the values get adjusted so that they are valid. + */ +void QHeightMapSurfaceDataProxy::setValueRanges(float minX, float maxX, float minZ, float maxZ) +{ + dptr()->setValueRanges(minX, maxX, minZ, maxZ); +} + +/*! + * \property QHeightMapSurfaceDataProxy::minXValue + * + * The minimum X value for the generated surface points. + * When setting this property the corresponding maximum value is adjusted if necessary, + * to ensure that the range remains valid. + */ +void QHeightMapSurfaceDataProxy::setMinXValue(float min) +{ + dptr()->setMinXValue(min); +} + +float QHeightMapSurfaceDataProxy::minXValue() const +{ + return dptrc()->m_minXValue; +} + +/*! + * \property QHeightMapSurfaceDataProxy::maxXValue + * + * The maximum X value for the generated surface points. + * When setting this property the corresponding minimum value is adjusted if necessary, + * to ensure that the range remains valid. + */ +void QHeightMapSurfaceDataProxy::setMaxXValue(float max) +{ + dptr()->setMaxXValue(max); +} + +float QHeightMapSurfaceDataProxy::maxXValue() const +{ + return dptrc()->m_maxXValue; +} + +/*! + * \property QHeightMapSurfaceDataProxy::minZValue + * + * The minimum Z value for the generated surface points. + * When setting this property the corresponding maximum value is adjusted if necessary, + * to ensure that the range remains valid. + */ +void QHeightMapSurfaceDataProxy::setMinZValue(float min) +{ + dptr()->setMinZValue(min); +} + +float QHeightMapSurfaceDataProxy::minZValue() const +{ + return dptrc()->m_minZValue; +} + +/*! + * \property QHeightMapSurfaceDataProxy::maxZValue + * + * The maximum Z value for the generated surface points. + * When setting this property the corresponding minimum value is adjusted if necessary, + * to ensure that the range remains valid. + */ +void QHeightMapSurfaceDataProxy::setMaxZValue(float max) +{ + dptr()->setMaxZValue(max); +} + +float QHeightMapSurfaceDataProxy::maxZValue() const +{ + return dptrc()->m_maxZValue; +} + +/*! + * \internal + */ +QHeightMapSurfaceDataProxyPrivate *QHeightMapSurfaceDataProxy::dptr() +{ + return static_cast<QHeightMapSurfaceDataProxyPrivate *>(d_ptr.data()); +} + +/*! + * \internal + */ +const QHeightMapSurfaceDataProxyPrivate *QHeightMapSurfaceDataProxy::dptrc() const +{ + return static_cast<const QHeightMapSurfaceDataProxyPrivate *>(d_ptr.data()); +} + +// +// QHeightMapSurfaceDataProxyPrivate +// + +QHeightMapSurfaceDataProxyPrivate::QHeightMapSurfaceDataProxyPrivate(QHeightMapSurfaceDataProxy *q) + : QSurfaceDataProxyPrivate(q), + m_minXValue(defaultMinValue), + m_maxXValue(defaultMaxValue), + m_minZValue(defaultMinValue), + m_maxZValue(defaultMaxValue) +{ + m_resolveTimer.setSingleShot(true); + QObject::connect(&m_resolveTimer, &QTimer::timeout, + this, &QHeightMapSurfaceDataProxyPrivate::handlePendingResolve); +} + +QHeightMapSurfaceDataProxyPrivate::~QHeightMapSurfaceDataProxyPrivate() +{ +} + +QHeightMapSurfaceDataProxy *QHeightMapSurfaceDataProxyPrivate::qptr() +{ + return static_cast<QHeightMapSurfaceDataProxy *>(q_ptr); +} + +void QHeightMapSurfaceDataProxyPrivate::setValueRanges(float minX, float maxX, float minZ, float maxZ) +{ + bool changed = false; + if (m_minXValue != minX || m_minZValue != minZ) { + m_minXValue = minX; + m_minZValue = minZ; + changed = true; + } + if (m_maxXValue != maxX || minX >= maxX) { + if (minX >= maxX) { + m_maxXValue = minX + 1.0; + qWarning() << "Warning: Tried to set invalid range for X value range." + " Range automatically adjusted to a valid one:" + << minX << "-" << maxX << "-->" << m_minXValue << "-" << m_maxXValue; + } else { + m_maxXValue = maxX; + } + changed = true; + } + if (m_maxZValue != maxZ || minZ >= maxZ) { + if (minZ >= maxZ) { + m_maxZValue = minZ + 1.0; + qWarning() << "Warning: Tried to set invalid range for Z value range." + " Range automatically adjusted to a valid one:" + << minZ << "-" << maxZ << "-->" << m_minZValue << "-" << m_maxZValue; + } else { + m_maxZValue = maxZ; + } + changed = true; + } + + if (changed && !m_resolveTimer.isActive()) + m_resolveTimer.start(0); +} + +void QHeightMapSurfaceDataProxyPrivate::setMinXValue(float min) +{ + if (min != m_minXValue) { + if (min >= m_maxXValue) { + qreal oldMax = m_maxXValue; + m_maxXValue = min + 1.0; + qWarning() << "Warning: Tried to set minimum X to equal or larger than maximum X for" + " value range. Maximum automatically adjusted to a valid one:" + << oldMax << "-->" << m_maxXValue; + } + m_minXValue = min; + + if (!m_resolveTimer.isActive()) + m_resolveTimer.start(0); + } +} + +void QHeightMapSurfaceDataProxyPrivate::setMaxXValue(float max) +{ + if (m_maxXValue != max) { + if (max <= m_minXValue) { + qreal oldMin = m_minXValue; + m_minXValue = max - 1.0; + qWarning() << "Warning: Tried to set maximum X to equal or smaller than minimum X for" + " value range. Minimum automatically adjusted to a valid one:" + << oldMin << "-->" << m_minXValue; + } + m_maxXValue = max; + + if (!m_resolveTimer.isActive()) + m_resolveTimer.start(0); + } +} + +void QHeightMapSurfaceDataProxyPrivate::setMinZValue(float min) +{ + if (min != m_minZValue) { + if (min >= m_maxZValue) { + qreal oldMax = m_maxZValue; + m_maxZValue = min + 1.0; + qWarning() << "Warning: Tried to set minimum Z to equal or larger than maximum Z for" + " value range. Maximum automatically adjusted to a valid one:" + << oldMax << "-->" << m_maxZValue; + } + m_minZValue = min; + + if (!m_resolveTimer.isActive()) + m_resolveTimer.start(0); + } +} + +void QHeightMapSurfaceDataProxyPrivate::setMaxZValue(float max) +{ + if (m_maxZValue != max) { + if (max <= m_minZValue) { + qreal oldMin = m_minZValue; + m_minZValue = max - 1.0; + qWarning() << "Warning: Tried to set maximum Z to equal or smaller than minimum Z for" + " value range. Minimum automatically adjusted to a valid one:" + << oldMin << "-->" << m_minZValue; + } + m_maxZValue = max; + + if (!m_resolveTimer.isActive()) + m_resolveTimer.start(0); + } +} + +void QHeightMapSurfaceDataProxyPrivate::handlePendingResolve() +{ + QImage heightImage = m_heightMap; + // Convert to RGB32 to be sure we're reading the right bytes + if (heightImage.format() != QImage::Format_RGB32) + heightImage = heightImage.convertToFormat(QImage::Format_RGB32); + + uchar *bits = heightImage.bits(); + + int imageHeight = heightImage.height(); + int imageWidth = heightImage.width(); + int bitCount = imageWidth * 4 * (imageHeight - 1); + int widthBits = imageWidth * 4; + float height = 0; + + // Do not recreate array if dimensions have not changed + QSurfaceDataArray *dataArray = m_dataArray; + if (imageWidth != qptr()->columnCount() || imageHeight != dataArray->size()) { + dataArray = new QSurfaceDataArray; + dataArray->reserve(imageHeight); + for (int i = 0; i < imageHeight; i++) { + QSurfaceDataRow *newProxyRow = new QSurfaceDataRow(imageWidth); + dataArray->append(newProxyRow); + } + } + + float xMul = (m_maxXValue - m_minXValue) / float(imageWidth - 1); + float zMul = (m_maxZValue - m_minZValue) / float(imageHeight - 1); + + if (heightImage.isGrayscale()) { + // Grayscale, it's enough to read Red byte + for (int i = 0; i < imageHeight; i++, bitCount -= widthBits) { + QSurfaceDataRow &newRow = *dataArray->at(i); + for (int j = 0; j < imageWidth; j++) + newRow[j].setPosition(QVector3D((float(j) * xMul) + m_minXValue, float(bits[bitCount + (j * 4)]), + (float(i) * zMul) + m_minZValue)); + } + } else { + // Not grayscale, we'll need to calculate height from RGB + for (int i = 0; i < imageHeight; i++, bitCount -= widthBits) { + QSurfaceDataRow &newRow = *dataArray->at(i); + for (int j = 0; j < imageWidth; j++) { + int nextpixel = j * 4; + height = (float(bits[bitCount + nextpixel]) + + float(bits[1 + bitCount + nextpixel]) + + float(bits[2 + bitCount + nextpixel])); + newRow[j].setPosition(QVector3D((float(j) * xMul) + m_minXValue, height / 3.0f, + (float(i) * zMul) + m_minZValue)); + } + } + } + + qptr()->resetArray(dataArray); +} + +QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavisualization/data/qheightmapsurfacedataproxy.h b/src/datavisualization/data/qheightmapsurfacedataproxy.h new file mode 100644 index 00000000..3306059f --- /dev/null +++ b/src/datavisualization/data/qheightmapsurfacedataproxy.h @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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 +** +****************************************************************************/ + +#ifndef QHEIGHTMAPSURFACEDATAPROXY_H +#define QHEIGHTMAPSURFACEDATAPROXY_H + +#include <QtDataVisualization/qsurfacedataproxy.h> + +#include <QImage> + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +class QHeightMapSurfaceDataProxyPrivate; + +class QT_DATAVISUALIZATION_EXPORT QHeightMapSurfaceDataProxy : public QSurfaceDataProxy +{ + Q_OBJECT + + Q_PROPERTY(QImage heightMap READ heightMap WRITE setHeightMap) + Q_PROPERTY(QString heightMapFile READ heightMapFile WRITE setHeightMapFile) + Q_PROPERTY(float minXValue READ minXValue WRITE setMinXValue) + Q_PROPERTY(float maxXValue READ maxXValue WRITE setMaxXValue) + Q_PROPERTY(float minZValue READ minZValue WRITE setMinZValue) + Q_PROPERTY(float maxZValue READ maxZValue WRITE setMaxZValue) + +public: + explicit QHeightMapSurfaceDataProxy(QObject *parent = 0); + explicit QHeightMapSurfaceDataProxy(const QImage &image, QObject *parent = 0); + virtual ~QHeightMapSurfaceDataProxy(); + + void setHeightMap(const QImage &image); + QImage heightMap() const; + + void setHeightMapFile(const QString &filename); + QString heightMapFile() const; + + void setValueRanges(float minX, float maxX, float minZ, float maxZ); + void setMinXValue(float min); + float minXValue() const; + void setMaxXValue(float max); + float maxXValue() const; + void setMinZValue(float min); + float minZValue() const; + void setMaxZValue(float max); + float maxZValue() const; + +protected: + explicit QHeightMapSurfaceDataProxy(QHeightMapSurfaceDataProxyPrivate *d, QObject *parent = 0); + QHeightMapSurfaceDataProxyPrivate *dptr(); + const QHeightMapSurfaceDataProxyPrivate *dptrc() const; + +private: + Q_DISABLE_COPY(QHeightMapSurfaceDataProxy) + + friend class Surface3DController; +}; + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif diff --git a/src/datavisualization/data/qheightmapsurfacedataproxy_p.h b/src/datavisualization/data/qheightmapsurfacedataproxy_p.h new file mode 100644 index 00000000..2d773344 --- /dev/null +++ b/src/datavisualization/data/qheightmapsurfacedataproxy_p.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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 +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVisualization API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. + +#ifndef QHEIGHTMAPSURFACEDATAPROXY_P_H +#define QHEIGHTMAPSURFACEDATAPROXY_P_H + +#include "qheightmapsurfacedataproxy.h" +#include "qsurfacedataproxy_p.h" +#include <QTimer> + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +class QHeightMapSurfaceDataProxyPrivate : public QSurfaceDataProxyPrivate +{ + Q_OBJECT + +public: + QHeightMapSurfaceDataProxyPrivate(QHeightMapSurfaceDataProxy *q); + virtual ~QHeightMapSurfaceDataProxyPrivate(); + + void setValueRanges(float minX, float maxX, float minZ, float maxZ); + void setMinXValue(float min); + void setMaxXValue(float max); + void setMinZValue(float min); + void setMaxZValue(float max); +private: + QHeightMapSurfaceDataProxy *qptr(); + void handlePendingResolve(); + + QImage m_heightMap; + QString m_heightMapFile; + QTimer m_resolveTimer; + + float m_minXValue; + float m_maxXValue; + float m_minZValue; + float m_maxZValue; + + friend class QHeightMapSurfaceDataProxy; +}; + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif diff --git a/src/datavisualization/data/qitemmodelbardatamapping.cpp b/src/datavisualization/data/qitemmodelbardatamapping.cpp new file mode 100644 index 00000000..fc6f8f54 --- /dev/null +++ b/src/datavisualization/data/qitemmodelbardatamapping.cpp @@ -0,0 +1,407 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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 "qitemmodelbardatamapping_p.h" + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +/*! + * \class QItemModelBarDataMapping + * \inmodule QtDataVisualization + * \brief Item model mapping for Q3DBars. + * \since 1.0.0 + * + * QItemModelBarDataMapping is used to map roles of QAbstractItemModel to rows, columns, and values + * of Q3DBars. There are three ways to use QItemModelBarDataMapping: + * + * 1) If useModelCategories property is set to true, QItemModelBarDataMapping will map rows and + * columns of QAbstractItemModel to rows and columns of Q3DBars, and uses the value returned for + * Qt::DisplayRole as bar value by default. + * The value role to be used can be redefined if Qt::DisplayRole is not suitable. + * + * 2) For models that do not have data already neatly sorted into rows and columns, such as + * QAbstractListModel based models, you can define a role from the model to map for each of row, + * column and value. + * + * 3) If you do not want to include all data contained in the model, or the autogenerated rows and + * columns are not ordered as you wish, you can specify which rows and columns should be included + * and in which order by defining an explicit list of categories for either or both of rows and + * columns. + * + * For example, assume that you have a custom QAbstractItemModel for storing various monthly values + * related to a business. + * Each item in the model has roles "year", "month", "income", and "expenses". + * You could do the following to display the data in a bar graph: + * + * \snippet doc_src_qtdatavisualization.cpp 3 + * + * \sa QItemModelBarDataProxy, {Qt Data Visualization Data Handling} + */ + +/*! + * \qmltype BarDataMapping + * \inqmlmodule com.digia.QtDataVisualization 1.0 + * \since com.digia.QtDataVisualization 1.0 + * \ingroup datavisualization_qml + * \instantiates QItemModelBarDataMapping + * \brief Item model mapping for Bars3D. + * + * This type is used to map roles of AbstractItemModel to rows, columns, and values of Bars3D. For + * more complete description, see QItemModelBarDataMapping. + * + * Usage example: + * + * \snippet doc_src_qmldatavisualization.cpp 4 + * + * \sa ItemModelBarDataProxy, {Qt Data Visualization Data Handling} + */ + +/*! + * \qmlproperty string BarDataMapping::rowRole + * The row role of the mapping. + */ + +/*! + * \qmlproperty string BarDataMapping::columnRole + * The column role of the mapping. + */ + +/*! + * \qmlproperty string BarDataMapping::valueRole + * The value role of the mapping. + */ + +/*! + * \qmlproperty list BarDataMapping::rowCategories + * The row categories of the mapping. Only items with row roles that are found in this list are + * included when data is resolved. The rows are ordered in the same order as they are in this list. + */ + +/*! + * \qmlproperty list BarDataMapping::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. + */ + +/*! + * \qmlproperty list BarDataMapping::useModelCategories + * When set to true, the mapping ignores row and column roles and categories, and uses + * the rows and columns from the model instead. Defaults to false. + */ + +/*! + * \qmlproperty list BarDataMapping::autoRowCategories + * When set to true, the mapping ignores any explicitly set row categories + * and overwrites them with automatically generated ones whenever the + * data from model is resolved. Defaults to true. + */ + +/*! + * \qmlproperty list BarDataMapping::autoColumnCategories + * When set to true, the mapping ignores any explicitly set column categories + * and overwrites them with automatically generated ones whenever the + * data from model is resolved. Defaults to true. + */ + +/*! + * Constructs QItemModelBarDataMapping with the given \a parent. + */ +QItemModelBarDataMapping::QItemModelBarDataMapping(QObject *parent) + : QAbstractDataMapping(new QItemModelBarDataMappingPrivate(this), parent) +{ +} + +/*! + * Constructs QItemModelBarDataMapping with \a valueRole and the given \a parent. + * This constructor is meant to be used with models that have data properly sorted + * in rows and columns already, so it also sets useModelCategories property to true. + */ +QItemModelBarDataMapping::QItemModelBarDataMapping(const QString &valueRole, QObject *parent) + : QAbstractDataMapping(new QItemModelBarDataMappingPrivate(this), parent) +{ + dptr()->m_valueRole = valueRole; + dptr()->m_useModelCategories = true; +} + +/*! + * Constructs QItemModelBarDataMapping with \a rowRole, \a columnRole, \a valueRole + * and the given \a parent. + */ +QItemModelBarDataMapping::QItemModelBarDataMapping(const QString &rowRole, + const QString &columnRole, + const QString &valueRole, + QObject *parent) + : QAbstractDataMapping(new QItemModelBarDataMappingPrivate(this), parent) +{ + dptr()->m_rowRole = rowRole; + dptr()->m_columnRole = columnRole; + dptr()->m_valueRole = valueRole; +} + +/*! + * Constructs QItemModelBarDataMapping with \a rowRole, \a columnRole, \a valueRole, + * \a rowCategories, \a columnCategories and the given \a parent. This constructor + * also sets autoRowCategories and autoColumnCategories to false. + */ +QItemModelBarDataMapping::QItemModelBarDataMapping(const QString &rowRole, + const QString &columnRole, + const QString &valueRole, + const QStringList &rowCategories, + const QStringList &columnCategories, + QObject *parent) + : QAbstractDataMapping(new QItemModelBarDataMappingPrivate(this), parent) +{ + dptr()->m_rowRole = rowRole; + dptr()->m_columnRole = columnRole; + dptr()->m_valueRole = valueRole; + dptr()->m_rowCategories = rowCategories; + dptr()->m_columnCategories = columnCategories; + dptr()->m_autoRowCategories = false; + dptr()->m_autoColumnCategories = false; +} + +/*! + * Destroys QItemModelBarDataMapping. + */ +QItemModelBarDataMapping::~QItemModelBarDataMapping() +{ +} + +/*! + * \property QItemModelBarDataMapping::rowRole + * + * Defines the row role for the mapping. + */ +void QItemModelBarDataMapping::setRowRole(const QString &role) +{ + if (dptr()->m_rowRole != role) { + dptr()->m_rowRole = role; + emit mappingChanged(); + } +} + +QString QItemModelBarDataMapping::rowRole() const +{ + return dptrc()->m_rowRole; +} + +/*! + * \property QItemModelBarDataMapping::columnRole + * + * Defines the column role for the mapping. + */ +void QItemModelBarDataMapping::setColumnRole(const QString &role) +{ + if (dptr()->m_columnRole != role) { + dptr()->m_columnRole = role; + emit mappingChanged(); + } +} + +QString QItemModelBarDataMapping::columnRole() const +{ + return dptrc()->m_columnRole; +} + +/*! + * \property QItemModelBarDataMapping::valueRole + * + * Defines the value role for the mapping. + */ +void QItemModelBarDataMapping::setValueRole(const QString &role) +{ + if (dptr()->m_valueRole != role) { + dptr()->m_valueRole = role; + emit mappingChanged(); + } +} + +QString QItemModelBarDataMapping::valueRole() const +{ + return dptrc()->m_valueRole; +} + +/*! + * \property QItemModelBarDataMapping::rowCategories + * + * Defines the row categories for the mapping. + */ +void QItemModelBarDataMapping::setRowCategories(const QStringList &categories) +{ + if (dptr()->m_rowCategories != categories) { + dptr()->m_rowCategories = categories; + emit mappingChanged(); + } +} + +QStringList QItemModelBarDataMapping::rowCategories() const +{ + return dptrc()->m_rowCategories; +} + +/*! + * \property QItemModelBarDataMapping::columnCategories + * + * Defines the column categories for the mapping. + */ +void QItemModelBarDataMapping::setColumnCategories(const QStringList &categories) +{ + if (dptr()->m_columnCategories != categories) { + dptr()->m_columnCategories = categories; + emit mappingChanged(); + } +} + +QStringList QItemModelBarDataMapping::columnCategories() const +{ + return dptrc()->m_columnCategories; +} + +/*! + * \property QItemModelBarDataMapping::useModelCategories + * + * When set to true, the mapping ignores row and column roles and categories, and uses + * the rows and columns from the model instead. Defaults to false. + */ +void QItemModelBarDataMapping::setUseModelCategories(bool enable) +{ + if (dptr()->m_useModelCategories != enable) { + dptr()->m_useModelCategories = enable; + emit mappingChanged(); + } +} + +bool QItemModelBarDataMapping::useModelCategories() const +{ + return dptrc()->m_useModelCategories; +} + +/*! + * \property QItemModelBarDataMapping::autoRowCategories + * + * When set to true, the mapping ignores any explicitly set row categories + * and overwrites them with automatically generated ones whenever the + * data from model is resolved. Defaults to true. + */ +void QItemModelBarDataMapping::setAutoRowCategories(bool enable) +{ + if (dptr()->m_autoRowCategories != enable) { + dptr()->m_autoRowCategories = enable; + emit mappingChanged(); + } +} + +bool QItemModelBarDataMapping::autoRowCategories() const +{ + return dptrc()->m_autoRowCategories; +} + +/*! + * \property QItemModelBarDataMapping::autoColumnCategories + * + * When set to true, the mapping ignores any explicitly set column categories + * and overwrites them with automatically generated ones whenever the + * data from model is resolved. Defaults to true. + */ +void QItemModelBarDataMapping::setAutoColumnCategories(bool enable) +{ + if (dptr()->m_autoColumnCategories != enable) { + dptr()->m_autoColumnCategories = enable; + emit mappingChanged(); + } +} + +bool QItemModelBarDataMapping::autoColumnCategories() const +{ + return dptrc()->m_autoColumnCategories; +} + +/*! + * Changes \a rowRole, \a columnRole, \a valueRole, \a rowCategories and \a columnCategories to the + * mapping. + */ +void QItemModelBarDataMapping::remap(const QString &rowRole, + const QString &columnRole, + const QString &valueRole, + const QStringList &rowCategories, + const QStringList &columnCategories) +{ + dptr()->m_rowRole = rowRole; + dptr()->m_columnRole = columnRole; + dptr()->m_valueRole = valueRole; + dptr()->m_rowCategories = rowCategories; + dptr()->m_columnCategories = columnCategories; + + emit mappingChanged(); +} + +/*! + * /return index of the specified \a category in row categories list. + * If the row categories list is empty, -1 is returned. + * \note If the automatic row categories generation is in use, this method will + * not return valid index before the data in the model is resolved for the first time. + */ +int QItemModelBarDataMapping::rowCategoryIndex(const QString &category) +{ + return dptr()->m_rowCategories.indexOf(category); +} + +/*! + * /return index of the specified \a category in column categories list. + * If the category is not found, -1 is returned. + * \note If the automatic column categories generation is in use, this method will + * not return valid index before the data in the model is resolved for the first time. + */ +int QItemModelBarDataMapping::columnCategoryIndex(const QString &category) +{ + return dptr()->m_columnCategories.indexOf(category); +} + +/*! + * \internal + */ +QItemModelBarDataMappingPrivate *QItemModelBarDataMapping::dptr() +{ + return static_cast<QItemModelBarDataMappingPrivate *>(d_ptr.data()); +} + +/*! + * \internal + */ +const QItemModelBarDataMappingPrivate *QItemModelBarDataMapping::dptrc() const +{ + return static_cast<const QItemModelBarDataMappingPrivate *>(d_ptr.data()); +} + +// QItemModelBarDataMappingPrivate + +QItemModelBarDataMappingPrivate::QItemModelBarDataMappingPrivate(QItemModelBarDataMapping *q) + : QAbstractDataMappingPrivate(q, QAbstractDataProxy::DataTypeBar), + m_useModelCategories(false), + m_autoRowCategories(true), + m_autoColumnCategories(true) +{ +} + +QItemModelBarDataMappingPrivate::~QItemModelBarDataMappingPrivate() +{ +} + + +QT_DATAVISUALIZATION_END_NAMESPACE + diff --git a/src/datavisualization/data/qitemmodelbardatamapping.h b/src/datavisualization/data/qitemmodelbardatamapping.h new file mode 100644 index 00000000..a5ef33b8 --- /dev/null +++ b/src/datavisualization/data/qitemmodelbardatamapping.h @@ -0,0 +1,90 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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 +** +****************************************************************************/ + +#ifndef QITEMMODELBARDATAMAPPING_H +#define QITEMMODELBARDATAMAPPING_H + +#include <QtDataVisualization/qdatavisualizationenums.h> +#include <QtDataVisualization/qabstractdatamapping.h> +#include <QStringList> + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +class QItemModelBarDataMappingPrivate; + +class QT_DATAVISUALIZATION_EXPORT QItemModelBarDataMapping : public QAbstractDataMapping +{ + Q_OBJECT + Q_PROPERTY(QString rowRole READ rowRole WRITE setRowRole) + Q_PROPERTY(QString columnRole READ columnRole WRITE setColumnRole) + Q_PROPERTY(QString valueRole READ valueRole WRITE setValueRole) + Q_PROPERTY(QStringList rowCategories READ rowCategories WRITE setRowCategories) + Q_PROPERTY(QStringList columnCategories READ columnCategories WRITE setColumnCategories) + Q_PROPERTY(bool useModelCategories READ useModelCategories WRITE setUseModelCategories) + Q_PROPERTY(bool autoRowCategories READ autoRowCategories WRITE setAutoRowCategories) + Q_PROPERTY(bool autoColumnCategories READ autoColumnCategories WRITE setAutoColumnCategories) + +public: + explicit QItemModelBarDataMapping(QObject *parent = 0); + QItemModelBarDataMapping(const QString &valueRole, QObject *parent = 0); + QItemModelBarDataMapping(const QString &rowRole, const QString &columnRole, + const QString &valueRole, QObject *parent = 0); + QItemModelBarDataMapping(const QString &rowRole, const QString &columnRole, + const QString &valueRole, const QStringList &rowCategories, + const QStringList &columnCategories, QObject *parent = 0); + virtual ~QItemModelBarDataMapping(); + + void setRowRole(const QString &role); + QString rowRole() const; + void setColumnRole(const QString &role); + QString columnRole() const; + void setValueRole(const QString &role); + QString valueRole() const; + + void setRowCategories(const QStringList &categories); + QStringList rowCategories() const; + void setColumnCategories(const QStringList &categories); + QStringList columnCategories() const; + + void setUseModelCategories(bool enable); + bool useModelCategories() const; + void setAutoRowCategories(bool enable); + bool autoRowCategories() const; + void setAutoColumnCategories(bool enable); + bool autoColumnCategories() const; + + void remap(const QString &rowRole, const QString &columnRole, + const QString &valueRole, const QStringList &rowCategories, + const QStringList &columnCategories); + + Q_INVOKABLE int rowCategoryIndex(const QString& category); + Q_INVOKABLE int columnCategoryIndex(const QString& category); + +protected: + QItemModelBarDataMappingPrivate *dptr(); + const QItemModelBarDataMappingPrivate *dptrc() const; + +private: + Q_DISABLE_COPY(QItemModelBarDataMapping) + + friend class BarItemModelHandler; +}; + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif diff --git a/src/datavisualization/data/qitemmodelbardatamapping_p.h b/src/datavisualization/data/qitemmodelbardatamapping_p.h new file mode 100644 index 00000000..90a17fdb --- /dev/null +++ b/src/datavisualization/data/qitemmodelbardatamapping_p.h @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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 +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVisualization API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. + +#include "qitemmodelbardatamapping.h" +#include "qabstractdatamapping_p.h" + +#ifndef QITEMMODELBARDATAMAPPING_P_H +#define QITEMMODELBARDATAMAPPING_P_H + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +class QItemModelBarDataMappingPrivate : public QAbstractDataMappingPrivate +{ + Q_OBJECT +public: + QItemModelBarDataMappingPrivate(QItemModelBarDataMapping *q); + virtual ~QItemModelBarDataMappingPrivate(); + +private: + QString m_rowRole; + QString m_columnRole; + QString m_valueRole; + + // For row/column items, sort items into these categories. Other categories are ignored. + QStringList m_rowCategories; + QStringList m_columnCategories; + + bool m_useModelCategories; + bool m_autoRowCategories; + bool m_autoColumnCategories; + + friend class QItemModelBarDataMapping; + friend class BarItemModelHandler; +}; + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif diff --git a/src/datavisualization/data/qitemmodelbardataproxy.cpp b/src/datavisualization/data/qitemmodelbardataproxy.cpp new file mode 100644 index 00000000..b0fa74b6 --- /dev/null +++ b/src/datavisualization/data/qitemmodelbardataproxy.cpp @@ -0,0 +1,198 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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 "qitemmodelbardataproxy_p.h" +#include "baritemmodelhandler_p.h" +#include <QTimer> + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +/*! + * \class QItemModelBarDataProxy + * \inmodule QtDataVisualization + * \brief Proxy class for presenting data in item models with Q3DBars. + * \since 1.0.0 + * + * QItemModelBarDataProxy allows you to use QAbstractItemModel derived models as a data source + * for Q3DBars. It uses QItemModelBarDataMapping instance to map data from the model to Q3DBars + * graph. + * + * Data is resolved asynchronously whenever the mapping or the model changes. + * QBarDataProxy::arrayReset() is emitted when the data has been resolved. + * + * \sa QItemModelBarDataMapping, {Qt Data Visualization Data Handling} + */ + +/*! + * \qmltype ItemModelBarDataProxy + * \inqmlmodule com.digia.QtDataVisualization 1.0 + * \since com.digia.QtDataVisualization 1.0 + * \ingroup datavisualization_qml + * \instantiates QItemModelBarDataProxy + * \inherits BarDataProxy + * \brief Proxy class for presenting data in item models with Bars3D. + * + * This type allows you to use AbstractItemModel derived models as a data source for Bars3D. + * + * Data is resolved asynchronously whenever the mapping or the model changes. + * QBarDataProxy::arrayReset() is emitted when the data has been resolved. + * + * Usage example: + * + * \snippet doc_src_qmldatavisualization.cpp 7 + * + * \sa BarDataProxy, BarDataMapping, {Qt Data Visualization Data Handling} + */ + +/*! + * \qmlproperty list ItemModelBarDataProxy::itemModel + * The item model. + */ + +/*! + * \qmlproperty list ItemModelBarDataProxy::activeMapping + * The active mapping. Modifying a mapping that is set to the proxy will trigger data set + * re-resolving. + */ + +/*! + * Constructs QItemModelBarDataProxy. + */ +QItemModelBarDataProxy::QItemModelBarDataProxy() : + QBarDataProxy(new QItemModelBarDataProxyPrivate(this)) +{ +} + +/*! + * Constructs QItemModelBarDataProxy with \a itemModel and \a mapping. Proxy takes ownership of the + * \a mapping, but doesn't take ownership of the \a itemModel, as typically item models are owned + * by other controls. + */ +QItemModelBarDataProxy::QItemModelBarDataProxy(const QAbstractItemModel *itemModel, + QItemModelBarDataMapping *mapping) : + QBarDataProxy(new QItemModelBarDataProxyPrivate(this)) +{ + dptr()->m_itemModelHandler->setItemModel(itemModel); + dptr()->m_itemModelHandler->setActiveMapping(mapping); +} + +/*! + * Destroys QItemModelBarDataProxy. + */ +QItemModelBarDataProxy::~QItemModelBarDataProxy() +{ +} + +/*! + * \property QItemModelBarDataProxy::itemModel + * + * Defines item model. Does not take ownership of the model, but does connect to it to listen for + * changes. + */ +void QItemModelBarDataProxy::setItemModel(const QAbstractItemModel *itemModel) +{ + dptr()->m_itemModelHandler->setItemModel(itemModel); +} + +const QAbstractItemModel *QItemModelBarDataProxy::itemModel() const +{ + return dptrc()->m_itemModelHandler->itemModel(); +} + +/*! + * \property QItemModelBarDataProxy::activeMapping + * + * Defines data mapping. Proxy takes ownership of the \a mapping. + * Modifying a mapping that is set to the proxy will trigger data set re-resolving. + */ +void QItemModelBarDataProxy::setActiveMapping(QItemModelBarDataMapping *mapping) +{ + dptr()->m_itemModelHandler->setActiveMapping(mapping); +} + +QItemModelBarDataMapping *QItemModelBarDataProxy::activeMapping() const +{ + return static_cast<QItemModelBarDataMapping *>(dptrc()->m_itemModelHandler->activeMapping()); +} + +/*! + * Transfers the ownership of the \a mapping to this proxy. The mapping is not taken to use yet. + * \sa setActiveMapping(), releaseMapping() + */ +void QItemModelBarDataProxy::addMapping(QItemModelBarDataMapping *mapping) +{ + dptr()->m_itemModelHandler->addMapping(mapping); +} + +/*! + * Releases the ownership of the \a mapping back to the caller. If the mapping was the currently + * active one, no mapping remains active after this call. + */ +void QItemModelBarDataProxy::releaseMapping(QItemModelBarDataMapping *mapping) +{ + dptr()->m_itemModelHandler->releaseMapping(mapping); +} + +/*! + * \return list of mappings owned by the proxy. + */ +QList<QItemModelBarDataMapping *> QItemModelBarDataProxy::mappings() const +{ + QList<QItemModelBarDataMapping *> retList; + QList<QAbstractDataMapping *> abstractList = dptrc()->m_itemModelHandler->mappings(); + foreach (QAbstractDataMapping *mapping, abstractList) + retList.append(static_cast<QItemModelBarDataMapping *>(mapping)); + + return retList; +} + +/*! + * \internal + */ +QItemModelBarDataProxyPrivate *QItemModelBarDataProxy::dptr() +{ + return static_cast<QItemModelBarDataProxyPrivate *>(d_ptr.data()); +} + +/*! + * \internal + */ +const QItemModelBarDataProxyPrivate *QItemModelBarDataProxy::dptrc() const +{ + return static_cast<const QItemModelBarDataProxyPrivate *>(d_ptr.data()); +} + +// QItemModelBarDataProxyPrivate + +QItemModelBarDataProxyPrivate::QItemModelBarDataProxyPrivate(QItemModelBarDataProxy *q) + : QBarDataProxyPrivate(q), + m_itemModelHandler(new BarItemModelHandler(q)) +{ +} + +QItemModelBarDataProxyPrivate::~QItemModelBarDataProxyPrivate() +{ + delete m_itemModelHandler; +} + +QItemModelBarDataProxy *QItemModelBarDataProxyPrivate::qptr() +{ + return static_cast<QItemModelBarDataProxy *>(q_ptr); +} + +QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavisualization/data/qitemmodelbardataproxy.h b/src/datavisualization/data/qitemmodelbardataproxy.h new file mode 100644 index 00000000..2a96f0c8 --- /dev/null +++ b/src/datavisualization/data/qitemmodelbardataproxy.h @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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 +** +****************************************************************************/ + +#ifndef QITEMMODELBARDATAPROXY_H +#define QITEMMODELBARDATAPROXY_H + +#include <QtDataVisualization/qbardataproxy.h> +#include <QtDataVisualization/qitemmodelbardatamapping.h> +#include <QAbstractItemModel> +#include <QStringList> + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +class QItemModelBarDataProxyPrivate; + +class QT_DATAVISUALIZATION_EXPORT QItemModelBarDataProxy : public QBarDataProxy +{ + Q_OBJECT + Q_PROPERTY(const QAbstractItemModel* itemModel READ itemModel WRITE setItemModel) + Q_PROPERTY(QItemModelBarDataMapping* activeMapping READ activeMapping WRITE setActiveMapping) + +public: + explicit QItemModelBarDataProxy(); + explicit QItemModelBarDataProxy(const QAbstractItemModel *itemModel, + QItemModelBarDataMapping *mapping); + virtual ~QItemModelBarDataProxy(); + + void setItemModel(const QAbstractItemModel *itemModel); + const QAbstractItemModel *itemModel() const; + + void setActiveMapping(QItemModelBarDataMapping *mapping); + QItemModelBarDataMapping *activeMapping() const; + void addMapping(QItemModelBarDataMapping *mapping); + void releaseMapping(QItemModelBarDataMapping *mapping); + QList<QItemModelBarDataMapping *> mappings() const; + +protected: + QItemModelBarDataProxyPrivate *dptr(); + const QItemModelBarDataProxyPrivate *dptrc() const; + +private: + Q_DISABLE_COPY(QItemModelBarDataProxy) +}; + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif diff --git a/src/datavisualization/data/qitemmodelbardataproxy_p.h b/src/datavisualization/data/qitemmodelbardataproxy_p.h new file mode 100644 index 00000000..fc646f0d --- /dev/null +++ b/src/datavisualization/data/qitemmodelbardataproxy_p.h @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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 +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVisualization API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. + +#ifndef QITEMMODELBARDATAPROXY_P_H +#define QITEMMODELBARDATAPROXY_P_H + +#include "qitemmodelbardataproxy.h" +#include "qbardataproxy_p.h" +#include <QPointer> +#include <QTimer> + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +class BarItemModelHandler; + +class QItemModelBarDataProxyPrivate : public QBarDataProxyPrivate +{ + Q_OBJECT +public: + QItemModelBarDataProxyPrivate(QItemModelBarDataProxy *q); + virtual ~QItemModelBarDataProxyPrivate(); + +private: + QItemModelBarDataProxy *qptr(); + + BarItemModelHandler *m_itemModelHandler; + + friend class QItemModelBarDataProxy; +}; + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif diff --git a/src/datavisualization/data/qitemmodelscatterdatamapping.cpp b/src/datavisualization/data/qitemmodelscatterdatamapping.cpp new file mode 100644 index 00000000..f9ef6d04 --- /dev/null +++ b/src/datavisualization/data/qitemmodelscatterdatamapping.cpp @@ -0,0 +1,200 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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 "qitemmodelscatterdatamapping_p.h" + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +/*! + * \class QItemModelScatterDataMapping + * \inmodule QtDataVisualization + * \brief Item model mapping for Q3DScatter. + * \since 1.0.0 + * + * QItemModelScatterDataMapping is used to map roles of QAbstractItemModel to the XYZ-values + * of Q3DScatter points. + * + * QItemModelScatterDataMapping ignores rows and columns of the QAbstractItemModel and treats + * all items equally. It requires the model to provide at least three roles for the data items + * that can be mapped to X, Y, and Z-values for the scatter points. + * + * For example, assume that you have a custom QAbstractItemModel for storing various measurements + * done on material samples, providing data for roles such as "density", "hardness" and + * "conductivity". You could visualize these properties on a scatter graph: + * + * \snippet doc_src_qtdatavisualization.cpp 4 + * + * \sa QItemModelScatterDataProxy, {Qt Data Visualization Data Handling} + */ + +/*! + * \qmltype ScatterDataMapping + * \inqmlmodule com.digia.QtDataVisualization 1.0 + * \since com.digia.QtDataVisualization 1.0 + * \ingroup datavisualization_qml + * \instantiates QItemModelScatterDataMapping + * \brief Item model mapping for Scatter3D. + * + * This type is used to map roles of AbstractItemModel to the XYZ-values of Scatter3D points. For + * more complete description, see QItemModelScatterDataMapping. + * + * Usage example: + * + * \snippet doc_src_qmldatavisualization.cpp 5 + * + * \sa ItemModelScatterDataProxy, {Qt Data Visualization Data Handling} + */ + +/*! + * \qmlproperty string ScatterDataMapping::xPosRole + * The X position role of the mapping. + */ + +/*! + * \qmlproperty string ScatterDataMapping::yPosRole + * The Y position role of the mapping. + */ + +/*! + * \qmlproperty string ScatterDataMapping::zPosRole + * The Z position role of the mapping. + */ + +/*! + * Constructs QItemModelScatterDataMapping with the given \a parent. + */ +QItemModelScatterDataMapping::QItemModelScatterDataMapping(QObject *parent) + : QAbstractDataMapping(new QItemModelScatterDataMappingPrivate(this), parent) +{ +} + +/*! + * Constructs QItemModelScatterDataMapping with \a xPosRole, \a yPosRole, \a zPosRole + * and the given \a parent. + */ +QItemModelScatterDataMapping::QItemModelScatterDataMapping(const QString &xPosRole, + const QString &yPosRole, + const QString &zPosRole, + QObject *parent) + : QAbstractDataMapping(new QItemModelScatterDataMappingPrivate(this), parent) +{ + dptr()->m_xPosRole = xPosRole; + dptr()->m_yPosRole = yPosRole; + dptr()->m_zPosRole = zPosRole; +} + +/*! + * Destroys QItemModelScatterDataMapping. + */ +QItemModelScatterDataMapping::~QItemModelScatterDataMapping() +{ +} + +/*! + * \property QItemModelScatterDataMapping::xPosRole + * + * Defines the X position role for the mapping. + */ +void QItemModelScatterDataMapping::setXPosRole(const QString &role) +{ + dptr()->m_xPosRole = role; + emit mappingChanged(); +} + +QString QItemModelScatterDataMapping::xPosRole() const +{ + return dptrc()->m_xPosRole; +} + +/*! + * \property QItemModelScatterDataMapping::yPosRole + * + * Defines the Y position role for the mapping. + */ +void QItemModelScatterDataMapping::setYPosRole(const QString &role) +{ + dptr()->m_yPosRole = role; + emit mappingChanged(); +} + +QString QItemModelScatterDataMapping::yPosRole() const +{ + return dptrc()->m_yPosRole; +} + +/*! + * \property QItemModelScatterDataMapping::zPosRole + * + * Defines the Z position role for the mapping. + */ +void QItemModelScatterDataMapping::setZPosRole(const QString &role) +{ + dptr()->m_zPosRole = role; + emit mappingChanged(); +} + +QString QItemModelScatterDataMapping::zPosRole() const +{ + return dptrc()->m_zPosRole; +} + +/*! + * Changes \a xPosRole, \a yPosRole and \a zPosRole to the mapping. + * + * Emits mappingChanged() signal after remapping. + */ +void QItemModelScatterDataMapping::remap(const QString &xPosRole, const QString &yPosRole, + const QString &zPosRole) +{ + dptr()->m_xPosRole = xPosRole; + dptr()->m_yPosRole = yPosRole; + dptr()->m_zPosRole = zPosRole; + + emit mappingChanged(); +} + +/*! + * \internal + */ +QItemModelScatterDataMappingPrivate *QItemModelScatterDataMapping::dptr() +{ + return static_cast<QItemModelScatterDataMappingPrivate *>(d_ptr.data()); +} + +/*! + * \internal + */ +const QItemModelScatterDataMappingPrivate *QItemModelScatterDataMapping::dptrc() const +{ + return static_cast<const QItemModelScatterDataMappingPrivate *>(d_ptr.data()); +} + +// QItemModelScatterDataMappingPrivate + +QItemModelScatterDataMappingPrivate::QItemModelScatterDataMappingPrivate( + QItemModelScatterDataMapping *q) + : QAbstractDataMappingPrivate(q, QAbstractDataProxy::DataTypeScatter) +{ +} + +QItemModelScatterDataMappingPrivate::~QItemModelScatterDataMappingPrivate() +{ +} + +QT_DATAVISUALIZATION_END_NAMESPACE + diff --git a/src/datavisualization/data/qitemmodelscatterdatamapping.h b/src/datavisualization/data/qitemmodelscatterdatamapping.h new file mode 100644 index 00000000..62f2fefc --- /dev/null +++ b/src/datavisualization/data/qitemmodelscatterdatamapping.h @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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 +** +****************************************************************************/ + +#ifndef QITEMMODELSCATTERDATAMAPPING_H +#define QITEMMODELSCATTERDATAMAPPING_H + +#include <QtDataVisualization/qdatavisualizationenums.h> +#include <QtDataVisualization/qabstractdatamapping.h> +#include <QObject> + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +class QItemModelScatterDataMappingPrivate; + +class QT_DATAVISUALIZATION_EXPORT QItemModelScatterDataMapping : public QAbstractDataMapping +{ + Q_OBJECT + Q_PROPERTY(QString xPosRole READ xPosRole WRITE setXPosRole) + Q_PROPERTY(QString yPosRole READ yPosRole WRITE setYPosRole) + Q_PROPERTY(QString zPosRole READ zPosRole WRITE setZPosRole) + +public: + explicit QItemModelScatterDataMapping(QObject *parent = 0); + QItemModelScatterDataMapping(const QString &xPosRole, const QString &yPosRole, + const QString &zPosRole, QObject *parent = 0); + virtual ~QItemModelScatterDataMapping(); + + void setXPosRole(const QString &role); + QString xPosRole() const; + void setYPosRole(const QString &role); + QString yPosRole() const; + void setZPosRole(const QString &role); + QString zPosRole() const; + + void remap(const QString &xPosRole, const QString &yPosRole, const QString &zPosRole); + +protected: + QItemModelScatterDataMappingPrivate *dptr(); + const QItemModelScatterDataMappingPrivate *dptrc() const; + +private: + Q_DISABLE_COPY(QItemModelScatterDataMapping) +}; + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif diff --git a/src/datavisualization/data/qitemmodelscatterdatamapping_p.h b/src/datavisualization/data/qitemmodelscatterdatamapping_p.h new file mode 100644 index 00000000..62ff42b4 --- /dev/null +++ b/src/datavisualization/data/qitemmodelscatterdatamapping_p.h @@ -0,0 +1,56 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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 +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVisualization API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. + +#ifndef QITEMMODELSCATTERDATAMAPPING_P_H +#define QITEMMODELSCATTERDATAMAPPING_P_H + +#include "qitemmodelscatterdatamapping.h" +#include "qabstractdatamapping_p.h" + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +class QItemModelScatterDataMappingPrivate : public QAbstractDataMappingPrivate +{ + Q_OBJECT +public: + QItemModelScatterDataMappingPrivate(QItemModelScatterDataMapping *q); + virtual ~QItemModelScatterDataMappingPrivate(); + +private: + //QString m_labelRole; + QString m_xPosRole; + QString m_yPosRole; + QString m_zPosRole; + //QString m_valueRole; + + friend class QItemModelScatterDataMapping; +}; + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif diff --git a/src/datavisualization/data/qitemmodelscatterdataproxy.cpp b/src/datavisualization/data/qitemmodelscatterdataproxy.cpp new file mode 100644 index 00000000..b037d4d1 --- /dev/null +++ b/src/datavisualization/data/qitemmodelscatterdataproxy.cpp @@ -0,0 +1,196 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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 "qitemmodelscatterdataproxy_p.h" +#include "scatteritemmodelhandler_p.h" +#include <QTimer> + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +/*! + * \class QItemModelScatterDataProxy + * \inmodule QtDataVisualization + * \brief Proxy class for presenting data in item models with Q3DScatter. + * \since 1.0.0 + * + * QItemModelScatterDataProxy allows you to use QAbstractItemModel derived models as a data source + * for Q3DScatter. It maps roles defined in QItemModelScatterDataMapping to roles in the model. + * + * Data is resolved asynchronously whenever the mapping or the model changes. + * QScatterDataProxy::arrayReset() is emitted when the data has been resolved. + * + * /sa {Qt Data Visualization Data Handling} + */ + +/*! + * \qmltype ItemModelScatterDataProxy + * \inqmlmodule com.digia.QtDataVisualization 1.0 + * \since com.digia.QtDataVisualization 1.0 + * \ingroup datavisualization_qml + * \instantiates QItemModelScatterDataProxy + * \inherits ScatterDataProxy + * \brief Proxy class for presenting data in item models with Scatter3D. + * + * This type allows you to use AbstractItemModel derived models as a data source for Scatter3D. + * + * Data is resolved asynchronously whenever the mapping or the model changes. + * QScatterDataProxy::arrayReset() is emitted when the data has been resolved. + * + * Usage example: + * + * \snippet doc_src_qmldatavisualization.cpp 8 + * + * \sa ScatterDataProxy, ScatterDataMapping, {Qt Data Visualization Data Handling} + */ + +/*! + * \qmlproperty list ItemModelScatterDataProxy::itemModel + * The item model. + */ + +/*! + * \qmlproperty list ItemModelScatterDataProxy::activeMapping + * The active mapping. Modifying a mapping that is set to the proxy will trigger data set + * re-resolving. + */ + +/*! + * Constructs QItemModelScatterDataProxy. + */ +QItemModelScatterDataProxy::QItemModelScatterDataProxy() : + QScatterDataProxy(new QItemModelScatterDataProxyPrivate(this)) +{ +} + +/*! + * Constructs QItemModelScatterDataProxy with \a itemModel and \a mapping. Does not take ownership + * of the model or the mapping, but does connect to them to listen for changes. + */ +QItemModelScatterDataProxy::QItemModelScatterDataProxy(const QAbstractItemModel *itemModel, + QItemModelScatterDataMapping *mapping) : + QScatterDataProxy(new QItemModelScatterDataProxyPrivate(this)) +{ + dptr()->m_itemModelHandler->setItemModel(itemModel); + dptr()->m_itemModelHandler->setActiveMapping(mapping); +} + +/*! + * Destroys QItemModelScatterDataProxy. + */ +QItemModelScatterDataProxy::~QItemModelScatterDataProxy() +{ +} + +/*! + * \property QItemModelScatterDataProxy::itemModel + * + * Defines item model. Does not take ownership of the model, but does connect to it to listen for + * changes. + */ +void QItemModelScatterDataProxy::setItemModel(const QAbstractItemModel *itemModel) +{ + dptr()->m_itemModelHandler->setItemModel(itemModel); +} + +const QAbstractItemModel *QItemModelScatterDataProxy::itemModel() const +{ + return dptrc()->m_itemModelHandler->itemModel(); +} + +/*! + * \property QItemModelScatterDataProxy::activeMapping + * + * Defines data mapping. Proxy takes ownership of the \a mapping. + * Modifying a mapping that is set to the proxy will trigger data set re-resolving. + */ +void QItemModelScatterDataProxy::setActiveMapping(QItemModelScatterDataMapping *mapping) +{ + dptr()->m_itemModelHandler->setActiveMapping(mapping); +} + +QItemModelScatterDataMapping *QItemModelScatterDataProxy::activeMapping() const +{ + return static_cast<QItemModelScatterDataMapping *>(dptrc()->m_itemModelHandler->activeMapping()); +} + +/*! + * Transfers the ownership of the \a mapping to this proxy. The mapping is not taken to use yet. + * \sa setActiveMapping(), releaseMapping() + */ +void QItemModelScatterDataProxy::addMapping(QItemModelScatterDataMapping *mapping) +{ + dptr()->m_itemModelHandler->addMapping(mapping); +} + +/*! + * Releases the ownership of the \a mapping back to the caller. If the mapping was the currently + * active one, no mapping remains active after this call. + */ +void QItemModelScatterDataProxy::releaseMapping(QItemModelScatterDataMapping *mapping) +{ + dptr()->m_itemModelHandler->releaseMapping(mapping); +} + +/*! + * \return list of mappings owned by the proxy. + */ +QList<QItemModelScatterDataMapping *> QItemModelScatterDataProxy::mappings() const +{ + QList<QItemModelScatterDataMapping *> retList; + QList<QAbstractDataMapping *> abstractList = dptrc()->m_itemModelHandler->mappings(); + foreach (QAbstractDataMapping *mapping, abstractList) + retList.append(static_cast<QItemModelScatterDataMapping *>(mapping)); + + return retList; +} + +/*! + * \internal + */ +QItemModelScatterDataProxyPrivate *QItemModelScatterDataProxy::dptr() +{ + return static_cast<QItemModelScatterDataProxyPrivate *>(d_ptr.data()); +} + +/*! + * \internal + */ +const QItemModelScatterDataProxyPrivate *QItemModelScatterDataProxy::dptrc() const +{ + return static_cast<const QItemModelScatterDataProxyPrivate *>(d_ptr.data()); +} + +// QItemModelScatterDataProxyPrivate + +QItemModelScatterDataProxyPrivate::QItemModelScatterDataProxyPrivate(QItemModelScatterDataProxy *q) + : QScatterDataProxyPrivate(q), + m_itemModelHandler(new ScatterItemModelHandler(q)) +{ +} + +QItemModelScatterDataProxyPrivate::~QItemModelScatterDataProxyPrivate() +{ + delete m_itemModelHandler; +} + +QItemModelScatterDataProxy *QItemModelScatterDataProxyPrivate::qptr() +{ + return static_cast<QItemModelScatterDataProxy *>(q_ptr); +} + +QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavisualization/data/qitemmodelscatterdataproxy.h b/src/datavisualization/data/qitemmodelscatterdataproxy.h new file mode 100644 index 00000000..891950c1 --- /dev/null +++ b/src/datavisualization/data/qitemmodelscatterdataproxy.h @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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 +** +****************************************************************************/ + +#ifndef QITEMMODELSCATTERDATAPROXY_H +#define QITEMMODELSCATTERDATAPROXY_H + +#include <QtDataVisualization/qscatterdataproxy.h> +#include <QtDataVisualization/qitemmodelscatterdatamapping.h> +#include <QAbstractItemModel> +#include <QStringList> + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +class QItemModelScatterDataProxyPrivate; + +class QT_DATAVISUALIZATION_EXPORT QItemModelScatterDataProxy : public QScatterDataProxy +{ + Q_OBJECT + Q_PROPERTY(const QAbstractItemModel* itemModel READ itemModel WRITE setItemModel) + Q_PROPERTY(QItemModelScatterDataMapping* activeMapping READ activeMapping WRITE setActiveMapping) + +public: + explicit QItemModelScatterDataProxy(); + explicit QItemModelScatterDataProxy(const QAbstractItemModel *itemModel, + QItemModelScatterDataMapping *mapping); + virtual ~QItemModelScatterDataProxy(); + + void setItemModel(const QAbstractItemModel *itemModel); + const QAbstractItemModel *itemModel() const; + + void setActiveMapping(QItemModelScatterDataMapping *mapping); + QItemModelScatterDataMapping *activeMapping() const; + void addMapping(QItemModelScatterDataMapping *mapping); + void releaseMapping(QItemModelScatterDataMapping *mapping); + QList<QItemModelScatterDataMapping *> mappings() const; + +protected: + QItemModelScatterDataProxyPrivate *dptr(); + const QItemModelScatterDataProxyPrivate *dptrc() const; + +private: + Q_DISABLE_COPY(QItemModelScatterDataProxy) +}; + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif diff --git a/src/datavisualization/data/qitemmodelscatterdataproxy_p.h b/src/datavisualization/data/qitemmodelscatterdataproxy_p.h new file mode 100644 index 00000000..854062a3 --- /dev/null +++ b/src/datavisualization/data/qitemmodelscatterdataproxy_p.h @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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 +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVisualization API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. + +#ifndef QITEMMODELSCATTERDATAPROXY_P_H +#define QITEMMODELSCATTERDATAPROXY_P_H + +#include "qitemmodelscatterdataproxy.h" +#include "qscatterdataproxy_p.h" +#include <QPointer> +#include <QTimer> + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +class ScatterItemModelHandler; + +class QItemModelScatterDataProxyPrivate : public QScatterDataProxyPrivate +{ + Q_OBJECT +public: + QItemModelScatterDataProxyPrivate(QItemModelScatterDataProxy *q); + virtual ~QItemModelScatterDataProxyPrivate(); + +private: + QItemModelScatterDataProxy *qptr(); + + ScatterItemModelHandler *m_itemModelHandler; + + friend class QItemModelScatterDataProxy; +}; + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif diff --git a/src/datavisualization/data/qitemmodelsurfacedatamapping.cpp b/src/datavisualization/data/qitemmodelsurfacedatamapping.cpp new file mode 100644 index 00000000..5388ec18 --- /dev/null +++ b/src/datavisualization/data/qitemmodelsurfacedatamapping.cpp @@ -0,0 +1,411 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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 "qitemmodelsurfacedatamapping_p.h" + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +/*! + * \class QItemModelSurfaceDataMapping + * \inmodule QtDataVisualization + * \brief Item model mapping for Q3DSurface. + * \since 1.0.0 + * + * QItemModelSurfaceDataMapping is used to map roles of QAbstractItemModel to rows, columns, and values + * of Q3DSurface. There are three ways to use QItemModelSurfaceDataMapping: + * + * 1) If useModelCategories property is set to true, QItemModelSurfaceDataMapping will map rows and + * columns of QAbstractItemModel to rows and columns of Q3DSurface, and uses the value returned for + * Qt::DisplayRole as bar value by default. + * The value role to be used can be redefined if Qt::DisplayRole is not suitable. + * + * 2) For models that do not have data already neatly sorted into rows and columns, such as + * QAbstractListModel based models, you can define a role from the model to map for each of row, + * column and value. + * + * 3) If you do not want to include all data contained in the model, or the autogenerated rows and + * columns are not ordered as you wish, you can specify which rows and columns should be included + * and in which order by defining an explicit list of categories for either or both of rows and + * columns. + * + * For example, assume that you have a custom QAbstractItemModel storing surface topography data. + * Each item in the model has roles "longitude", "latitude" and "height". The item model already + * contains the data properly sorted so that longitudes and latitudes are first encountered in + * correct order, which enables us to utilize the row and column category autogeneration. + * You could do the following to display the data in a surface graph: + * + * \snippet doc_src_qtdatavisualization.cpp 5 + * + * \sa QItemModelSurfaceDataProxy, {Qt Data Visualization Data Handling} + */ + +/*! + * \qmltype SurfaceDataMapping + * \inqmlmodule com.digia.QtDataVisualization 1.0 + * \since com.digia.QtDataVisualization 1.0 + * \ingroup datavisualization_qml + * \instantiates QItemModelSurfaceDataMapping + * \brief Item model mapping for Surface3D. + * + * This type is used to map roles of AbstractItemModel to rows, columns, and values of Surface3D. + * For more complete description, see QItemModelSurfaceDataMapping. + * + * Usage example: + * + * \snippet doc_src_qmldatavisualization.cpp 6 + * + * \sa ItemModelSurfaceDataProxy, {Qt Data Visualization Data Handling} + */ + +/*! + * \qmlproperty string SurfaceDataMapping::rowRole + * The row role of the mapping. + */ + +/*! + * \qmlproperty string SurfaceDataMapping::columnRole + * The column role of the mapping. + */ + +/*! + * \qmlproperty string SurfaceDataMapping::valueRole + * The value role of the mapping. + */ + +/*! + * \qmlproperty list SurfaceDataMapping::rowCategories + * The row categories of the mapping. Only items with row roles that are found in this list are + * included when data is resolved. The rows are ordered in the same order as they are in this list. + */ + +/*! + * \qmlproperty list SurfaceDataMapping::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. + */ + +/*! + * \qmlproperty list SurfaceDataMapping::useModelCategories + * When set to true, the mapping ignores row and column roles and categories, and uses + * the rows and columns from the model instead. Defaults to false. + */ + +/*! + * \qmlproperty list SurfaceDataMapping::autoRowCategories + * When set to true, the mapping ignores any explicitly set row categories + * and overwrites them with automatically generated ones whenever the + * data from model is resolved. Proxy minimum and maximum row values are also + * autogenerated from data when this is set to true. Defaults to true. + */ + +/*! + * \qmlproperty list SurfaceDataMapping::autoColumnCategories + * When set to true, the mapping ignores any explicitly set column categories + * and overwrites them with automatically generated ones whenever the + * data from model is resolved. Proxy minimum and maximum column values are also + * autogenerated from data when this is set to true. Defaults to true. + */ + +/*! + * Constructs QItemModelSurfaceDataMapping with the given \a parent. + */ +QItemModelSurfaceDataMapping::QItemModelSurfaceDataMapping(QObject *parent) + : QAbstractDataMapping(new QItemModelSurfaceDataMappingPrivate(this), parent) +{ +} + +/*! + * Constructs QItemModelSurfaceDataMapping with \a valueRole and the given \a parent. + * This constructor is meant to be used with models that have data properly sorted + * in rows and columns already, so it also sets useModelCategories property to true. + */ +QItemModelSurfaceDataMapping::QItemModelSurfaceDataMapping(const QString &valueRole, QObject *parent) + : QAbstractDataMapping(new QItemModelSurfaceDataMappingPrivate(this), parent) +{ + dptr()->m_valueRole = valueRole; + dptr()->m_useModelCategories = true; +} + +/*! + * Constructs QItemModelSurfaceDataMapping with \a rowRole, \a columnRole, \a valueRole + * and the given \a parent. + */ +QItemModelSurfaceDataMapping::QItemModelSurfaceDataMapping(const QString &rowRole, + const QString &columnRole, + const QString &valueRole, + QObject *parent) + : QAbstractDataMapping(new QItemModelSurfaceDataMappingPrivate(this), parent) +{ + dptr()->m_rowRole = rowRole; + dptr()->m_columnRole = columnRole; + dptr()->m_valueRole = valueRole; +} + +/*! + * Constructs QItemModelSurfaceDataMapping with \a rowRole, \a columnRole, \a valueRole, + * \a rowCategories, \a columnCategories and the given \a parent. This constructor + * also sets autoRowCategories and autoColumnCategories to false. + */ +QItemModelSurfaceDataMapping::QItemModelSurfaceDataMapping(const QString &rowRole, + const QString &columnRole, + const QString &valueRole, + const QStringList &rowCategories, + const QStringList &columnCategories, + QObject *parent) + : QAbstractDataMapping(new QItemModelSurfaceDataMappingPrivate(this), parent) +{ + dptr()->m_rowRole = rowRole; + dptr()->m_columnRole = columnRole; + dptr()->m_valueRole = valueRole; + dptr()->m_rowCategories = rowCategories; + dptr()->m_columnCategories = columnCategories; + dptr()->m_autoRowCategories = false; + dptr()->m_autoColumnCategories = false; +} + +/*! + * Destroys QItemModelSurfaceDataMapping. + */ +QItemModelSurfaceDataMapping::~QItemModelSurfaceDataMapping() +{ +} + +/*! + * \property QItemModelSurfaceDataMapping::rowRole + * + * Defines the row role for the mapping. + */ +void QItemModelSurfaceDataMapping::setRowRole(const QString &role) +{ + if (dptr()->m_rowRole != role) { + dptr()->m_rowRole = role; + emit mappingChanged(); + } +} + +QString QItemModelSurfaceDataMapping::rowRole() const +{ + return dptrc()->m_rowRole; +} + +/*! + * \property QItemModelSurfaceDataMapping::columnRole + * + * Defines the column role for the mapping. + */ +void QItemModelSurfaceDataMapping::setColumnRole(const QString &role) +{ + if (dptr()->m_columnRole != role) { + dptr()->m_columnRole = role; + emit mappingChanged(); + } +} + +QString QItemModelSurfaceDataMapping::columnRole() const +{ + return dptrc()->m_columnRole; +} + +/*! + * \property QItemModelSurfaceDataMapping::valueRole + * + * Defines the value role for the mapping. + */ +void QItemModelSurfaceDataMapping::setValueRole(const QString &role) +{ + if (dptr()->m_valueRole != role) { + dptr()->m_valueRole = role; + emit mappingChanged(); + } +} + +QString QItemModelSurfaceDataMapping::valueRole() const +{ + return dptrc()->m_valueRole; +} + +/*! + * \property QItemModelSurfaceDataMapping::rowCategories + * + * Defines the row categories for the mapping. + */ +void QItemModelSurfaceDataMapping::setRowCategories(const QStringList &categories) +{ + if (dptr()->m_rowCategories != categories) { + dptr()->m_rowCategories = categories; + emit mappingChanged(); + } +} + +QStringList QItemModelSurfaceDataMapping::rowCategories() const +{ + return dptrc()->m_rowCategories; +} + +/*! + * \property QItemModelSurfaceDataMapping::columnCategories + * + * Defines the column categories for the mapping. + */ +void QItemModelSurfaceDataMapping::setColumnCategories(const QStringList &categories) +{ + if (dptr()->m_columnCategories != categories) { + dptr()->m_columnCategories = categories; + emit mappingChanged(); + } +} + +QStringList QItemModelSurfaceDataMapping::columnCategories() const +{ + return dptrc()->m_columnCategories; +} + +/*! + * \property QItemModelSurfaceDataMapping::useModelCategories + * + * When set to true, the mapping ignores row and column roles and categories, and uses + * the rows and columns from the model instead. Defaults to false. + */ +void QItemModelSurfaceDataMapping::setUseModelCategories(bool enable) +{ + if (dptr()->m_useModelCategories != enable) { + dptr()->m_useModelCategories = enable; + emit mappingChanged(); + } +} + +bool QItemModelSurfaceDataMapping::useModelCategories() const +{ + return dptrc()->m_useModelCategories; +} + +/*! + * \property QItemModelSurfaceDataMapping::autoRowCategories + * + * When set to true, the mapping ignores any explicitly set row categories + * and overwrites them with automatically generated ones whenever the + * data from model is resolved. Proxy minimum and maximum row values are also + * autogenerated from data when this is set to true. Defaults to true. + */ +void QItemModelSurfaceDataMapping::setAutoRowCategories(bool enable) +{ + if (dptr()->m_autoRowCategories != enable) { + dptr()->m_autoRowCategories = enable; + emit mappingChanged(); + } +} + +bool QItemModelSurfaceDataMapping::autoRowCategories() const +{ + return dptrc()->m_autoRowCategories; +} + +/*! + * \property QItemModelSurfaceDataMapping::autoColumnCategories + * + * When set to true, the mapping ignores any explicitly set column categories + * and overwrites them with automatically generated ones whenever the + * data from model is resolved. Proxy minimum and maximum column values are also + * autogenerated from data when this is set to true. Defaults to true. + */ +void QItemModelSurfaceDataMapping::setAutoColumnCategories(bool enable) +{ + if (dptr()->m_autoColumnCategories != enable) { + dptr()->m_autoColumnCategories = enable; + emit mappingChanged(); + } +} + +bool QItemModelSurfaceDataMapping::autoColumnCategories() const +{ + return dptrc()->m_autoColumnCategories; +} + +/*! + * Changes \a rowRole, \a columnRole, \a valueRole, \a rowCategories and \a columnCategories to the + * mapping. + */ +void QItemModelSurfaceDataMapping::remap(const QString &rowRole, + const QString &columnRole, + const QString &valueRole, + const QStringList &rowCategories, + const QStringList &columnCategories) +{ + dptr()->m_rowRole = rowRole; + dptr()->m_columnRole = columnRole; + dptr()->m_valueRole = valueRole; + dptr()->m_rowCategories = rowCategories; + dptr()->m_columnCategories = columnCategories; + + emit mappingChanged(); +} + +/*! + * /return index of the specified \a category in row categories list. + * If the row categories list is empty, -1 is returned. + * \note If the automatic row categories generation is in use, this method will + * not return valid index before the data in the model is resolved for the first time. + */ +int QItemModelSurfaceDataMapping::rowCategoryIndex(const QString &category) +{ + return dptr()->m_rowCategories.indexOf(category); +} + +/*! + * /return index of the specified \a category in column categories list. + * \note If the automatic column categories generation is in use, this method will + * not return valid index before the data in the model is resolved for the first time. + */ +int QItemModelSurfaceDataMapping::columnCategoryIndex(const QString &category) +{ + return dptr()->m_columnCategories.indexOf(category); +} + +/*! + * \internal + */ +QItemModelSurfaceDataMappingPrivate *QItemModelSurfaceDataMapping::dptr() +{ + return static_cast<QItemModelSurfaceDataMappingPrivate *>(d_ptr.data()); +} + +/*! + * \internal + */ +const QItemModelSurfaceDataMappingPrivate *QItemModelSurfaceDataMapping::dptrc() const +{ + return static_cast<const QItemModelSurfaceDataMappingPrivate *>(d_ptr.data()); +} + +// QItemModelSurfaceDataMappingPrivate + +QItemModelSurfaceDataMappingPrivate::QItemModelSurfaceDataMappingPrivate(QItemModelSurfaceDataMapping *q) + : QAbstractDataMappingPrivate(q, QAbstractDataProxy::DataTypeSurface), + m_useModelCategories(false), + m_autoRowCategories(true), + m_autoColumnCategories(true) +{ +} + +QItemModelSurfaceDataMappingPrivate::~QItemModelSurfaceDataMappingPrivate() +{ +} + + +QT_DATAVISUALIZATION_END_NAMESPACE + diff --git a/src/datavisualization/data/qitemmodelsurfacedatamapping.h b/src/datavisualization/data/qitemmodelsurfacedatamapping.h new file mode 100644 index 00000000..7e8817bf --- /dev/null +++ b/src/datavisualization/data/qitemmodelsurfacedatamapping.h @@ -0,0 +1,90 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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 +** +****************************************************************************/ + +#ifndef QITEMMODELSURFACEDATAMAPPING_H +#define QITEMMODELSURFACEDATAMAPPING_H + +#include <QtDataVisualization/qdatavisualizationenums.h> +#include <QtDataVisualization/qabstractdatamapping.h> +#include <QStringList> + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +class QItemModelSurfaceDataMappingPrivate; + +class QT_DATAVISUALIZATION_EXPORT QItemModelSurfaceDataMapping : public QAbstractDataMapping +{ + Q_OBJECT + Q_PROPERTY(QString rowRole READ rowRole WRITE setRowRole) + Q_PROPERTY(QString columnRole READ columnRole WRITE setColumnRole) + Q_PROPERTY(QString valueRole READ valueRole WRITE setValueRole) + Q_PROPERTY(QStringList rowCategories READ rowCategories WRITE setRowCategories) + Q_PROPERTY(QStringList columnCategories READ columnCategories WRITE setColumnCategories) + Q_PROPERTY(bool useModelCategories READ useModelCategories WRITE setUseModelCategories) + Q_PROPERTY(bool autoRowCategories READ autoRowCategories WRITE setAutoRowCategories) + Q_PROPERTY(bool autoColumnCategories READ autoColumnCategories WRITE setAutoColumnCategories) + +public: + explicit QItemModelSurfaceDataMapping(QObject *parent = 0); + QItemModelSurfaceDataMapping(const QString &valueRole, QObject *parent = 0); + QItemModelSurfaceDataMapping(const QString &rowRole, const QString &columnRole, + const QString &valueRole, QObject *parent = 0); + QItemModelSurfaceDataMapping(const QString &rowRole, const QString &columnRole, + const QString &valueRole, const QStringList &rowCategories, + const QStringList &columnCategories, QObject *parent = 0); + virtual ~QItemModelSurfaceDataMapping(); + + void setRowRole(const QString &role); + QString rowRole() const; + void setColumnRole(const QString &role); + QString columnRole() const; + void setValueRole(const QString &role); + QString valueRole() const; + + void setRowCategories(const QStringList &categories); + QStringList rowCategories() const; + void setColumnCategories(const QStringList &categories); + QStringList columnCategories() const; + + void setUseModelCategories(bool enable); + bool useModelCategories() const; + void setAutoRowCategories(bool enable); + bool autoRowCategories() const; + void setAutoColumnCategories(bool enable); + bool autoColumnCategories() const; + + void remap(const QString &rowRole, const QString &columnRole, + const QString &valueRole, const QStringList &rowCategories, + const QStringList &columnCategories); + + Q_INVOKABLE int rowCategoryIndex(const QString& category); + Q_INVOKABLE int columnCategoryIndex(const QString& category); + +protected: + QItemModelSurfaceDataMappingPrivate *dptr(); + const QItemModelSurfaceDataMappingPrivate *dptrc() const; + +private: + Q_DISABLE_COPY(QItemModelSurfaceDataMapping) + + friend class SurfaceItemModelHandler; +}; + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif diff --git a/src/datavisualization/data/qitemmodelsurfacedatamapping_p.h b/src/datavisualization/data/qitemmodelsurfacedatamapping_p.h new file mode 100644 index 00000000..9896f868 --- /dev/null +++ b/src/datavisualization/data/qitemmodelsurfacedatamapping_p.h @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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 +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVisualization API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. + +#include "qitemmodelsurfacedatamapping.h" +#include "qabstractdatamapping_p.h" + +#ifndef QITEMMODELSURFACEDATAMAPPING_P_H +#define QITEMMODELSURFACEDATAMAPPING_P_H + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +class QItemModelSurfaceDataMappingPrivate : public QAbstractDataMappingPrivate +{ + Q_OBJECT +public: + QItemModelSurfaceDataMappingPrivate(QItemModelSurfaceDataMapping *q); + virtual ~QItemModelSurfaceDataMappingPrivate(); + +private: + QString m_rowRole; + QString m_columnRole; + QString m_valueRole; + + // For row/column items, sort items into these categories. Other categories are ignored. + QStringList m_rowCategories; + QStringList m_columnCategories; + + bool m_useModelCategories; + bool m_autoRowCategories; + bool m_autoColumnCategories; + + friend class QItemModelSurfaceDataMapping; + friend class SurfaceItemModelHandler; +}; + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif diff --git a/src/datavisualization/data/qitemmodelsurfacedataproxy.cpp b/src/datavisualization/data/qitemmodelsurfacedataproxy.cpp new file mode 100644 index 00000000..f6403e9b --- /dev/null +++ b/src/datavisualization/data/qitemmodelsurfacedataproxy.cpp @@ -0,0 +1,198 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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 "qitemmodelsurfacedataproxy_p.h" +#include "surfaceitemmodelhandler_p.h" +#include <QTimer> + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +// TODO: CHECK DOCUMENTATION! + +/*! + * \class QItemModelSurfaceDataProxy + * \inmodule QtDataVisualization + * \brief Proxy class for presenting data in item models with Q3DSurface. + * \since 1.0.0 + * + * QItemModelSurfaceDataProxy allows you to use QAbstractItemModel derived models as a data source + * for Q3DSurface. It maps roles defined in QItemModelSurfaceDataMapping to roles in the model. + * + * Data is resolved asynchronously whenever the mapping or the model changes. + * QSurfaceDataProxy::arrayReset() is emitted when the data has been resolved. + * + * /sa {Qt Data Visualization Data Handling} + */ + +/*! + * \qmltype ItemModelSurfaceDataProxy + * \inqmlmodule com.digia.QtDataVisualization 1.0 + * \since com.digia.QtDataVisualization 1.0 + * \ingroup datavisualization_qml + * \instantiates QItemModelSurfaceDataProxy + * \inherits SurfaceDataProxy + * \brief Proxy class for presenting data in item models with Surface3D. + * + * This type allows you to use AbstractItemModel derived models as a data source for Surface3D. + * + * Data is resolved asynchronously whenever the mapping or the model changes. + * QSurfaceDataProxy::arrayReset() is emitted when the data has been resolved. + * + * Usage example: + * + * \snippet doc_src_qmldatavisualization.cpp 9 + * + * \sa SurfaceDataProxy, SurfaceDataMapping, {Qt Data Visualization Data Handling} + */ + +/*! + * \qmlproperty list ItemModelSurfaceDataProxy::itemModel + * The item model. + */ + +/*! + * \qmlproperty list ItemModelSurfaceDataProxy::activeMapping + * The active mapping. Modifying a mapping that is set to the proxy will trigger data set + * re-resolving. + */ + +/*! + * Constructs QItemModelSurfaceDataProxy. + */ +QItemModelSurfaceDataProxy::QItemModelSurfaceDataProxy() : + QSurfaceDataProxy(new QItemModelSurfaceDataProxyPrivate(this)) +{ +} + +/*! + * Constructs QItemModelSurfaceDataProxy with \a itemModel and \a mapping. Does not take ownership + * of the model or the mapping, but does connect to them to listen for changes. + */ +QItemModelSurfaceDataProxy::QItemModelSurfaceDataProxy(const QAbstractItemModel *itemModel, + QItemModelSurfaceDataMapping *mapping) : + QSurfaceDataProxy(new QItemModelSurfaceDataProxyPrivate(this)) +{ + dptr()->m_itemModelHandler->setItemModel(itemModel); + dptr()->m_itemModelHandler->setActiveMapping(mapping); +} + +/*! + * Destroys QItemModelSurfaceDataProxy. + */ +QItemModelSurfaceDataProxy::~QItemModelSurfaceDataProxy() +{ +} + +/*! + * \property QItemModelSurfaceDataProxy::itemModel + * + * Defines item model. Does not take ownership of the model, but does connect to it to listen for + * changes. + */ +void QItemModelSurfaceDataProxy::setItemModel(const QAbstractItemModel *itemModel) +{ + dptr()->m_itemModelHandler->setItemModel(itemModel); +} + +const QAbstractItemModel *QItemModelSurfaceDataProxy::itemModel() const +{ + return dptrc()->m_itemModelHandler->itemModel(); +} + +/*! + * \property QItemModelSurfaceDataProxy::activeMapping + * + * Defines data mapping. Proxy takes ownership of the \a mapping. + * Modifying a mapping that is set to the proxy will trigger data set re-resolving. + */ +void QItemModelSurfaceDataProxy::setActiveMapping(QItemModelSurfaceDataMapping *mapping) +{ + dptr()->m_itemModelHandler->setActiveMapping(mapping); +} + +QItemModelSurfaceDataMapping *QItemModelSurfaceDataProxy::activeMapping() const +{ + return static_cast<QItemModelSurfaceDataMapping *>(dptrc()->m_itemModelHandler->activeMapping()); +} + +/*! + * Transfers the ownership of the \a mapping to this proxy. The mapping is not taken to use yet. + * \sa setActiveMapping(), releaseMapping() + */ +void QItemModelSurfaceDataProxy::addMapping(QItemModelSurfaceDataMapping *mapping) +{ + dptr()->m_itemModelHandler->addMapping(mapping); +} + +/*! + * Releases the ownership of the \a mapping back to the caller. If the mapping was the currently + * active one, no mapping remains active after this call. + */ +void QItemModelSurfaceDataProxy::releaseMapping(QItemModelSurfaceDataMapping *mapping) +{ + dptr()->m_itemModelHandler->releaseMapping(mapping); +} + +/*! + * \return list of mappings owned by the proxy. + */ +QList<QItemModelSurfaceDataMapping *> QItemModelSurfaceDataProxy::mappings() const +{ + QList<QItemModelSurfaceDataMapping *> retList; + QList<QAbstractDataMapping *> abstractList = dptrc()->m_itemModelHandler->mappings(); + foreach (QAbstractDataMapping *mapping, abstractList) + retList.append(static_cast<QItemModelSurfaceDataMapping *>(mapping)); + + return retList; +} + +/*! + * \internal + */ +QItemModelSurfaceDataProxyPrivate *QItemModelSurfaceDataProxy::dptr() +{ + return static_cast<QItemModelSurfaceDataProxyPrivate *>(d_ptr.data()); +} + +/*! + * \internal + */ +const QItemModelSurfaceDataProxyPrivate *QItemModelSurfaceDataProxy::dptrc() const +{ + return static_cast<const QItemModelSurfaceDataProxyPrivate *>(d_ptr.data()); +} + +// QItemModelSurfaceDataProxyPrivate + +QItemModelSurfaceDataProxyPrivate::QItemModelSurfaceDataProxyPrivate(QItemModelSurfaceDataProxy *q) + : QSurfaceDataProxyPrivate(q), + m_itemModelHandler(new SurfaceItemModelHandler(q)) +{ +} + +QItemModelSurfaceDataProxyPrivate::~QItemModelSurfaceDataProxyPrivate() +{ + delete m_itemModelHandler; +} + +QItemModelSurfaceDataProxy *QItemModelSurfaceDataProxyPrivate::qptr() +{ + return static_cast<QItemModelSurfaceDataProxy *>(q_ptr); +} + +QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavisualization/data/qitemmodelsurfacedataproxy.h b/src/datavisualization/data/qitemmodelsurfacedataproxy.h new file mode 100644 index 00000000..080bf54b --- /dev/null +++ b/src/datavisualization/data/qitemmodelsurfacedataproxy.h @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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 +** +****************************************************************************/ + +#ifndef QITEMMODELSURFACEDATAPROXY_H +#define QITEMMODELSURFACEDATAPROXY_H + +#include <QtDataVisualization/qsurfacedataproxy.h> +#include <QtDataVisualization/qitemmodelsurfacedatamapping.h> +#include <QAbstractItemModel> +#include <QStringList> + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +class QItemModelSurfaceDataProxyPrivate; + +class QT_DATAVISUALIZATION_EXPORT QItemModelSurfaceDataProxy : public QSurfaceDataProxy +{ + Q_OBJECT + Q_PROPERTY(const QAbstractItemModel* itemModel READ itemModel WRITE setItemModel) + Q_PROPERTY(QItemModelSurfaceDataMapping* activeMapping READ activeMapping WRITE setActiveMapping) + +public: + explicit QItemModelSurfaceDataProxy(); + explicit QItemModelSurfaceDataProxy(const QAbstractItemModel *itemModel, + QItemModelSurfaceDataMapping *mapping); + virtual ~QItemModelSurfaceDataProxy(); + + void setItemModel(const QAbstractItemModel *itemModel); + const QAbstractItemModel *itemModel() const; + + void setActiveMapping(QItemModelSurfaceDataMapping *mapping); + QItemModelSurfaceDataMapping *activeMapping() const; + void addMapping(QItemModelSurfaceDataMapping *mapping); + void releaseMapping(QItemModelSurfaceDataMapping *mapping); + QList<QItemModelSurfaceDataMapping *> mappings() const; + +protected: + QItemModelSurfaceDataProxyPrivate *dptr(); + const QItemModelSurfaceDataProxyPrivate *dptrc() const; + +private: + Q_DISABLE_COPY(QItemModelSurfaceDataProxy) +}; + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif diff --git a/src/datavisualization/data/qitemmodelsurfacedataproxy_p.h b/src/datavisualization/data/qitemmodelsurfacedataproxy_p.h new file mode 100644 index 00000000..ff9d13de --- /dev/null +++ b/src/datavisualization/data/qitemmodelsurfacedataproxy_p.h @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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 +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVisualization API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. + +#ifndef QITEMMODELSURFACEDATAPROXY_P_H +#define QITEMMODELSURFACEDATAPROXY_P_H + +#include "qitemmodelsurfacedataproxy.h" +#include "qsurfacedataproxy_p.h" +#include <QPointer> +#include <QTimer> + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +class SurfaceItemModelHandler; + +class QItemModelSurfaceDataProxyPrivate : public QSurfaceDataProxyPrivate +{ + Q_OBJECT +public: + QItemModelSurfaceDataProxyPrivate(QItemModelSurfaceDataProxy *q); + virtual ~QItemModelSurfaceDataProxyPrivate(); + +private: + QItemModelSurfaceDataProxy *qptr(); + + SurfaceItemModelHandler *m_itemModelHandler; + + friend class QItemModelSurfaceDataProxy; +}; + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif diff --git a/src/datavisualization/data/qscatterdataitem.cpp b/src/datavisualization/data/qscatterdataitem.cpp new file mode 100644 index 00000000..055a9dad --- /dev/null +++ b/src/datavisualization/data/qscatterdataitem.cpp @@ -0,0 +1,153 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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 "qscatterdataitem_p.h" + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +/*! + * \class QScatterDataItem + * \inmodule QtDataVisualization + * \brief The QScatterDataItem class provides a container for resolved data to be added to scatter + * graphs. + * \since 1.0.0 + * + * A QScatterDataItem holds data for a single rendered item in a scatter graph. + * Scatter data proxies parse data into QScatterDataItem instances for visualizing. + * + * \sa QScatterDataProxy, {Qt Data Visualization C++ Classes} + */ + +/*! + * Constructs QScatterDataItem. + */ +QScatterDataItem::QScatterDataItem() + : d_ptr(0) // private data doesn't exist by default (optimization) + +{ +} + +/*! + * Constructs QScatterDataItem with \a position. + */ +QScatterDataItem::QScatterDataItem(const QVector3D &position) + : d_ptr(0), + m_position(position) +{ +} + +/*! + * Constructs a copy of \a other. + */ +QScatterDataItem::QScatterDataItem(const QScatterDataItem &other) +{ + operator=(other); +} + +/*! + * Destroys QScatterDataItem. + */ +QScatterDataItem::~QScatterDataItem() +{ +} + +/*! + * Assigns a copy of \a other to this object. + */ +QScatterDataItem &QScatterDataItem::operator=(const QScatterDataItem &other) +{ + m_position = other.m_position; + //m_size = other.m_size; + + if (other.d_ptr) + createExtraData(); + else + d_ptr = 0; + // TODO set extra data + + return *this; +} + +/*! + * \fn void QScatterDataItem::setPosition(const QVector3D &position) + * Sets \a position to this data item. + */ + +/*! + * \fn QVector3D QScatterDataItem::position() const + * \return position of this data item. + */ + +/*! + * \fn void QScatterDataItem::setX(float value) + * Sets the X component of the item position to the \a value. + */ + +/*! + * \fn void QScatterDataItem::setY(float value) + * Sets the Y component of the item position to the \a value. + */ + +/*! + * \fn void QScatterDataItem::setZ(float value) + * Sets the Z component of the item position to the \a value. + */ + +/*! + * \fn float QScatterDataItem::x() const + * \return the X component of the position of this data item. + */ + +/*! + * \fn float QScatterDataItem::y() const + * \return the Y component of the position of this data item. + */ + +/*! + * \fn float QScatterDataItem::z() const + * \return the Z component of the position of this data item. + */ + +//void QScatterDataItem::setSize(qreal size) +//{ +// m_size = size; +//} + +//const qreal &QScatterDataItem::size() const +//{ +// return m_size; +//} + +/*! + * \internal + */ +void QScatterDataItem::createExtraData() +{ + if (!d_ptr) + d_ptr = new QScatterDataItemPrivate; +} + +QScatterDataItemPrivate::QScatterDataItemPrivate() +{ +} + +QScatterDataItemPrivate::~QScatterDataItemPrivate() +{ +} + +QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavisualization/data/qscatterdataitem.h b/src/datavisualization/data/qscatterdataitem.h new file mode 100644 index 00000000..29154259 --- /dev/null +++ b/src/datavisualization/data/qscatterdataitem.h @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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 +** +****************************************************************************/ + +#ifndef QSCATTERDATAITEM_H +#define QSCATTERDATAITEM_H + +#include <QtDataVisualization/qdatavisualizationenums.h> +#include <QVector3D> + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +class QScatterDataItemPrivate; + +class QT_DATAVISUALIZATION_EXPORT QScatterDataItem +{ +public: + QScatterDataItem(); + QScatterDataItem(const QVector3D &position); + QScatterDataItem(const QScatterDataItem &other); + ~QScatterDataItem(); + + QScatterDataItem &operator=(const QScatterDataItem &other); + + inline void setPosition(const QVector3D &position) { m_position = position; } + inline QVector3D position() const { return m_position; } + inline void setX(float value) { m_position.setX(value); } + inline void setY(float value) { m_position.setY(value); } + inline void setZ(float value) { m_position.setZ(value); } + inline float x() const { return m_position.x(); } + inline float y() const { return m_position.y(); } + inline float z() const { return m_position.z(); } + + //void setSize(qreal size); + //qreal size() const; + +protected: + virtual void createExtraData(); + + QScatterDataItemPrivate *d_ptr; + +private: + QVector3D m_position; + //qreal m_size; +}; + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif diff --git a/src/datavisualization/data/qscatterdataitem_p.h b/src/datavisualization/data/qscatterdataitem_p.h new file mode 100644 index 00000000..acc67347 --- /dev/null +++ b/src/datavisualization/data/qscatterdataitem_p.h @@ -0,0 +1,51 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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 +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVisualization API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. + +#ifndef QSCATTERDATAITEM_P_H +#define QSCATTERDATAITEM_P_H + +#include "datavisualizationglobal_p.h" +#include "qscatterdataitem.h" + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +class QScatterDataItemPrivate +{ +public: + QScatterDataItemPrivate(); + virtual ~QScatterDataItemPrivate(); + + // TODO stores other data for scatter items besides position + +protected: + friend class QScatterDataItem; +}; + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif diff --git a/src/datavisualization/data/qscatterdataproxy.cpp b/src/datavisualization/data/qscatterdataproxy.cpp new file mode 100644 index 00000000..4d83da8d --- /dev/null +++ b/src/datavisualization/data/qscatterdataproxy.cpp @@ -0,0 +1,367 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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 "qscatterdataproxy.h" +#include "qscatterdataproxy_p.h" + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +/*! + * \class QScatterDataProxy + * \inmodule QtDataVisualization + * \brief Base proxy class for Q3DScatter. + * \since 1.0.0 + * + * QScatterDataProxy handles adding, inserting, changing and removing data items. + * + * QScatterDataProxy takes ownership of all QScatterDataArrays and QScatterDataItems passed to it. + * + * QScatterDataProxy supports the following format tags for QAbstractDataProxy::setItemLabelFormat(): + * \table + * \row + * \li @xTitle \li Title from X axis + * \row + * \li @yTitle \li Title from Y axis + * \row + * \li @zTitle \li Title from Z axis + * \row + * \li @xLabel \li Item value formatted using the same format the X axis attached to the graph uses, + * see \l{Q3DValueAxis::setLabelFormat()} for more information. + * \row + * \li @yLabel \li Item value formatted using the same format the Y axis attached to the graph uses, + * see \l{Q3DValueAxis::setLabelFormat()} for more information. + * \row + * \li @zLabel \li Item value formatted using the same format the Z axis attached to the graph uses, + * see \l{Q3DValueAxis::setLabelFormat()} for more information. + * \endtable + * + * For example: + * \snippet doc_src_qtdatavisualization.cpp 2 + * + * /sa {Qt Data Visualization Data Handling} + */ + +/*! + * \qmltype ScatterDataProxy + * \inqmlmodule com.digia.QtDataVisualization 1.0 + * \since com.digia.QtDataVisualization 1.0 + * \ingroup datavisualization_qml + * \instantiates QScatterDataProxy + * \inherits AbstractDataProxy + * \brief Base proxy class for Scatter3D. + * + * This type handles adding, inserting, changing and removing data items. + * + * This type is uncreatable, but contains properties that are exposed via subtypes. + * + * For more complete description, see QScatterDataProxy. + * + * \sa ItemModelScatterDataProxy, {Qt Data Visualization Data Handling} + */ + +/*! + * \qmlproperty int ScatterDataProxy::itemCount + * Item count in the array. + */ + +/*! + * Constructs QScatterDataProxy with the given \a parent. + */ +QScatterDataProxy::QScatterDataProxy(QObject *parent) : + QAbstractDataProxy(new QScatterDataProxyPrivate(this), parent) +{ +} + +/*! + * \internal + */ +QScatterDataProxy::QScatterDataProxy(QScatterDataProxyPrivate *d, QObject *parent) : + QAbstractDataProxy(d, parent) +{ +} + +/*! + * Destroys QScatterDataProxy. + */ +QScatterDataProxy::~QScatterDataProxy() +{ +} + +/*! + * Takes ownership of the \a newArray. Clears the existing array and if the \a newArray is + * different than the existing array. If it's the same array, this just triggers arrayReset() + * signal. + * Passing null array deletes the old array and creates a new empty array. + */ +void QScatterDataProxy::resetArray(QScatterDataArray *newArray) +{ + if (dptr()->m_dataArray != newArray) + dptr()->resetArray(newArray); + + emit arrayReset(); +} + +/*! + * Changes a single item at \a index with \a item. + */ +void QScatterDataProxy::setItem(int index, const QScatterDataItem &item) +{ + dptr()->setItem(index, item); + emit itemsChanged(index, 1); +} + +/*! + * Changes items starting from \a index with \a items. + */ +void QScatterDataProxy::setItems(int index, const QScatterDataArray &items) +{ + dptr()->setItems(index, items); + emit itemsChanged(index, items.size()); +} + +/*! + * Adds a single \a item to the end of the array. + * + * \return index of the added item. + */ +int QScatterDataProxy::addItem(const QScatterDataItem &item) +{ + int addIndex = dptr()->addItem(item); + emit itemsAdded(addIndex, 1); + return addIndex; +} + +/*! + * Adds \a items to the end of the array. + * + * \return index of the first added item. + */ +int QScatterDataProxy::addItems(const QScatterDataArray &items) +{ + int addIndex = dptr()->addItems(items); + emit itemsAdded(addIndex, items.size()); + return addIndex; +} + +/*! + * Inserts a single \a item to \a index. If index is equal to data array size, item is added to + * the array. + */ +void QScatterDataProxy::insertItem(int index, const QScatterDataItem &item) +{ + dptr()->insertItem(index, item); + emit itemsInserted(index, 1); +} + +/*! + * Inserts \a items to \a index. If index is equal to data array size, items are added to the array. + */ +void QScatterDataProxy::insertItems(int index, const QScatterDataArray &items) +{ + dptr()->insertItems(index, items); + emit itemsInserted(index, items.size()); +} + +/*! + * Removes \a removeCount items starting from \a index. Attempting to remove items past the end of + * the array does nothing. + */ +void QScatterDataProxy::removeItems(int index, int removeCount) +{ + dptr()->removeItems(index, removeCount); + emit itemsRemoved(index, removeCount); +} + +/*! + * \property QScatterDataProxy::itemCount + * + * \return item count in the array. + */ +int QScatterDataProxy::itemCount() const +{ + return dptrc()->m_dataArray->size(); +} + +/*! + * \return pointer to the data array. + */ +const QScatterDataArray *QScatterDataProxy::array() const +{ + return dptrc()->m_dataArray; +} + +/*! + * \return pointer to the item at \a index. It is guaranteed to be valid only until next call + * that modifies data. + */ +const QScatterDataItem *QScatterDataProxy::itemAt(int index) const +{ + return &dptrc()->m_dataArray->at(index); +} + +/*! + * \internal + */ +QScatterDataProxyPrivate *QScatterDataProxy::dptr() +{ + return static_cast<QScatterDataProxyPrivate *>(d_ptr.data()); +} + +/*! + * \internal + */ +const QScatterDataProxyPrivate *QScatterDataProxy::dptrc() const +{ + return static_cast<const QScatterDataProxyPrivate *>(d_ptr.data()); +} + +/*! + * \fn void QScatterDataProxy::arrayReset() + * + * Emitted when data array is reset. + * If you change the whole array contents without calling resetArray(), you need to + * emit this signal yourself or the graph won't get updated. + */ + +/*! + * \fn void QScatterDataProxy::itemsAdded(int startIndex, int count) + * + * Emitted when items have been added. Provides \a startIndex and \a count of items added. + * If you add items directly to the array without calling addItem() or addItems(), you + * need to emit this signal yourself or the graph won't get updated. + */ + +/*! + * \fn void QScatterDataProxy::itemsChanged(int startIndex, int count) + * + * Emitted when items have changed. Provides \a startIndex and \a count of changed items. + * If you change items directly in the array without calling setItem() or setItems(), you + * need to emit this signal yourself or the graph won't get updated. + */ + +/*! + * \fn void QScatterDataProxy::itemsRemoved(int startIndex, int count) + * + * Emitted when items have been removed. Provides \a startIndex and \a count of items removed. + * Index may be over current array size if removed from end. + * If you remove items directly from the array without calling removeItems(), you + * need to emit this signal yourself or the graph won't get updated. + */ + +/*! + * \fn void QScatterDataProxy::itemsInserted(int startIndex, int count) + * + * Emitted when items have been inserted. Provides \a startIndex and \a count of inserted items. + * If you insert items directly into the array without calling insertItem() or insertItems(), you + * need to emit this signal yourself or the graph won't get updated. + */ + +// QScatterDataProxyPrivate + +QScatterDataProxyPrivate::QScatterDataProxyPrivate(QScatterDataProxy *q) + : QAbstractDataProxyPrivate(q, QAbstractDataProxy::DataTypeScatter), + m_dataArray(new QScatterDataArray) +{ + m_itemLabelFormat = QStringLiteral("(@xLabel, @yLabel, @zLabel)"); +} + +QScatterDataProxyPrivate::~QScatterDataProxyPrivate() +{ + m_dataArray->clear(); + delete m_dataArray; +} + +void QScatterDataProxyPrivate::resetArray(QScatterDataArray *newArray) +{ + if (!newArray) + newArray = new QScatterDataArray; + + if (newArray != m_dataArray) { + m_dataArray->clear(); + delete m_dataArray; + m_dataArray = newArray; + } +} + +void QScatterDataProxyPrivate::setItem(int index, const QScatterDataItem &item) +{ + Q_ASSERT(index >= 0 && index < m_dataArray->size()); + (*m_dataArray)[index] = item; +} + +void QScatterDataProxyPrivate::setItems(int index, const QScatterDataArray &items) +{ + Q_ASSERT(index >= 0 && (index + items.size()) <= m_dataArray->size()); + for (int i = 0; i < items.size(); i++) + (*m_dataArray)[index++] = items[i]; +} + +int QScatterDataProxyPrivate::addItem(const QScatterDataItem &item) +{ + int currentSize = m_dataArray->size(); + m_dataArray->append(item); + return currentSize; +} + +int QScatterDataProxyPrivate::addItems(const QScatterDataArray &items) +{ + int currentSize = m_dataArray->size(); + (*m_dataArray) += items; + return currentSize; +} + +void QScatterDataProxyPrivate::insertItem(int index, const QScatterDataItem &item) +{ + Q_ASSERT(index >= 0 && index <= m_dataArray->size()); + m_dataArray->insert(index, item); +} + +void QScatterDataProxyPrivate::insertItems(int index, const QScatterDataArray &items) +{ + Q_ASSERT(index >= 0 && index <= m_dataArray->size()); + for (int i = 0; i < items.size(); i++) + m_dataArray->insert(index++, items.at(i)); +} + +void QScatterDataProxyPrivate::removeItems(int index, int removeCount) +{ + Q_ASSERT(index >= 0); + int maxRemoveCount = m_dataArray->size() - index; + removeCount = qMin(removeCount, maxRemoveCount); + m_dataArray->remove(index, removeCount); +} + +QVector3D QScatterDataProxyPrivate::limitValues() +{ + QVector3D limits; + for (int i = 0; i < m_dataArray->size(); i++) { + const QScatterDataItem &item = m_dataArray->at(i); + float xValue = qAbs(item.position().x()); + if (limits.x() < xValue) + limits.setX(xValue); + float yValue = qAbs(item.position().y()); + if (limits.y() < yValue) + limits.setY(yValue); + float zValue = qAbs(item.position().z()); + if (limits.z() < zValue) + limits.setZ(zValue); + } + return limits; +} + +QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavisualization/data/qscatterdataproxy.h b/src/datavisualization/data/qscatterdataproxy.h new file mode 100644 index 00000000..178bc900 --- /dev/null +++ b/src/datavisualization/data/qscatterdataproxy.h @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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 +** +****************************************************************************/ + +#ifndef QSCATTERDATAPROXY_H +#define QSCATTERDATAPROXY_H + +#include <QtDataVisualization/qabstractdataproxy.h> +#include <QtDataVisualization/qscatterdataitem.h> + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +typedef QVector<QScatterDataItem> QScatterDataArray; + +class QScatterDataProxyPrivate; + +class QT_DATAVISUALIZATION_EXPORT QScatterDataProxy : public QAbstractDataProxy +{ + Q_OBJECT + + Q_PROPERTY(int itemCount READ itemCount) + +public: + explicit QScatterDataProxy(QObject *parent = 0); + virtual ~QScatterDataProxy(); + + // TODO: Replace first part of class description in docs with this once all TODOs are done: + /* + * QScatterDataProxy handles adding, inserting, changing and removing data items. + * QScatterDataProxy is optimized to use cases where the only defining characteristics of an + * individual scatter item are it's position and size. Modifying other data that might be + * added in the future such as color requires allocating additional data object for the bar. + */ + + int itemCount() const; + const QScatterDataArray *array() const; + const QScatterDataItem *itemAt(int index) const; + + void resetArray(QScatterDataArray *newArray); + + void setItem(int index, const QScatterDataItem &item); + void setItems(int index, const QScatterDataArray &items); + + int addItem(const QScatterDataItem &item); + int addItems(const QScatterDataArray &items); + + void insertItem(int index, const QScatterDataItem &item); + void insertItems(int index, const QScatterDataArray &items); + + void removeItems(int index, int removeCount); + +signals: + void arrayReset(); + void itemsAdded(int startIndex, int count); + void itemsChanged(int startIndex, int count); + void itemsRemoved(int startIndex, int count); + void itemsInserted(int startIndex, int count); + +protected: + explicit QScatterDataProxy(QScatterDataProxyPrivate *d, QObject *parent = 0); + QScatterDataProxyPrivate *dptr(); + const QScatterDataProxyPrivate *dptrc() const; + +private: + Q_DISABLE_COPY(QScatterDataProxy) + + friend class Scatter3DController; +}; + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif diff --git a/src/datavisualization/data/qscatterdataproxy_p.h b/src/datavisualization/data/qscatterdataproxy_p.h new file mode 100644 index 00000000..9920e3a7 --- /dev/null +++ b/src/datavisualization/data/qscatterdataproxy_p.h @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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 +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVisualization API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. + +#ifndef QSCATTERDATAPROXY_P_H +#define QSCATTERDATAPROXY_P_H + +#include "qscatterdataproxy.h" +#include "qabstractdataproxy_p.h" +#include "qscatterdataitem.h" + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +class QScatterDataProxyPrivate : public QAbstractDataProxyPrivate +{ + Q_OBJECT +public: + QScatterDataProxyPrivate(QScatterDataProxy *q); + virtual ~QScatterDataProxyPrivate(); + + void resetArray(QScatterDataArray *newArray); + void setItem(int index, const QScatterDataItem &item); + void setItems(int index, const QScatterDataArray &items); + int addItem(const QScatterDataItem &item); + int addItems(const QScatterDataArray &items); + void insertItem(int index, const QScatterDataItem &item); + void insertItems(int index, const QScatterDataArray &items); + void removeItems(int index, int removeCount); + + QVector3D limitValues(); + +private: + QScatterDataArray *m_dataArray; + + friend class QScatterDataProxy; +}; + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif // QBARDATAPROXY_P_H diff --git a/src/datavisualization/data/qsurfacedataitem.cpp b/src/datavisualization/data/qsurfacedataitem.cpp new file mode 100644 index 00000000..19f8f347 --- /dev/null +++ b/src/datavisualization/data/qsurfacedataitem.cpp @@ -0,0 +1,143 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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 "qsurfacedataitem_p.h" + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +/*! + * \class QSurfaceDataItem + * \inmodule QtDataVisualization + * \brief The QSurfaceDataItem class provides a container for resolved data to be added to surface + * graphs. + * \since 1.0.0 + * + * A QSurfaceDataItem holds data for a single vertex in surface graph. + * Surface data proxies parse data into QSurfaceDataItem instances for visualizing. + * + * \sa QSurfaceDataProxy, {Qt Data Visualization C++ Classes} + */ + +/*! + * Constructs QSurfaceDataItem. + */ +QSurfaceDataItem::QSurfaceDataItem() + : d_ptr(0) // private data doesn't exist by default (optimization) + +{ +} + +/*! + * Constructs QSurfaceDataItem with \a position. + */ +QSurfaceDataItem::QSurfaceDataItem(const QVector3D &position) + : d_ptr(0), + m_position(position) +{ +} + +/*! + * Constructs a copy of \a other. + */ +QSurfaceDataItem::QSurfaceDataItem(const QSurfaceDataItem &other) +{ + operator=(other); +} + +/*! + * Destroys QSurfaceDataItem. + */ +QSurfaceDataItem::~QSurfaceDataItem() +{ +} + +/*! + * Assigns a copy of \a other to this object. + */ +QSurfaceDataItem &QSurfaceDataItem::operator=(const QSurfaceDataItem &other) +{ + m_position = other.m_position; + //m_size = other.m_size; + + if (other.d_ptr) + createExtraData(); + else + d_ptr = 0; + // TODO set extra data + + return *this; +} + +/*! + * \fn void QSurfaceDataItem::setPosition(const QVector3D &position) + * Sets \a position to this data item. + */ + +/*! + * \fn QVector3D QSurfaceDataItem::position() const + * \return position of this data item. + */ + +/*! + * \fn void QSurfaceDataItem::setX(float value) + * Sets the X component of the item position to the \a value. + */ + +/*! + * \fn void QSurfaceDataItem::setY(float value) + * Sets the Y component of the item position to the \a value. + */ + +/*! + * \fn void QSurfaceDataItem::setZ(float value) + * Sets the Z component of the item position to the \a value. + */ + +/*! + * \fn float QSurfaceDataItem::x() const + * \return the X component of the position of this data item. + */ + +/*! + * \fn float QSurfaceDataItem::y() const + * \return the Y component of the position of this data item. + */ + +/*! + * \fn float QSurfaceDataItem::z() const + * \return the Z component of the position of this data item. + */ + +/*! + * \internal + */ +void QSurfaceDataItem::createExtraData() +{ + if (!d_ptr) + d_ptr = new QSurfaceDataItemPrivate; +} + +QSurfaceDataItemPrivate::QSurfaceDataItemPrivate() +{ +} + +QSurfaceDataItemPrivate::~QSurfaceDataItemPrivate() +{ +} + +QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavisualization/data/qsurfacedataitem.h b/src/datavisualization/data/qsurfacedataitem.h new file mode 100644 index 00000000..dbc849d3 --- /dev/null +++ b/src/datavisualization/data/qsurfacedataitem.h @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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 +** +****************************************************************************/ + +#ifndef QSURFACEDATAITEM_H +#define QSURFACEDATAITEM_H + +#include <QtDataVisualization/qdatavisualizationenums.h> +#include <QVector3D> + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +class QSurfaceDataItemPrivate; + +class QT_DATAVISUALIZATION_EXPORT QSurfaceDataItem +{ +public: + QSurfaceDataItem(); + QSurfaceDataItem(const QVector3D &position); + QSurfaceDataItem(const QSurfaceDataItem &other); + ~QSurfaceDataItem(); + + QSurfaceDataItem &operator=(const QSurfaceDataItem &other); + + inline void setPosition(const QVector3D &position) { m_position = position; } + inline QVector3D position() const { return m_position; } + inline void setX(float value) { m_position.setX(value); } + inline void setY(float value) { m_position.setY(value); } + inline void setZ(float value) { m_position.setZ(value); } + inline float x() const { return m_position.x(); } + inline float y() const { return m_position.y(); } + inline float z() const { return m_position.z(); } + +protected: + virtual void createExtraData(); + + QSurfaceDataItemPrivate *d_ptr; + +private: + QVector3D m_position; +}; + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif diff --git a/src/datavisualization/data/qsurfacedataitem_p.h b/src/datavisualization/data/qsurfacedataitem_p.h new file mode 100644 index 00000000..d13679a8 --- /dev/null +++ b/src/datavisualization/data/qsurfacedataitem_p.h @@ -0,0 +1,51 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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 +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVisualization API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. + +#ifndef QSURFACEDATAITEM_P_H +#define QSURFACEDATAITEM_P_H + +#include "datavisualizationglobal_p.h" +#include "qsurfacedataitem.h" + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +class QSurfaceDataItemPrivate +{ +public: + QSurfaceDataItemPrivate(); + virtual ~QSurfaceDataItemPrivate(); + + // TODO stores other data for surface items besides position + +protected: + friend class QSurfaceDataItem; +}; + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif diff --git a/src/datavisualization/data/qsurfacedataproxy.cpp b/src/datavisualization/data/qsurfacedataproxy.cpp new file mode 100644 index 00000000..72f33de7 --- /dev/null +++ b/src/datavisualization/data/qsurfacedataproxy.cpp @@ -0,0 +1,289 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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 "qsurfacedataproxy.h" +#include "qsurfacedataproxy_p.h" + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +/*! + * \class QSurfaceDataProxy + * \inmodule QtDataVisualization + * \brief Base proxy class for Q3DSurface. + * \since 1.0.0 + * + * QSurfaceDataProxy takes care of surface related data handling. The QSurfaceDataProxy handles the data + * in rows and for this it provides two auxiliary typedefs. QSurfaceDataArray is a QList for + * controlling the rows. For rows there is a QVector QSurfaceDataRow which contains QSurfaceDataItem + * objects. See Q3DSurface documentation and basic sample code there how to feed the data for the + * QSurfaceDataProxy. + * + * All rows must have same number of items. + * + * When determining what rows and columns are visible, the first item in each row and the first item in + * each column determine if the whole row or column is visible, even if other items in the row or column + * individually have different X- or Z-coordinates. + * + * \note Surfaces with less than two rows or columns are not considered valid surfaces and will + * not get rendered. + * + * QSurfaceDataProxy supports the following format tags for QAbstractDataProxy::setItemLabelFormat(): + * \table + * \row + * \li @xTitle \li Title from X axis + * \row + * \li @yTitle \li Title from Y axis + * \row + * \li @zTitle \li Title from Z axis + * \row + * \li @xLabel \li Item value formatted using the same format as the X axis attached to the graph uses, + * see \l{Q3DValueAxis::setLabelFormat()} for more information. + * \row + * \li @yLabel \li Item value formatted using the same format as the Y axis attached to the graph uses, + * see \l{Q3DValueAxis::setLabelFormat()} for more information. + * \row + * \li @zLabel \li Item value formatted using the same format as the Z axis attached to the graph uses, + * see \l{Q3DValueAxis::setLabelFormat()} for more information. + * \endtable + * + * \sa {Qt Data Visualization Data Handling} + */ + +/*! + * \qmltype SurfaceDataProxy + * \inqmlmodule com.digia.QtDataVisualization 1.0 + * \since com.digia.QtDataVisualization 1.0 + * \ingroup datavisualization_qml + * \instantiates QSurfaceDataProxy + * \inherits AbstractDataProxy + * \brief Base proxy class for Surface3D. + * + * This type handles surface data items. The data is arranged into rows and columns, and all rows must have + * the same number of columns. + * + * This type is uncreatable, but contains properties that are exposed via subtypes. + * + * For more complete description, see QSurfaceDataProxy. + * + * \sa ItemModelSurfaceDataProxy, {Qt Data Visualization Data Handling} + */ + +/*! + * \qmlproperty int SurfaceDataProxy::rowCount + * Number of the rows in the array. + */ + +/*! + * \qmlproperty int SurfaceDataProxy::columnCount + * Number of the columns in the array. + */ + +/*! + * Constructs QSurfaceDataProxy with the given \a parent. + */ +QSurfaceDataProxy::QSurfaceDataProxy(QObject *parent) : + QAbstractDataProxy(new QSurfaceDataProxyPrivate(this), parent) +{ +} + +/*! + * \internal + */ +QSurfaceDataProxy::QSurfaceDataProxy(QSurfaceDataProxyPrivate *d, QObject *parent) : + QAbstractDataProxy(d, parent) +{ +} + +/*! + * Destroys QSurfaceDataProxy. + */ +QSurfaceDataProxy::~QSurfaceDataProxy() +{ +} + +/*! + * Takes ownership of the \a newArray. Clears the existing array and if the \a newArray is + * different than the existing array. If it's the same array, this just triggers arrayReset() + * signal. + * Passing null array deletes the old array and creates a new empty array. + * All rows in \a newArray must be of same length. + */ +void QSurfaceDataProxy::resetArray(QSurfaceDataArray *newArray) +{ + if (dptr()->m_dataArray != newArray) { + dptr()->resetArray(newArray); + } + emit arrayReset(); +} + +/*! + * \return pointer to the data array. + */ +const QSurfaceDataArray *QSurfaceDataProxy::array() const +{ + return dptrc()->m_dataArray; +} + +/*! + * \property QSurfaceDataProxy::rowCount + * + * \return number of rows in the data. + */ +int QSurfaceDataProxy::rowCount() const +{ + return dptrc()->m_dataArray->size(); +} + +/*! + * \property QSurfaceDataProxy::columnCount + * + * \return number of items in the columns. + */ +int QSurfaceDataProxy::columnCount() const +{ + if (dptrc()->m_dataArray->size() > 0) + return dptrc()->m_dataArray->at(0)->size(); + else + return 0; +} + +/*! + * \return pointer to the item at \a index. It is guaranteed to be valid only until next call that + * modifies data. + */ +const QSurfaceDataItem *QSurfaceDataProxy::itemAt(int index) const +{ + return &dptrc()->m_dataArray->at(index)->at(2); +} + +/*! + * \internal + */ +QSurfaceDataProxyPrivate *QSurfaceDataProxy::dptr() +{ + return static_cast<QSurfaceDataProxyPrivate *>(d_ptr.data()); +} + +/*! + * \internal + */ +const QSurfaceDataProxyPrivate *QSurfaceDataProxy::dptrc() const +{ + return static_cast<const QSurfaceDataProxyPrivate *>(d_ptr.data()); +} + +/*! + * \fn void QSurfaceDataProxy::arrayReset() + * + * Emitted when data array is reset. + * If you change the whole array contents without calling resetArray(), you need to + * emit this signal yourself or the graph won't get updated. + */ + +// +// QSurfaceDataProxyPrivate +// + +QSurfaceDataProxyPrivate::QSurfaceDataProxyPrivate(QSurfaceDataProxy *q) + : QAbstractDataProxyPrivate(q, QAbstractDataProxy::DataTypeSurface), + m_dataArray(new QSurfaceDataArray) +{ + m_itemLabelFormat = QStringLiteral("@yLabel (@xLabel, @zLabel)"); +} + +QSurfaceDataProxyPrivate::~QSurfaceDataProxyPrivate() +{ + clearArray(); +} + +void QSurfaceDataProxyPrivate::resetArray(QSurfaceDataArray *newArray) +{ + if (!newArray) + newArray = new QSurfaceDataArray; + + if (newArray != m_dataArray) { + clearArray(); + m_dataArray = newArray; + } +} + +QSurfaceDataProxy *QSurfaceDataProxyPrivate::qptr() +{ + return static_cast<QSurfaceDataProxy *>(q_ptr); +} + +void QSurfaceDataProxyPrivate::limitValues(QVector3D &minValues, QVector3D &maxValues) +{ + qreal min = 0.0; + qreal max = 0.0; + + int rows = m_dataArray->size(); + int columns = 0; + if (rows) + columns = m_dataArray->at(0)->size(); + + if (rows && columns) { + min = m_dataArray->at(0)->at(0).y(); + max = m_dataArray->at(0)->at(0).y(); + } + + for (int i = 0; i < rows; i++) { + QSurfaceDataRow *row = m_dataArray->at(i); + if (row) { + for (int j = 0; j < columns; j++) { + qreal itemValue = m_dataArray->at(i)->at(j).y(); + if (min > itemValue) + min = itemValue; + if (max < itemValue) + max = itemValue; + } + } + } + + 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()); + } else { + minValues.setX(0.0f); + minValues.setZ(0.0f); + maxValues.setX(0.0f); + maxValues.setZ(0.0f); + } +} + +void QSurfaceDataProxyPrivate::clearRow(int rowIndex) +{ + if (m_dataArray->at(rowIndex)) { + delete m_dataArray->at(rowIndex); + (*m_dataArray)[rowIndex] = 0; + } +} + +void QSurfaceDataProxyPrivate::clearArray() +{ + for (int i = 0; i < m_dataArray->size(); i++) + clearRow(i); + m_dataArray->clear(); + delete m_dataArray; +} + +QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavisualization/data/qsurfacedataproxy.h b/src/datavisualization/data/qsurfacedataproxy.h new file mode 100644 index 00000000..460fa437 --- /dev/null +++ b/src/datavisualization/data/qsurfacedataproxy.h @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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 +** +****************************************************************************/ + +#ifndef QSURFACEDATAPROXY_H +#define QSURFACEDATAPROXY_H + +#include <QtDataVisualization/qabstractdataproxy.h> +#include <QtDataVisualization/qsurfacedataitem.h> + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +typedef QVector<QSurfaceDataItem> QSurfaceDataRow; +typedef QList<QSurfaceDataRow *> QSurfaceDataArray; + +class QSurfaceDataProxyPrivate; + +class QT_DATAVISUALIZATION_EXPORT QSurfaceDataProxy : public QAbstractDataProxy +{ + Q_OBJECT + + Q_PROPERTY(int rowCount READ rowCount) + Q_PROPERTY(int columnCount READ columnCount) + +public: + explicit QSurfaceDataProxy(QObject *parent = 0); + virtual ~QSurfaceDataProxy(); + + int rowCount() const; + int columnCount() const; + const QSurfaceDataArray *array() const; + const QSurfaceDataItem *itemAt(int index) const; + + void resetArray(QSurfaceDataArray *newArray); + +signals: + void arrayReset(); + +protected: + explicit QSurfaceDataProxy(QSurfaceDataProxyPrivate *d, QObject *parent = 0); + QSurfaceDataProxyPrivate *dptr(); + const QSurfaceDataProxyPrivate *dptrc() const; + +private: + Q_DISABLE_COPY(QSurfaceDataProxy) + + friend class Surface3DController; +}; + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif // QSURFACEDATAPROXY_H diff --git a/src/datavisualization/data/qsurfacedataproxy_p.h b/src/datavisualization/data/qsurfacedataproxy_p.h new file mode 100644 index 00000000..4c8c2820 --- /dev/null +++ b/src/datavisualization/data/qsurfacedataproxy_p.h @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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 +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVisualization API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. + +#ifndef QSURFACEDATAPROXY_P_H +#define QSURFACEDATAPROXY_P_H + +#include "qsurfacedataproxy.h" +#include "qabstractdataproxy_p.h" + +#include <QSize> + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +class QSurfaceDataProxyPrivate : public QAbstractDataProxyPrivate +{ + Q_OBJECT +public: + QSurfaceDataProxyPrivate(QSurfaceDataProxy *q); + virtual ~QSurfaceDataProxyPrivate(); + + void resetArray(QSurfaceDataArray *newArray); + + void limitValues(QVector3D &minValues, QVector3D &maxValues); + +protected: + QSurfaceDataArray *m_dataArray; + +private: + QSurfaceDataProxy *qptr(); + void clearRow(int rowIndex); + void clearArray(); + + friend class QSurfaceDataProxy; +}; + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif // QSURFACEDATAPROXY_P_H diff --git a/src/datavisualization/data/scatteritemmodelhandler.cpp b/src/datavisualization/data/scatteritemmodelhandler.cpp new file mode 100644 index 00000000..34230ae0 --- /dev/null +++ b/src/datavisualization/data/scatteritemmodelhandler.cpp @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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 "scatteritemmodelhandler_p.h" +#include <QTimer> + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +ScatterItemModelHandler::ScatterItemModelHandler(QItemModelScatterDataProxy *proxy, QObject *parent) + : AbstractItemModelHandler(parent), + m_proxy(proxy), + m_proxyArray(0) +{ +} + +ScatterItemModelHandler::~ScatterItemModelHandler() +{ +} + +// Resolve entire item model into QScatterDataArray. +void ScatterItemModelHandler::resolveModel() +{ + QItemModelScatterDataMapping *mapping = static_cast<QItemModelScatterDataMapping *>(m_activeMapping); + if (m_itemModel.isNull() || !mapping) { + m_proxy->resetArray(0); + m_proxyArray = 0; + return; + } + + static const int noRoleIndex = -1; + + QHash<int, QByteArray> roleHash = m_itemModel->roleNames(); + const int xPosRole = roleHash.key(mapping->xPosRole().toLatin1(), noRoleIndex); + const int yPosRole = roleHash.key(mapping->yPosRole().toLatin1(), noRoleIndex); + const int zPosRole = roleHash.key(mapping->zPosRole().toLatin1(), noRoleIndex); + const int columnCount = m_itemModel->columnCount(); + const int rowCount = m_itemModel->rowCount(); + const int totalCount = rowCount * columnCount; + int runningCount = 0; + + // If dimensions have changed, recreate the array + if (m_proxyArray != m_proxy->array() || totalCount != m_proxyArray->size()) + m_proxyArray = new QScatterDataArray(totalCount); + + // Parse data into newProxyArray + for (int i = 0; i < rowCount; i++) { + for (int j = 0; j < columnCount; j++) { + QModelIndex index = m_itemModel->index(i, j); + float xPos(0.0f); + float yPos(0.0f); + float zPos(0.0f); + if (xPosRole != noRoleIndex) + xPos = index.data(xPosRole).toFloat(); + if (yPosRole != noRoleIndex) + yPos = index.data(yPosRole).toFloat(); + if (zPosRole != noRoleIndex) + zPos = index.data(zPosRole).toFloat(); + (*m_proxyArray)[runningCount].setPosition(QVector3D(xPos, yPos, zPos)); + runningCount++; + } + } + + m_proxy->resetArray(m_proxyArray); +} + +QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavisualization/data/scatteritemmodelhandler_p.h b/src/datavisualization/data/scatteritemmodelhandler_p.h new file mode 100644 index 00000000..9b8a19a2 --- /dev/null +++ b/src/datavisualization/data/scatteritemmodelhandler_p.h @@ -0,0 +1,53 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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 +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVisualization API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. + +#ifndef SCATTERITEMMODELHANDLER_P_H +#define SCATTERITEMMODELHANDLER_P_H + +#include "abstractitemmodelhandler_p.h" +#include "qitemmodelscatterdataproxy.h" + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +class ScatterItemModelHandler : public AbstractItemModelHandler +{ + Q_OBJECT +public: + ScatterItemModelHandler(QItemModelScatterDataProxy *proxy, QObject *parent = 0); + virtual ~ScatterItemModelHandler(); + +protected: + void virtual resolveModel(); + + QItemModelScatterDataProxy *m_proxy; // Not owned + QScatterDataArray *m_proxyArray; // Not owned +}; + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif diff --git a/src/datavisualization/data/scatterrenderitem.cpp b/src/datavisualization/data/scatterrenderitem.cpp new file mode 100644 index 00000000..83c66583 --- /dev/null +++ b/src/datavisualization/data/scatterrenderitem.cpp @@ -0,0 +1,42 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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 "scatterrenderitem_p.h" +#include "scatter3drenderer_p.h" +#include "qscatterdataproxy.h" + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +ScatterRenderItem::ScatterRenderItem() + : AbstractRenderItem(), + m_visible(false) +{ +} + +ScatterRenderItem::ScatterRenderItem(const ScatterRenderItem &other) + : AbstractRenderItem(other), + m_visible(false) +{ + m_position = other.m_position; +} + +ScatterRenderItem::~ScatterRenderItem() +{ +} + +QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavisualization/data/scatterrenderitem_p.h b/src/datavisualization/data/scatterrenderitem_p.h new file mode 100644 index 00000000..58e91e96 --- /dev/null +++ b/src/datavisualization/data/scatterrenderitem_p.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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 +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVisualization API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. + +#ifndef SCATTERRENDERITEM_P_H +#define SCATTERRENDERITEM_P_H + +#include "abstractrenderitem_p.h" + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +class Scatter3DRenderer; + +class ScatterRenderItem : public AbstractRenderItem +{ +public: + ScatterRenderItem(); + ScatterRenderItem(const ScatterRenderItem &other); + virtual ~ScatterRenderItem(); + + inline const QVector3D &position() const { return m_position; } + inline void setPosition(const QVector3D &pos); + + inline bool isVisible() const { return m_visible; } + inline void setVisible(bool visible) { m_visible = visible; } + + //inline void setSize(qreal size); + //inline qreal size() const { return m_size; } + +protected: + QVector3D m_position; + bool m_visible; + //qreal m_size; // TODO in case we need a fourth variable that adjusts scatter item size + + friend class QScatterDataItem; +}; + +void ScatterRenderItem::setPosition(const QVector3D &pos) +{ + if (m_position != pos) { + m_position = pos; + // Force reformatting on next access by setting label string to null string + if (!m_selectionLabel.isNull()) + setSelectionLabel(QString()); + } +} + +typedef QVector<ScatterRenderItem> ScatterRenderItemArray; + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif diff --git a/src/datavisualization/data/surfaceitemmodelhandler.cpp b/src/datavisualization/data/surfaceitemmodelhandler.cpp new file mode 100644 index 00000000..70482162 --- /dev/null +++ b/src/datavisualization/data/surfaceitemmodelhandler.cpp @@ -0,0 +1,144 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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 "surfaceitemmodelhandler_p.h" +#include "qitemmodelsurfacedatamapping_p.h" + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +SurfaceItemModelHandler::SurfaceItemModelHandler(QItemModelSurfaceDataProxy *proxy, QObject *parent) + : AbstractItemModelHandler(parent), + m_proxy(proxy), + m_proxyArray(0) +{ +} + +SurfaceItemModelHandler::~SurfaceItemModelHandler() +{ +} + +// Resolve entire item model into QSurfaceDataArray. +void SurfaceItemModelHandler::resolveModel() +{ + QItemModelSurfaceDataMapping *mapping = static_cast<QItemModelSurfaceDataMapping *>(m_activeMapping); + if (m_itemModel.isNull() || !mapping) { + m_proxy->resetArray(0); + m_proxyArray = 0; + return; + } + + if (!mapping->useModelCategories() + && (mapping->rowRole().isEmpty() || mapping->columnRole().isEmpty())) { + m_proxy->resetArray(0); + m_proxyArray = 0; + return; + } + + QHash<int, QByteArray> roleHash = m_itemModel->roleNames(); + + // Default to display role if no mapping + int valueRole = roleHash.key(mapping->valueRole().toLatin1(), Qt::DisplayRole); + int rowCount = m_itemModel->rowCount(); + int columnCount = m_itemModel->columnCount(); + + if (mapping->useModelCategories()) { + // If dimensions have changed, recreate the array + if (m_proxyArray != m_proxy->array() || columnCount != m_proxy->columnCount() + || rowCount != m_proxyArray->size()) { + m_proxyArray = new QSurfaceDataArray; + m_proxyArray->reserve(rowCount); + for (int i = 0; i < rowCount; i++) + m_proxyArray->append(new QSurfaceDataRow(columnCount)); + } + for (int i = 0; i < rowCount; i++) { + QSurfaceDataRow &newProxyRow = *m_proxyArray->at(i); + for (int j = 0; j < columnCount; j++) { + newProxyRow[j].setPosition( + QVector3D(m_itemModel->headerData(j, Qt::Horizontal).toFloat(), + m_itemModel->index(i, j).data(valueRole).toFloat(), + m_itemModel->headerData(i, Qt::Vertical).toFloat())); + } + } + } else { + int rowRole = roleHash.key(mapping->rowRole().toLatin1()); + int columnRole = roleHash.key(mapping->columnRole().toLatin1()); + + bool generateRows = mapping->autoRowCategories(); + bool generateColumns = mapping->autoColumnCategories(); + + QStringList rowList; + QStringList columnList; + // For detecting duplicates in categories generation, using QHashes should be faster than + // simple QStringList::contains() check. + QHash<QString, bool> rowListHash; + QHash<QString, bool> columnListHash; + + // Sort values into rows and columns + typedef QHash<QString, qreal> ColumnValueMap; + QHash <QString, ColumnValueMap> itemValueMap; + 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 (generateRows && !rowListHash.value(rowRoleStr, false)) { + rowListHash.insert(rowRoleStr, true); + rowList << rowRoleStr; + } + if (generateColumns && !columnListHash.value(columnRoleStr, false)) { + columnListHash.insert(columnRoleStr, true); + columnList << columnRoleStr; + } + } + } + + if (generateRows) + mapping->dptr()->m_rowCategories = rowList; + else + rowList = mapping->rowCategories(); + + if (generateColumns) + mapping->dptr()->m_columnCategories = columnList; + else + columnList = mapping->columnCategories(); + + // If dimensions have changed, recreate the array + if (m_proxyArray != m_proxy->array() || columnList.size() != m_proxy->columnCount() + || rowList.size() != m_proxyArray->size()) { + m_proxyArray = new QSurfaceDataArray; + m_proxyArray->reserve(rowList.size()); + for (int i = 0; i < rowList.size(); i++) + m_proxyArray->append(new QSurfaceDataRow(columnList.size())); + } + // Create data array from itemValueMap + for (int i = 0; i < rowList.size(); i++) { + QString rowKey = rowList.at(i); + QSurfaceDataRow &newProxyRow = *m_proxyArray->at(i); + for (int j = 0; j < columnList.size(); j++) { + newProxyRow[j].setPosition(QVector3D(columnList.at(j).toFloat(), + itemValueMap[rowKey][columnList.at(j)], + rowList.at(i).toFloat())); + } + } + } + + m_proxy->resetArray(m_proxyArray); +} + +QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavisualization/data/surfaceitemmodelhandler_p.h b/src/datavisualization/data/surfaceitemmodelhandler_p.h new file mode 100644 index 00000000..bcf642c5 --- /dev/null +++ b/src/datavisualization/data/surfaceitemmodelhandler_p.h @@ -0,0 +1,53 @@ +/**************************************************************************** +** +** Copyright (C) 2013 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 +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtDataVisualization API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. + +#ifndef SURFACEITEMMODELHANDLER_P_H +#define SURFACEITEMMODELHANDLER_P_H + +#include "abstractitemmodelhandler_p.h" +#include "qitemmodelsurfacedataproxy.h" + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +class SurfaceItemModelHandler : public AbstractItemModelHandler +{ + Q_OBJECT +public: + SurfaceItemModelHandler(QItemModelSurfaceDataProxy *proxy, QObject *parent = 0); + virtual ~SurfaceItemModelHandler(); + +protected: + void virtual resolveModel(); + + QItemModelSurfaceDataProxy *m_proxy; // Not owned + QSurfaceDataArray *m_proxyArray; // Not owned +}; + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif |