diff options
Diffstat (limited to 'src')
321 files changed, 23605 insertions, 15699 deletions
diff --git a/src/datavis3d/axis/axis.pri b/src/datavis3d/axis/axis.pri deleted file mode 100644 index 7d5a1c6f..00000000 --- a/src/datavis3d/axis/axis.pri +++ /dev/null @@ -1,12 +0,0 @@ -HEADERS += \ - $$PWD/qabstractaxis.h \ - $$PWD/qabstractaxis_p.h \ - $$PWD/qvalueaxis.h \ - $$PWD/qvalueaxis_p.h \ - $$PWD/qcategoryaxis.h \ - $$PWD/qcategoryaxis_p.h - -SOURCES += \ - $$PWD/qabstractaxis.cpp \ - $$PWD/qvalueaxis.cpp \ - $$PWD/qcategoryaxis.cpp diff --git a/src/datavis3d/axis/qabstractaxis.cpp b/src/datavis3d/axis/qabstractaxis.cpp deleted file mode 100644 index 71b9effd..00000000 --- a/src/datavis3d/axis/qabstractaxis.cpp +++ /dev/null @@ -1,84 +0,0 @@ -/**************************************************************************** -** -** 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 QtDataVis3D 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 "qabstractaxis.h" -#include "qabstractaxis_p.h" - -QT_DATAVIS3D_BEGIN_NAMESPACE - -QAbstractAxis::QAbstractAxis(QAbstractAxisPrivate *d) : - QObject(0), - d_ptr(d) -{ -} - -QAbstractAxis::~QAbstractAxis() -{ -} - -QString QAbstractAxis::title() const -{ - return d_ptr->m_title; -} - -QStringList QAbstractAxis::labels() const -{ - return d_ptr->m_labels; -} - -QAbstractAxis::AxisOrientation QAbstractAxis::orientation() const -{ - return d_ptr->m_orientation; -} - -QAbstractAxis::AxisType QAbstractAxis::type() const -{ - return d_ptr->m_type; -} - -void QAbstractAxis::setTitle(QString title) -{ - if (d_ptr->m_title != title) { - d_ptr->m_title = title; - emit titleChanged(title); - } -} - -// QAbstractAxisPrivate - -QAbstractAxisPrivate::QAbstractAxisPrivate(QAbstractAxis *q, QAbstractAxis::AxisType type) - : QObject(0), - q_ptr(q), - m_orientation(QAbstractAxis::AxisOrientationNone), - m_type(type) -{ -} - -QAbstractAxisPrivate::~QAbstractAxisPrivate() -{ -} - -void QAbstractAxisPrivate::setOrientation(QAbstractAxis::AxisOrientation orientation) -{ - if (m_orientation == QAbstractAxis::AxisOrientationNone) - m_orientation = orientation; - else - Q_ASSERT("Attempted to reset axis orientation."); -} - -QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/axis/qabstractaxis_p.h b/src/datavis3d/axis/qabstractaxis_p.h deleted file mode 100644 index 3866ee75..00000000 --- a/src/datavis3d/axis/qabstractaxis_p.h +++ /dev/null @@ -1,61 +0,0 @@ -/**************************************************************************** -** -** 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 QtDataVis3D 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 QtDataVis3D 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 "datavis3dglobal_p.h" -#include "qabstractaxis.h" - -#ifndef QABSTRACTAXIS_P_H -#define QABSTRACTAXIS_P_H - -QT_DATAVIS3D_BEGIN_NAMESPACE - -class QAbstractAxisPrivate : public QObject -{ - Q_OBJECT -public: - QAbstractAxisPrivate(QAbstractAxis *q, QAbstractAxis::AxisType type); - virtual ~QAbstractAxisPrivate(); - - void setOrientation(QAbstractAxis::AxisOrientation orientation); - -protected: - QAbstractAxis *q_ptr; - - QString m_title; - QStringList m_labels; - QAbstractAxis::AxisOrientation m_orientation; - QAbstractAxis::AxisType m_type; - - friend class QAbstractAxis; - friend class QValueAxis; - friend class QCategoryAxis; -}; - -QT_DATAVIS3D_END_NAMESPACE - -#endif // QABSTRACTAXIS_P_H diff --git a/src/datavis3d/axis/qcategoryaxis.cpp b/src/datavis3d/axis/qcategoryaxis.cpp deleted file mode 100644 index c20eb80f..00000000 --- a/src/datavis3d/axis/qcategoryaxis.cpp +++ /dev/null @@ -1,60 +0,0 @@ -/**************************************************************************** -** -** 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 QtDataVis3D 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 "qcategoryaxis.h" -#include "qcategoryaxis_p.h" - -QT_DATAVIS3D_BEGIN_NAMESPACE - -QCategoryAxis::QCategoryAxis() : - QAbstractAxis(new QCategoryAxisPrivate(this)) -{ -} - -QCategoryAxis::~QCategoryAxis() -{ -} - -QStringList QCategoryAxis::categoryLabels() const -{ - return labels(); -} - -void QCategoryAxis::setCategoryLabels(const QStringList &labels) -{ - if (d_ptr->m_labels != labels) { - d_ptr->m_labels = labels; - emit labelsChanged(); - } -} - -QCategoryAxisPrivate *QCategoryAxis::dptr() -{ - return static_cast<QCategoryAxisPrivate *>(d_ptr.data()); -} - -QCategoryAxisPrivate::QCategoryAxisPrivate(QCategoryAxis *q) - : QAbstractAxisPrivate(q, QAbstractAxis::AxisTypeCategory) -{ -} - -QCategoryAxisPrivate::~QCategoryAxisPrivate() -{ -} - -QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/axis/qvalueaxis.cpp b/src/datavis3d/axis/qvalueaxis.cpp deleted file mode 100644 index cee8a5c7..00000000 --- a/src/datavis3d/axis/qvalueaxis.cpp +++ /dev/null @@ -1,235 +0,0 @@ -/**************************************************************************** -** -** 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 QtDataVis3D 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 "qvalueaxis.h" -#include "qvalueaxis_p.h" - -QT_DATAVIS3D_BEGIN_NAMESPACE - -QValueAxis::QValueAxis() : - QAbstractAxis(new QValueAxisPrivate(this)) -{ -} - -QValueAxis::~QValueAxis() -{ -} - -void QValueAxis::setRange(qreal min, qreal max) -{ - dptr()->setRange(min, max); - setAutoAdjustRange(false); -} - -void QValueAxis::setMin(qreal min) -{ - dptr()->setMin(min); - setAutoAdjustRange(false); -} - -void QValueAxis::setMax(qreal max) -{ - dptr()->setMax(max); - setAutoAdjustRange(false); -} - -qreal QValueAxis::min() const -{ - return dptrc()->m_min; -} - -qreal QValueAxis::max() const -{ - return dptrc()->m_max; -} - -void QValueAxis::setSegmentCount(int count) -{ - if (count <= 0) { - qWarning() << "Warning: Illegal segment count automatically adjusted to a legal one:" - << count << "-> 1"; - count = 1; - } - if (dptr()->m_segmentCount != count){ - dptr()->m_segmentCount = count; - dptr()->recreateLabels(); - emit segmentCountChanged(count); - } -} - -int QValueAxis::segmentCount() const -{ - return dptrc()->m_segmentCount; -} - -void QValueAxis::setSubSegmentCount(int count) -{ - if (count <= 0) { - qWarning() << "Warning: Illegal subsegment count automatically adjusted to a legal one:" - << count << "-> 1"; - count = 1; - } - if (dptr()->m_subSegmentCount != count) { - dptr()->m_subSegmentCount = count; - emit subSegmentCountChanged(count); - } -} - -int QValueAxis::subSegmentCount() const -{ - return dptrc()->m_subSegmentCount; -} - -void QValueAxis::setAutoAdjustRange(bool autoAdjust) -{ - if (dptr()->m_autoAdjust != autoAdjust) { - dptr()->m_autoAdjust = autoAdjust; - emit autoAdjustRangeChanged(autoAdjust); - } -} - -bool QValueAxis::isAutoAdjustRange() const -{ - return dptrc()->m_autoAdjust; -} - -void QValueAxis::setLabelFormat(const QString &format) -{ - if (dptr()->m_labelFormat != format) { - dptr()->m_labelFormat = format; - dptr()->recreateLabels(); - emit labelFormatChanged(format); - } -} - -QString QValueAxis::labelFormat() const -{ - return dptrc()->m_labelFormat; -} - -QValueAxisPrivate *QValueAxis::dptr() -{ - return static_cast<QValueAxisPrivate *>(d_ptr.data()); -} - -const QValueAxisPrivate *QValueAxis::dptrc() const -{ - return static_cast<const QValueAxisPrivate *>(d_ptr.data()); -} - -QValueAxisPrivate::QValueAxisPrivate(QValueAxis *q) - : QAbstractAxisPrivate(q, QAbstractAxis::AxisTypeValue), - m_min(0.0), - m_max(10.0), - m_segmentCount(5), - m_subSegmentCount(1), - m_autoAdjust(true) -{ -} - -QValueAxisPrivate::~QValueAxisPrivate() -{ -} - -void QValueAxisPrivate::setRange(qreal min, qreal max) -{ - // If min >= max, we adjust ranges so that - // m_max becomes (min + 1.0) - // as axes need some kind of valid range. - // TODO: Make "reverse" axes work (i.e. min > max) - bool dirty = false; - if (m_min != min) { - m_min = min; - dirty = true; - } - if (m_max != max) { - if (min >= max) { - m_max = min + 1.0; - qWarning() << "Warning: Tried to set invalid range for value axis." - " Range automatically adjusted to a valid one:" - << min << "-" << max << "-->" << m_min << "-" << m_max; - } else { - m_max = max; - } - dirty = true; - } - if (dirty) { - recreateLabels(); - emit qptr()->rangeChanged(min, max); - } -} - -void QValueAxisPrivate::setMin(qreal min) -{ - if (m_min != min) { - if (min >= m_max) { - qreal oldMax = m_max; - m_max = min + 1.0; - qWarning() << "Warning: Tried to set minimum to equal or larger than maximum for" - " value axis. Maximum automatically adjusted to a valid one:" - << oldMax << "-->" << m_max; - } - m_min = min; - recreateLabels(); - emit qptr()->rangeChanged(m_min, m_max); - } -} - -void QValueAxisPrivate::setMax(qreal max) -{ - if (m_max != max) { - if (max <= m_min) { - qreal oldMin = m_min; - m_min = max - 1.0; - qWarning() << "Warning: Tried to set maximum to equal or smaller than minimum for" - " value axis. Minimum automatically adjusted to a valid one:" - << oldMin << "-->" << m_min; - } - m_max = max; - recreateLabels(); - emit qptr()->rangeChanged(m_min, m_max); - } -} - -void QValueAxisPrivate::recreateLabels() -{ - QStringList newLabels; - newLabels.reserve(m_segmentCount + 1); - - // First label is at axis min, which is an extra segment - qreal segmentStep = (m_max - m_min) / m_segmentCount; - - for (int i = 0; i < m_segmentCount; i++) { - // TODO Actually do proper formatting - newLabels.append(QString::number(m_min + (segmentStep * i))); - } - // Ensure max label doesn't suffer from any rounding errors - newLabels.append(QString::number(m_max)); - - if (m_labels != newLabels) { - m_labels = newLabels; - emit q_ptr->labelsChanged(); - } -} - -QValueAxis *QValueAxisPrivate::qptr() -{ - return static_cast<QValueAxis *>(q_ptr); -} - -QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/data/maprenderitem.cpp b/src/datavis3d/data/maprenderitem.cpp deleted file mode 100644 index c7165104..00000000 --- a/src/datavis3d/data/maprenderitem.cpp +++ /dev/null @@ -1,52 +0,0 @@ -/**************************************************************************** -** -** 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 QtDataVis3D 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 "maprenderitem_p.h" -#include "maps3drenderer_p.h" // TODO remove when maps refactored -#include "maps3dcontroller_p.h" // TODO should be renderer -#include "qmapdataproxy.h" - -QT_DATAVIS3D_BEGIN_NAMESPACE - -MapRenderItem::MapRenderItem() - : BarRenderItem() -{ -} - -MapRenderItem::~MapRenderItem() -{ -} - -void MapRenderItem::formatLabel() -{ - // TODO The label format specified in proxy should probably have additional custom formatting - // TODO specifiers in addition to standard printf specifiers for placement of item labels - // TODO and selection data (like row/column in bar selection) - - // Format the string on first access - QString numStr; - numStr.setNum(m_value); - // TODO actually format instead of just prepending the value - m_label.clear(); // Just in case - m_label.append(m_itemLabel); - m_label.append(QStringLiteral(" ")); - m_label.append(numStr); - m_label.append(m_renderer->dataProxy()->itemLabelFormat()); -} - -QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/data/maprenderitem_p.h b/src/datavis3d/data/maprenderitem_p.h deleted file mode 100644 index f1e7290e..00000000 --- a/src/datavis3d/data/maprenderitem_p.h +++ /dev/null @@ -1,69 +0,0 @@ -/**************************************************************************** -** -** 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 QtDataVis3D 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 QtDataVis3D 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 MAPRENDERITEM_P_H -#define MAPRENDERITEM_P_H - -#include "barrenderitem_p.h" - -QT_DATAVIS3D_BEGIN_NAMESPACE - -class Maps3DRenderer; -class Maps3DController; // TODO remove when maps refactored - -class MapRenderItem : public BarRenderItem -{ -public: - MapRenderItem(); - virtual ~MapRenderItem(); - - inline const QPointF &mapPosition() const { return m_mapPosition; } - inline void setMapPosition(const QPointF &pos) { m_mapPosition = pos; } - - inline const QString &itemLabel() const { return m_itemLabel; } - inline void setItemLabel(const QString &label) { m_itemLabel = label; } - - // TODO should be in abstract, but currently there is no abstract renderer - // TODO change when maps refactored - inline void setRenderer(Maps3DController *renderer) { m_renderer = renderer; } - -protected: - virtual void formatLabel(); - - Maps3DController *m_renderer; - QPointF m_mapPosition; - QString m_itemLabel; // from QMapDataItem::label() - unformatted item label - - friend class QMapDataItem; -}; - -typedef QVector<MapRenderItem> MapRenderItemArray; - -QT_DATAVIS3D_END_NAMESPACE - -#endif diff --git a/src/datavis3d/data/qabstractdataproxy.cpp b/src/datavis3d/data/qabstractdataproxy.cpp deleted file mode 100644 index 11874edb..00000000 --- a/src/datavis3d/data/qabstractdataproxy.cpp +++ /dev/null @@ -1,68 +0,0 @@ -/**************************************************************************** -** -** 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 QtDataVis3D 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_DATAVIS3D_BEGIN_NAMESPACE - -QAbstractDataProxy::QAbstractDataProxy(QAbstractDataProxyPrivate *d) : - QObject(0), - d_ptr(d) -{ -} - -QAbstractDataProxy::~QAbstractDataProxy() -{ -} - -QAbstractDataProxy::DataType QAbstractDataProxy::type() const -{ - return d_ptr->m_type; -} - -void QAbstractDataProxy::setItemLabelFormat(const QString &format) -{ - d_ptr->setItemLabelFormat(format); - emit itemLabelFormatChanged(); -} - -QString QAbstractDataProxy::itemLabelFormat() const -{ - return d_ptr->m_itemLabelFormat; -} - -// QAbstractDataProxyPrivate - -QAbstractDataProxyPrivate::QAbstractDataProxyPrivate(QAbstractDataProxy *q, QAbstractDataProxy::DataType type) - : QObject(0), - q_ptr(q), - m_type(type) -{ -} - -QAbstractDataProxyPrivate::~QAbstractDataProxyPrivate() -{ -} - -void QAbstractDataProxyPrivate::setItemLabelFormat(const QString &format) -{ - m_itemLabelFormat = format; -} - -QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/data/qbardataproxy.cpp b/src/datavis3d/data/qbardataproxy.cpp deleted file mode 100644 index 589ed37a..00000000 --- a/src/datavis3d/data/qbardataproxy.cpp +++ /dev/null @@ -1,262 +0,0 @@ -/**************************************************************************** -** -** 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 QtDataVis3D 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_DATAVIS3D_BEGIN_NAMESPACE - -QBarDataProxy::QBarDataProxy() : - QAbstractDataProxy(new QBarDataProxyPrivate(this)) -{ -} - -QBarDataProxy::QBarDataProxy(QBarDataProxyPrivate *d) : - QAbstractDataProxy(d) -{ -} - -QBarDataProxy::~QBarDataProxy() -{ -} - -void QBarDataProxy::resetArray(QBarDataArray *newArray) -{ - if (dptr()->resetArray(newArray)) - emit arrayReset(); -} - -void QBarDataProxy::setRow(int rowIndex, QBarDataRow *row) -{ - dptr()->setRow(rowIndex, row); - emit rowsChanged(rowIndex, 1); -} - -void QBarDataProxy::setRows(int rowIndex, const QBarDataArray &rows) -{ - dptr()->setRows(rowIndex, rows); - emit rowsChanged(rowIndex, rows.size()); -} - -void QBarDataProxy::setItem(int rowIndex, int columnIndex, const QBarDataItem &item) -{ - dptr()->setItem(rowIndex, columnIndex, item); - emit itemChanged(rowIndex, columnIndex); -} - -int QBarDataProxy::addRow(QBarDataRow *row) -{ - int addIndex = dptr()->addRow(row); - emit rowsAdded(addIndex, 1); - return addIndex; -} - -int QBarDataProxy::addRows(const QBarDataArray &rows) -{ - int addIndex = dptr()->addRows(rows); - emit rowsAdded(addIndex, rows.size()); - return addIndex; -} - -void QBarDataProxy::insertRow(int rowIndex, QBarDataRow *row) -{ - dptr()->insertRow(rowIndex, row); - emit rowsInserted(rowIndex, 1); -} - -void QBarDataProxy::insertRows(int rowIndex, const QBarDataArray &rows) -{ - dptr()->insertRows(rowIndex, rows); - emit rowsInserted(rowIndex, rows.size()); -} - -void QBarDataProxy::removeRows(int rowIndex, int removeCount) -{ - if (rowIndex < rowCount()) { - dptr()->removeRows(rowIndex, removeCount); - emit rowsRemoved(rowIndex, removeCount); - } -} - -int QBarDataProxy::rowCount() const -{ - return dptrc()->m_dataArray->size(); -} - -const QBarDataArray *QBarDataProxy::array() const -{ - return dptrc()->m_dataArray; -} - -const QBarDataRow *QBarDataProxy::rowAt(int rowIndex) const -{ - const QBarDataArray &dataArray = *dptrc()->m_dataArray; - Q_ASSERT(rowIndex >= 0 && rowIndex < dataArray.size()); - return dataArray[rowIndex]; -} - -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); -} - -QBarDataProxyPrivate *QBarDataProxy::dptr() -{ - return static_cast<QBarDataProxyPrivate *>(d_ptr.data()); -} - -const QBarDataProxyPrivate *QBarDataProxy::dptrc() const -{ - return static_cast<const QBarDataProxyPrivate *>(d_ptr.data()); -} - -// QBarDataProxyPrivate - -QBarDataProxyPrivate::QBarDataProxyPrivate(QBarDataProxy *q) - : QAbstractDataProxyPrivate(q, QAbstractDataProxy::DataTypeBar), - m_dataArray(new QBarDataArray) -{ -} - -QBarDataProxyPrivate::~QBarDataProxyPrivate() -{ - clearArray(); -} - -bool QBarDataProxyPrivate::resetArray(QBarDataArray *newArray) -{ - if (!m_dataArray->size() && (!newArray || !newArray->size())) - return false; - - clearArray(); - - if (newArray) - m_dataArray = newArray; - else - m_dataArray = new QBarDataArray; - - return true; -} - -void QBarDataProxyPrivate::setRow(int rowIndex, QBarDataRow *row) -{ - Q_ASSERT(rowIndex >= 0 && rowIndex < m_dataArray->size()); - clearRow(rowIndex); - (*m_dataArray)[rowIndex] = row; -} - -void QBarDataProxyPrivate::setRows(int rowIndex, const QBarDataArray &rows) -{ - QBarDataArray &dataArray = *m_dataArray; - Q_ASSERT(rowIndex >= 0 && (rowIndex + rows.size()) <= dataArray.size()); - for (int i = 0; i < rows.size(); i++) { - 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) -{ - int currentSize = m_dataArray->size(); - m_dataArray->append(row); - return currentSize; -} - -int QBarDataProxyPrivate::addRows(const QBarDataArray &rows) -{ - int currentSize = m_dataArray->size(); - for (int i = 0; i < rows.size(); i++) - m_dataArray->append(rows.at(i)); - return currentSize; -} - -void QBarDataProxyPrivate::insertRow(int rowIndex, QBarDataRow *row) -{ - Q_ASSERT(rowIndex >= 0 && rowIndex <= m_dataArray->size()); - m_dataArray->insert(rowIndex, row); -} - -void QBarDataProxyPrivate::insertRows(int rowIndex, const QBarDataArray &rows) -{ - Q_ASSERT(rowIndex >= 0 && rowIndex <= m_dataArray->size()); - for (int i = 0; i < rows.size(); i++) - m_dataArray->insert(rowIndex++, rows.at(i)); -} - -void QBarDataProxyPrivate::removeRows(int rowIndex, int removeCount) -{ - Q_ASSERT(rowIndex >= 0); - int maxRemoveCount = m_dataArray->size() - rowIndex; - removeCount = qMin(removeCount, maxRemoveCount); - for (int i = 0; i < removeCount; i++) { - clearRow(rowIndex); - m_dataArray->removeAt(rowIndex); - } -} - -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; -} - -QPair<GLfloat, GLfloat> QBarDataProxyPrivate::limitValues(int startRow, int endRow, int startColumn, int endColumn) -{ - 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_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/data/qitemmodelbardatamapping.cpp b/src/datavis3d/data/qitemmodelbardatamapping.cpp deleted file mode 100644 index 0aecb082..00000000 --- a/src/datavis3d/data/qitemmodelbardatamapping.cpp +++ /dev/null @@ -1,156 +0,0 @@ -/**************************************************************************** -** -** 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 QtDataVis3D 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_DATAVIS3D_BEGIN_NAMESPACE - -QItemModelBarDataMapping::QItemModelBarDataMapping() - : QObject(0), - d_ptr(new QItemModelBarDataMappingPrivate(this)) -{ -} - -QItemModelBarDataMapping::QItemModelBarDataMapping(const QItemModelBarDataMapping &other) - : QObject(0), - d_ptr(new QItemModelBarDataMappingPrivate(this)) -{ - operator=(other); -} - -QItemModelBarDataMapping::QItemModelBarDataMapping(const QString &valueRole) - : QObject(0), - d_ptr(new QItemModelBarDataMappingPrivate(this)) -{ - d_ptr->m_valueRole = valueRole; -} - -QItemModelBarDataMapping::QItemModelBarDataMapping(const QString &rowRole, - const QString &columnRole, - const QString &valueRole, - const QStringList &rowCategories, - const QStringList &columnCategories) - : QObject(0), - d_ptr(new QItemModelBarDataMappingPrivate(this)) -{ - d_ptr->m_rowRole = rowRole; - d_ptr->m_columnRole = columnRole; - d_ptr->m_valueRole = valueRole; - d_ptr->m_rowCategories = rowCategories; - d_ptr->m_columnCategories = columnCategories; -} - -QItemModelBarDataMapping::~QItemModelBarDataMapping() -{ -} - -QItemModelBarDataMapping &QItemModelBarDataMapping::operator=(const QItemModelBarDataMapping &other) -{ - d_ptr->m_rowRole = other.d_ptr->m_rowRole; - d_ptr->m_columnRole = other.d_ptr->m_columnRole; - d_ptr->m_valueRole = other.d_ptr->m_valueRole; - d_ptr->m_rowCategories = other.d_ptr->m_rowCategories; - d_ptr->m_columnCategories = other.d_ptr->m_columnCategories; - - return *this; -} - -void QItemModelBarDataMapping::setRowRole(const QString &role) -{ - d_ptr->m_rowRole = role; - emit mappingChanged(); -} - -QString QItemModelBarDataMapping::rowRole() const -{ - return d_ptr->m_rowRole; -} - -void QItemModelBarDataMapping::setColumnRole(const QString &role) -{ - d_ptr->m_columnRole = role; - emit mappingChanged(); -} - -QString QItemModelBarDataMapping::columnRole() const -{ - return d_ptr->m_columnRole; -} - -void QItemModelBarDataMapping::setValueRole(const QString &role) -{ - d_ptr->m_valueRole = role; - emit mappingChanged(); -} - -QString QItemModelBarDataMapping::valueRole() const -{ - return d_ptr->m_valueRole; -} - -void QItemModelBarDataMapping::setRowCategories(const QStringList &categories) -{ - d_ptr->m_rowCategories = categories; - emit mappingChanged(); -} - -const QStringList &QItemModelBarDataMapping::rowCategories() const -{ - return d_ptr->m_rowCategories; -} - -void QItemModelBarDataMapping::setColumnCategories(const QStringList &categories) -{ - d_ptr->m_columnCategories = categories; - emit mappingChanged(); -} - -const QStringList &QItemModelBarDataMapping::columnCategories() const -{ - return d_ptr->m_columnCategories; -} - -void QItemModelBarDataMapping::remap(const QString &rowRole, - const QString &columnRole, - const QString &valueRole, - const QStringList &rowCategories, - const QStringList &columnCategories) -{ - d_ptr->m_rowRole = rowRole; - d_ptr->m_columnRole = columnRole; - d_ptr->m_valueRole = valueRole; - d_ptr->m_rowCategories = rowCategories; - d_ptr->m_columnCategories = columnCategories; - - emit mappingChanged(); -} - -// QItemModelBarDataMappingPrivate - -QItemModelBarDataMappingPrivate::QItemModelBarDataMappingPrivate(QItemModelBarDataMapping *q) - : QObject(0), - q_ptr(q) -{ -} - -QItemModelBarDataMappingPrivate::~QItemModelBarDataMappingPrivate() -{ -} - -QT_DATAVIS3D_END_NAMESPACE - diff --git a/src/datavis3d/data/qitemmodelbardataproxy.cpp b/src/datavis3d/data/qitemmodelbardataproxy.cpp deleted file mode 100644 index 4b3ed020..00000000 --- a/src/datavis3d/data/qitemmodelbardataproxy.cpp +++ /dev/null @@ -1,290 +0,0 @@ -/**************************************************************************** -** -** 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 QtDataVis3D 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 <QTimer> - -QT_DATAVIS3D_BEGIN_NAMESPACE - -QItemModelBarDataProxy::QItemModelBarDataProxy() : - QBarDataProxy(new QItemModelBarDataProxyPrivate(this)) -{ -} - -QItemModelBarDataProxy::QItemModelBarDataProxy(QAbstractItemModel *itemModel, - QItemModelBarDataMapping *mapping) : - QBarDataProxy(new QItemModelBarDataProxyPrivate(this)) -{ - dptr()->setItemModel(itemModel); - dptr()->setMapping(mapping); -} - -QItemModelBarDataProxy::~QItemModelBarDataProxy() -{ -} - -void QItemModelBarDataProxy::setItemModel(QAbstractItemModel *itemModel) -{ - dptr()->setItemModel(itemModel); -} - -QAbstractItemModel *QItemModelBarDataProxy::itemModel() -{ - return dptr()->m_itemModel.data(); -} - -void QItemModelBarDataProxy::setMapping(QItemModelBarDataMapping *mapping) -{ - dptr()->setMapping(mapping); -} - -QItemModelBarDataMapping *QItemModelBarDataProxy::mapping() -{ - return dptr()->m_mapping.data(); -} - -QItemModelBarDataProxyPrivate *QItemModelBarDataProxy::dptr() -{ - return static_cast<QItemModelBarDataProxyPrivate *>(d_ptr.data()); -} - -// QItemModelBarDataProxyPrivate - -QItemModelBarDataProxyPrivate::QItemModelBarDataProxyPrivate(QItemModelBarDataProxy *q) - : QBarDataProxyPrivate(q), - resolvePending(0) -{ - m_resolveTimer.setSingleShot(true); - QObject::connect(&m_resolveTimer, &QTimer::timeout, this, &QItemModelBarDataProxyPrivate::handlePendingResolve); -} - -QItemModelBarDataProxyPrivate::~QItemModelBarDataProxyPrivate() -{ -} - -void QItemModelBarDataProxyPrivate::setItemModel(QAbstractItemModel *itemModel) -{ - if (!m_itemModel.isNull()) - QObject::disconnect(m_itemModel, 0, this, 0); - - m_itemModel = itemModel; - - if (!m_itemModel.isNull()) { - QObject::connect(m_itemModel, &QAbstractItemModel::columnsInserted, this, &QItemModelBarDataProxyPrivate::handleColumnsInserted); - QObject::connect(m_itemModel, &QAbstractItemModel::columnsMoved, this, &QItemModelBarDataProxyPrivate::handleColumnsMoved); - QObject::connect(m_itemModel, &QAbstractItemModel::columnsRemoved, this, &QItemModelBarDataProxyPrivate::handleColumnsRemoved); - QObject::connect(m_itemModel, &QAbstractItemModel::dataChanged, this, &QItemModelBarDataProxyPrivate::handleDataChanged); - QObject::connect(m_itemModel, &QAbstractItemModel::layoutChanged, this, &QItemModelBarDataProxyPrivate::handleLayoutChanged); - QObject::connect(m_itemModel, &QAbstractItemModel::modelReset, this, &QItemModelBarDataProxyPrivate::handleModelReset); - QObject::connect(m_itemModel, &QAbstractItemModel::rowsInserted, this, &QItemModelBarDataProxyPrivate::handleRowsInserted); - QObject::connect(m_itemModel, &QAbstractItemModel::rowsMoved, this, &QItemModelBarDataProxyPrivate::handleRowsMoved); - QObject::connect(m_itemModel, &QAbstractItemModel::rowsRemoved, this, &QItemModelBarDataProxyPrivate::handleRowsRemoved); - } - if (!m_resolveTimer.isActive()) - m_resolveTimer.start(0); -} - -void QItemModelBarDataProxyPrivate::setMapping(QItemModelBarDataMapping *mapping) -{ - if (!m_mapping.isNull()) - QObject::disconnect(m_mapping.data(), &QItemModelBarDataMapping::mappingChanged, this, &QItemModelBarDataProxyPrivate::handleMappingChanged); - - m_mapping = mapping; - - if (!m_mapping.isNull()) - QObject::connect(m_mapping.data(), &QItemModelBarDataMapping::mappingChanged, this, &QItemModelBarDataProxyPrivate::handleMappingChanged); - - if (!m_resolveTimer.isActive()) - m_resolveTimer.start(0); -} - -void QItemModelBarDataProxyPrivate::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 QItemModelBarDataProxyPrivate::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 QItemModelBarDataProxyPrivate::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 QItemModelBarDataProxyPrivate::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 QItemModelBarDataProxyPrivate::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 QItemModelBarDataProxyPrivate::handleModelReset() -{ - // Data cleared, reset array - if (!m_resolveTimer.isActive()) - m_resolveTimer.start(0); // TODO Resolving entire model is inefficient -} - -void QItemModelBarDataProxyPrivate::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 QItemModelBarDataProxyPrivate::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 QItemModelBarDataProxyPrivate::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 QItemModelBarDataProxyPrivate::handleMappingChanged() -{ - if (!m_resolveTimer.isActive()) - m_resolveTimer.start(0); -} - -void QItemModelBarDataProxyPrivate::handlePendingResolve() -{ - resolveModel(); -} - -// Resolve entire item model into QBarDataArray. -void QItemModelBarDataProxyPrivate::resolveModel() -{ - if (m_itemModel.isNull() || m_mapping.isNull()) { - qptr()->resetArray(0); - return; - } - - bool useModelRows(false); - if (!m_mapping->rowCategories().size() || !m_mapping->columnCategories().size()) { - useModelRows = true; - } else if (m_mapping->rowRole().isEmpty() || m_mapping->columnRole().isEmpty()) { - qptr()->resetArray(0); - return; - } - - QBarDataArray *newProxyArray = new QBarDataArray; - QHash<int, QByteArray> roleHash = m_itemModel->roleNames(); - // Default to display role if no mapping - int valueRole = roleHash.key(m_mapping->valueRole().toLatin1(), Qt::DisplayRole); - int rowCount = m_itemModel->rowCount(); - int columnCount = m_itemModel->columnCount(); - - if (useModelRows) { - for (int i = 0; i < rowCount; i++) { - QBarDataRow *newProxyRow = new QBarDataRow(columnCount); - for (int j = 0; j < columnCount; j++) - (*newProxyRow)[j].setValue(m_itemModel->index(i, j).data(valueRole).toReal()); - newProxyArray->append(newProxyRow); - } - } else { - int rowRole = roleHash.key(m_mapping->rowRole().toLatin1()); - int columnRole = roleHash.key(m_mapping->columnRole().toLatin1()); - const QStringList &rowList = m_mapping->rowCategories(); - const QStringList &columnList = m_mapping->columnCategories(); - - // 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); - itemValueMap[index.data(rowRole).toString()][index.data(columnRole).toString()] - = index.data(valueRole).toReal(); - } - } - - // Create new data array from itemValueMap - foreach (QString rowKey, rowList) { - QBarDataRow *newProxyRow = new QBarDataRow(columnList.size()); - for (int i = 0; i < columnList.size(); i++) - (*newProxyRow)[i].setValue(itemValueMap[rowKey][columnList.at(i)]); - newProxyArray->append(newProxyRow); - } - } - qDebug() << __FUNCTION__ << "RowCount:" << newProxyArray->size() << "Column count:" << (newProxyArray->size() ? newProxyArray->at(0)->size() : 0); - - qptr()->resetArray(newProxyArray); -} - -QItemModelBarDataProxy *QItemModelBarDataProxyPrivate::qptr() -{ - return static_cast<QItemModelBarDataProxy *>(q_ptr); -} - -QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/data/qitemmodelbardataproxy.h b/src/datavis3d/data/qitemmodelbardataproxy.h deleted file mode 100644 index 1d60bed6..00000000 --- a/src/datavis3d/data/qitemmodelbardataproxy.h +++ /dev/null @@ -1,59 +0,0 @@ -/**************************************************************************** -** -** 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 QtDataVis3D 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 <QtDataVis3D/qbardataproxy.h> -#include <QtDataVis3D/qitemmodelbardatamapping.h> -#include <QAbstractItemModel> -#include <QStringList> - -QT_DATAVIS3D_BEGIN_NAMESPACE - -class QItemModelBarDataProxyPrivate; - -class QT_DATAVIS3D_EXPORT QItemModelBarDataProxy : public QBarDataProxy -{ - Q_OBJECT - -public: - explicit QItemModelBarDataProxy(); - explicit QItemModelBarDataProxy(QAbstractItemModel *itemModel, QItemModelBarDataMapping *mapping); - virtual ~QItemModelBarDataProxy(); - - // Doesn't gain ownership of the model, but does connect to it to listen for data changes. - void setItemModel(QAbstractItemModel *itemModel); - QAbstractItemModel *itemModel(); - - // Map bars role (row, column, value) to role in model. - // Doesn't gain ownership of mapping, but does connect to it to listen for mapping changes. - // Modifying mapping that is set to proxy will trigger dataset re-resolving. - void setMapping(QItemModelBarDataMapping *mapping); - QItemModelBarDataMapping *mapping(); - -protected: - QItemModelBarDataProxyPrivate *dptr(); - -private: - Q_DISABLE_COPY(QItemModelBarDataProxy) -}; - -QT_DATAVIS3D_END_NAMESPACE - -#endif diff --git a/src/datavis3d/data/qitemmodelbardataproxy_p.h b/src/datavis3d/data/qitemmodelbardataproxy_p.h deleted file mode 100644 index c69b1679..00000000 --- a/src/datavis3d/data/qitemmodelbardataproxy_p.h +++ /dev/null @@ -1,77 +0,0 @@ -/**************************************************************************** -** -** 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 QtDataVis3D 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 QtDataVis3D 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_DATAVIS3D_BEGIN_NAMESPACE - -class QItemModelBarDataProxyPrivate : public QBarDataProxyPrivate -{ - Q_OBJECT -public: - QItemModelBarDataProxyPrivate(QItemModelBarDataProxy *q); - virtual ~QItemModelBarDataProxyPrivate(); - - void setItemModel(QAbstractItemModel *itemModel); - void setMapping(QItemModelBarDataMapping *mapping); - -public slots: - void handleColumnsInserted(const QModelIndex & parent, int start, int end); - void handleColumnsMoved(const QModelIndex & sourceParent, int sourceStart, int sourceEnd, const QModelIndex & destinationParent, int destinationColumn); - void handleColumnsRemoved(const QModelIndex & parent, int start, int end); - void handleDataChanged(const QModelIndex & topLeft, const QModelIndex & bottomRight, const QVector<int> & roles = QVector<int> ()); - void handleLayoutChanged(const QList<QPersistentModelIndex> & parents = QList<QPersistentModelIndex> (), QAbstractItemModel::LayoutChangeHint hint = QAbstractItemModel::NoLayoutChangeHint); - void handleModelReset(); - void handleRowsInserted(const QModelIndex & parent, int start, int end); - void handleRowsMoved(const QModelIndex & sourceParent, int sourceStart, int sourceEnd, const QModelIndex & destinationParent, int destinationRow); - void handleRowsRemoved(const QModelIndex & parent, int start, int end); - - void handleMappingChanged(); - void handlePendingResolve(); - -private: - void resolveModel(); - QItemModelBarDataProxy *qptr(); - - QPointer<QAbstractItemModel> m_itemModel; // Not owned - QPointer<QItemModelBarDataMapping> m_mapping; // Not owned - bool resolvePending; - QTimer m_resolveTimer; - - friend class QItemModelBarDataProxy; -}; - -QT_DATAVIS3D_END_NAMESPACE - -#endif diff --git a/src/datavis3d/data/qitemmodelmapdatamapping.cpp b/src/datavis3d/data/qitemmodelmapdatamapping.cpp deleted file mode 100644 index a59be94b..00000000 --- a/src/datavis3d/data/qitemmodelmapdatamapping.cpp +++ /dev/null @@ -1,130 +0,0 @@ -/**************************************************************************** -** -** 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 QtDataVis3D 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 "qitemmodelmapdatamapping_p.h" - -QT_DATAVIS3D_BEGIN_NAMESPACE - -QItemModelMapDataMapping::QItemModelMapDataMapping() - : QObject(0), - d_ptr(new QItemModelMapDataMappingPrivate(this)) -{ -} - -QItemModelMapDataMapping::QItemModelMapDataMapping(const QItemModelMapDataMapping &other) - : QObject(0), - d_ptr(new QItemModelMapDataMappingPrivate(this)) -{ - operator=(other); -} - -QItemModelMapDataMapping::QItemModelMapDataMapping(const QString &labelRole, const QString &xPosRole, - const QString &yPosRole, const QString &valueRole) - : QObject(0), - d_ptr(new QItemModelMapDataMappingPrivate(this)) -{ - d_ptr->m_labelRole = labelRole; - d_ptr->m_xPosRole = xPosRole; - d_ptr->m_yPosRole = yPosRole; - d_ptr->m_valueRole = valueRole; -} - -QItemModelMapDataMapping::~QItemModelMapDataMapping() -{ -} - -QItemModelMapDataMapping &QItemModelMapDataMapping::operator=(const QItemModelMapDataMapping &other) -{ - d_ptr->m_labelRole = other.d_ptr->m_labelRole; - d_ptr->m_xPosRole = other.d_ptr->m_xPosRole; - d_ptr->m_yPosRole = other.d_ptr->m_yPosRole; - d_ptr->m_valueRole = other.d_ptr->m_valueRole; - - return *this; -} - -void QItemModelMapDataMapping::setLabelRole(const QString &role) -{ - d_ptr->m_labelRole = role; - emit mappingChanged(); -} - -QString QItemModelMapDataMapping::labelRole() const -{ - return d_ptr->m_labelRole; -} - -void QItemModelMapDataMapping::setXPosRole(const QString &role) -{ - d_ptr->m_xPosRole = role; - emit mappingChanged(); -} - -QString QItemModelMapDataMapping::xPosRole() const -{ - return d_ptr->m_xPosRole; -} - -void QItemModelMapDataMapping::setYPosRole(const QString &role) -{ - d_ptr->m_yPosRole = role; - emit mappingChanged(); -} - -QString QItemModelMapDataMapping::yPosRole() const -{ - return d_ptr->m_yPosRole; -} - -void QItemModelMapDataMapping::setValueRole(const QString &role) -{ - d_ptr->m_valueRole = role; - emit mappingChanged(); -} - -QString QItemModelMapDataMapping::valueRole() const -{ - return d_ptr->m_valueRole; -} - - -void QItemModelMapDataMapping::remap(const QString &labelRole, const QString &xPosRole, - const QString &yPosRole, const QString &valueRole) -{ - d_ptr->m_labelRole = labelRole; - d_ptr->m_xPosRole = xPosRole; - d_ptr->m_yPosRole = yPosRole; - d_ptr->m_valueRole = valueRole; - - emit mappingChanged(); -} - -// QItemModelMapDataMappingPrivate - -QItemModelMapDataMappingPrivate::QItemModelMapDataMappingPrivate(QItemModelMapDataMapping *q) - : QObject(0), - q_ptr(q) -{ -} - -QItemModelMapDataMappingPrivate::~QItemModelMapDataMappingPrivate() -{ -} - -QT_DATAVIS3D_END_NAMESPACE - diff --git a/src/datavis3d/data/qitemmodelmapdatamapping.h b/src/datavis3d/data/qitemmodelmapdatamapping.h deleted file mode 100644 index 79080a65..00000000 --- a/src/datavis3d/data/qitemmodelmapdatamapping.h +++ /dev/null @@ -1,66 +0,0 @@ -/**************************************************************************** -** -** 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 QtDataVis3D 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 QITEMMODELMAPDATAMAPPING_H -#define QITEMMODELMAPDATAMAPPING_H - -#include <QtDataVis3D/qdatavis3denums.h> -#include <QStringList> - -QT_DATAVIS3D_BEGIN_NAMESPACE - -class QItemModelMapDataMappingPrivate; - -class QT_DATAVIS3D_EXPORT QItemModelMapDataMapping : public QObject -{ - Q_OBJECT - Q_PROPERTY(QString labelRole READ labelRole WRITE setLabelRole) - Q_PROPERTY(QString xPosRole READ xPosRole WRITE setXPosRole) - Q_PROPERTY(QString yPosRole READ yPosRole WRITE setYPosRole) - Q_PROPERTY(QString valueRole READ valueRole WRITE setValueRole) -public: - explicit QItemModelMapDataMapping(); - QItemModelMapDataMapping(const QItemModelMapDataMapping &other); - QItemModelMapDataMapping(const QString &labelRole, const QString &xPosRole, - const QString &yPosRole, const QString &valueRole); - virtual ~QItemModelMapDataMapping(); - - QItemModelMapDataMapping &operator=(const QItemModelMapDataMapping &other); - - void setLabelRole(const QString &role); - QString labelRole() const; - void setXPosRole(const QString &role); - QString xPosRole() const; - void setYPosRole(const QString &role); - QString yPosRole() const; - void setValueRole(const QString &role); - QString valueRole() const; - - void remap(const QString &labelRole, const QString &xPosRole, - const QString &yPosRole, const QString &valueRole); -signals: - void mappingChanged(); - -private: - QScopedPointer<QItemModelMapDataMappingPrivate> d_ptr; -}; - - -QT_DATAVIS3D_END_NAMESPACE - -#endif diff --git a/src/datavis3d/data/qitemmodelmapdataproxy.cpp b/src/datavis3d/data/qitemmodelmapdataproxy.cpp deleted file mode 100644 index b41384e9..00000000 --- a/src/datavis3d/data/qitemmodelmapdataproxy.cpp +++ /dev/null @@ -1,275 +0,0 @@ -/**************************************************************************** -** -** 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 QtDataVis3D 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 "qitemmodelmapdataproxy_p.h" -#include <QTimer> - -QT_DATAVIS3D_BEGIN_NAMESPACE - -QItemModelMapDataProxy::QItemModelMapDataProxy() : - QMapDataProxy(new QItemModelMapDataProxyPrivate(this)) -{ -} - -QItemModelMapDataProxy::QItemModelMapDataProxy(QAbstractItemModel *itemModel, - QItemModelMapDataMapping *mapping) : - QMapDataProxy(new QItemModelMapDataProxyPrivate(this)) -{ - dptr()->setItemModel(itemModel); - dptr()->setMapping(mapping); -} - -QItemModelMapDataProxy::~QItemModelMapDataProxy() -{ -} - -void QItemModelMapDataProxy::setItemModel(QAbstractItemModel *itemModel) -{ - dptr()->setItemModel(itemModel); -} - -QAbstractItemModel *QItemModelMapDataProxy::itemModel() -{ - return dptr()->m_itemModel.data(); -} - -void QItemModelMapDataProxy::setMapping(QItemModelMapDataMapping *mapping) -{ - dptr()->setMapping(mapping); -} - -QItemModelMapDataMapping *QItemModelMapDataProxy::mapping() -{ - return dptr()->m_mapping.data(); -} - -QItemModelMapDataProxyPrivate *QItemModelMapDataProxy::dptr() -{ - return static_cast<QItemModelMapDataProxyPrivate *>(d_ptr.data()); -} - -// QItemModelMapDataProxyPrivate - -QItemModelMapDataProxyPrivate::QItemModelMapDataProxyPrivate(QItemModelMapDataProxy *q) - : QMapDataProxyPrivate(q), - resolvePending(0) -{ - m_resolveTimer.setSingleShot(true); - QObject::connect(&m_resolveTimer, &QTimer::timeout, this, &QItemModelMapDataProxyPrivate::handlePendingResolve); -} - -QItemModelMapDataProxyPrivate::~QItemModelMapDataProxyPrivate() -{ -} - -void QItemModelMapDataProxyPrivate::setItemModel(QAbstractItemModel *itemModel) -{ - if (!m_itemModel.isNull()) - QObject::disconnect(m_itemModel, 0, this, 0); - - m_itemModel = itemModel; - - if (!m_itemModel.isNull()) { - QObject::connect(m_itemModel, &QAbstractItemModel::columnsInserted, this, &QItemModelMapDataProxyPrivate::handleColumnsInserted); - QObject::connect(m_itemModel, &QAbstractItemModel::columnsMoved, this, &QItemModelMapDataProxyPrivate::handleColumnsMoved); - QObject::connect(m_itemModel, &QAbstractItemModel::columnsRemoved, this, &QItemModelMapDataProxyPrivate::handleColumnsRemoved); - QObject::connect(m_itemModel, &QAbstractItemModel::dataChanged, this, &QItemModelMapDataProxyPrivate::handleDataChanged); - QObject::connect(m_itemModel, &QAbstractItemModel::layoutChanged, this, &QItemModelMapDataProxyPrivate::handleLayoutChanged); - QObject::connect(m_itemModel, &QAbstractItemModel::modelReset, this, &QItemModelMapDataProxyPrivate::handleModelReset); - QObject::connect(m_itemModel, &QAbstractItemModel::rowsInserted, this, &QItemModelMapDataProxyPrivate::handleRowsInserted); - QObject::connect(m_itemModel, &QAbstractItemModel::rowsMoved, this, &QItemModelMapDataProxyPrivate::handleRowsMoved); - QObject::connect(m_itemModel, &QAbstractItemModel::rowsRemoved, this, &QItemModelMapDataProxyPrivate::handleRowsRemoved); - } - if (!m_resolveTimer.isActive()) - m_resolveTimer.start(0); -} - -void QItemModelMapDataProxyPrivate::setMapping(QItemModelMapDataMapping *mapping) -{ - if (!m_mapping.isNull()) - QObject::disconnect(m_mapping.data(), &QItemModelMapDataMapping::mappingChanged, this, &QItemModelMapDataProxyPrivate::handleMappingChanged); - - m_mapping = mapping; - - if (!m_mapping.isNull()) - QObject::connect(m_mapping.data(), &QItemModelMapDataMapping::mappingChanged, this, &QItemModelMapDataProxyPrivate::handleMappingChanged); - - if (!m_resolveTimer.isActive()) - m_resolveTimer.start(0); -} - -void QItemModelMapDataProxyPrivate::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 QItemModelMapDataProxyPrivate::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 QItemModelMapDataProxyPrivate::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 QItemModelMapDataProxyPrivate::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 QItemModelMapDataProxyPrivate::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 QItemModelMapDataProxyPrivate::handleModelReset() -{ - // Data cleared, reset array - if (!m_resolveTimer.isActive()) - m_resolveTimer.start(0); // TODO Resolving entire model is inefficient -} - -void QItemModelMapDataProxyPrivate::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 QItemModelMapDataProxyPrivate::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 QItemModelMapDataProxyPrivate::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 QItemModelMapDataProxyPrivate::handleMappingChanged() -{ - if (!m_resolveTimer.isActive()) - m_resolveTimer.start(0); -} - -void QItemModelMapDataProxyPrivate::handlePendingResolve() -{ - resolveModel(); -} - -// Resolve entire item model into QMapDataArray. -void QItemModelMapDataProxyPrivate::resolveModel() -{ - if (m_itemModel.isNull() || m_mapping.isNull()) { - qptr()->resetArray(0); - return; - } - - static const int noRoleIndex = -1; - - QHash<int, QByteArray> roleHash = m_itemModel->roleNames(); - const int labelRole = roleHash.key(m_mapping->labelRole().toLatin1(), noRoleIndex); - const int xPosRole = roleHash.key(m_mapping->xPosRole().toLatin1(), noRoleIndex); - const int yPosRole = roleHash.key(m_mapping->yPosRole().toLatin1(), noRoleIndex); - // Default valueRole to display role if no mapping - const int valueRole = roleHash.key(m_mapping->valueRole().toLatin1(), Qt::DisplayRole); - const int columnCount = m_itemModel->columnCount(); - const int rowCount = m_itemModel->rowCount(); - const int totalCount = rowCount * columnCount; - int runningCount = 0; - - // Parse data into newProxyArray - QMapDataArray *newProxyArray = new QMapDataArray(totalCount); - for (int i = 0; i < rowCount; i++) { - for (int j = 0; j < columnCount; j++) { - QModelIndex index = m_itemModel->index(i, j); - if (labelRole != noRoleIndex) - (*newProxyArray)[runningCount].setLabel(index.data(labelRole).toString()); - qreal xPos(qreal(0.0)); - qreal yPos(qreal(0.0)); - if (xPosRole != noRoleIndex) - xPos = index.data(xPosRole).toReal(); - if (yPosRole != noRoleIndex) - yPos = index.data(yPosRole).toReal(); - (*newProxyArray)[runningCount].setMapPosition(QPointF(xPos, yPos)); - (*newProxyArray)[runningCount].setValue(index.data(valueRole).toReal()); - runningCount++; - } - } - - qDebug() << __FUNCTION__ << "Total count:" << newProxyArray->size(); - - qptr()->resetArray(newProxyArray); -} - -QItemModelMapDataProxy *QItemModelMapDataProxyPrivate::qptr() -{ - return static_cast<QItemModelMapDataProxy *>(q_ptr); -} - -QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/data/qitemmodelmapdataproxy.h b/src/datavis3d/data/qitemmodelmapdataproxy.h deleted file mode 100644 index 784ee162..00000000 --- a/src/datavis3d/data/qitemmodelmapdataproxy.h +++ /dev/null @@ -1,59 +0,0 @@ -/**************************************************************************** -** -** 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 QtDataVis3D 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 QITEMMODELMAPDATAPROXY_H -#define QITEMMODELMAPDATAPROXY_H - -#include <QtDataVis3D/qmapdataproxy.h> -#include <QtDataVis3D/qitemmodelmapdatamapping.h> -#include <QAbstractItemModel> -#include <QStringList> - -QT_DATAVIS3D_BEGIN_NAMESPACE - -class QItemModelMapDataProxyPrivate; - -class QT_DATAVIS3D_EXPORT QItemModelMapDataProxy : public QMapDataProxy -{ - Q_OBJECT - -public: - explicit QItemModelMapDataProxy(); - explicit QItemModelMapDataProxy(QAbstractItemModel *itemModel, QItemModelMapDataMapping *mapping); - virtual ~QItemModelMapDataProxy(); - - // Doesn't gain ownership of the model, but does connect to it to listen for data changes. - void setItemModel(QAbstractItemModel *itemModel); - QAbstractItemModel *itemModel(); - - // Map maps role (label, xPos, yPos, value) to role in model - // Doesn't gain ownership of mapping, but does connect to it to listen for mapping changes. - // Modifying mapping that is set to proxy will trigger dataset re-resolving. - void setMapping(QItemModelMapDataMapping *mapping); - QItemModelMapDataMapping *mapping(); - -protected: - QItemModelMapDataProxyPrivate *dptr(); - -private: - Q_DISABLE_COPY(QItemModelMapDataProxy) -}; - -QT_DATAVIS3D_END_NAMESPACE - -#endif diff --git a/src/datavis3d/data/qitemmodelmapdataproxy_p.h b/src/datavis3d/data/qitemmodelmapdataproxy_p.h deleted file mode 100644 index 64b16c7f..00000000 --- a/src/datavis3d/data/qitemmodelmapdataproxy_p.h +++ /dev/null @@ -1,81 +0,0 @@ -/**************************************************************************** -** -** 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 QtDataVis3D 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 QtDataVis3D 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 QITEMMODELMAPDATAPROXY_P_H -#define QITEMMODELMAPDATAPROXY_P_H - -#include "qitemmodelmapdataproxy.h" -#include "qMapDataProxy_p.h" -#include <QPointer> -#include <QTimer> - -QT_DATAVIS3D_BEGIN_NAMESPACE - -class QItemModelMapDataProxyPrivate : public QMapDataProxyPrivate -{ - Q_OBJECT -public: - QItemModelMapDataProxyPrivate(QItemModelMapDataProxy *q); - virtual ~QItemModelMapDataProxyPrivate(); - - void setItemModel(QAbstractItemModel *itemModel); - void setMapping(QItemModelMapDataMapping *mapping); - -public slots: - void handleColumnsInserted(const QModelIndex &parent, int start, int end); - void handleColumnsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, - const QModelIndex &destinationParent, int destinationColumn); - void handleColumnsRemoved(const QModelIndex &parent, int start, int end); - void handleDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, - const QVector<int> &roles = QVector<int> ()); - void handleLayoutChanged(const QList<QPersistentModelIndex> &parents = QList<QPersistentModelIndex> (), - QAbstractItemModel::LayoutChangeHint hint = QAbstractItemModel::NoLayoutChangeHint); - void handleModelReset(); - void handleRowsInserted(const QModelIndex &parent, int start, int end); - void handleRowsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, - const QModelIndex &destinationParent, int destinationRow); - void handleRowsRemoved(const QModelIndex &parent, int start, int end); - - void handleMappingChanged(); - void handlePendingResolve(); - -private: - void resolveModel(); - QItemModelMapDataProxy *qptr(); - - QPointer<QAbstractItemModel> m_itemModel; // Not owned - QPointer<QItemModelMapDataMapping> m_mapping; // Not owned - bool resolvePending; - QTimer m_resolveTimer; - - friend class QItemModelMapDataProxy; -}; - -QT_DATAVIS3D_END_NAMESPACE - -#endif diff --git a/src/datavis3d/data/qitemmodelscatterdatamapping.cpp b/src/datavis3d/data/qitemmodelscatterdatamapping.cpp deleted file mode 100644 index 0b430b79..00000000 --- a/src/datavis3d/data/qitemmodelscatterdatamapping.cpp +++ /dev/null @@ -1,154 +0,0 @@ -/**************************************************************************** -** -** 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 QtDataVis3D 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_DATAVIS3D_BEGIN_NAMESPACE - -QItemModelScatterDataMapping::QItemModelScatterDataMapping() - : QObject(0), - d_ptr(new QItemModelScatterDataMappingPrivate(this)) -{ -} - -QItemModelScatterDataMapping::QItemModelScatterDataMapping( - const QItemModelScatterDataMapping &other) - : QObject(0), - d_ptr(new QItemModelScatterDataMappingPrivate(this)) -{ - operator=(other); -} - -QItemModelScatterDataMapping::QItemModelScatterDataMapping(const QString &labelRole, - const QString &xPosRole, - const QString &yPosRole, - const QString &zPosRole, - const QString &valueRole) - : QObject(0), - d_ptr(new QItemModelScatterDataMappingPrivate(this)) -{ - Q_UNUSED(labelRole); - Q_UNUSED(valueRole); - //d_ptr->m_labelRole = labelRole; - d_ptr->m_xPosRole = xPosRole; - d_ptr->m_yPosRole = yPosRole; - d_ptr->m_zPosRole = zPosRole; - //d_ptr->m_valueRole = valueRole; -} - -QItemModelScatterDataMapping::~QItemModelScatterDataMapping() -{ -} - -QItemModelScatterDataMapping &QItemModelScatterDataMapping::operator=( - const QItemModelScatterDataMapping &other) -{ - //d_ptr->m_labelRole = other.d_ptr->m_labelRole; - d_ptr->m_xPosRole = other.d_ptr->m_xPosRole; - d_ptr->m_yPosRole = other.d_ptr->m_yPosRole; - d_ptr->m_zPosRole = other.d_ptr->m_zPosRole; - //d_ptr->m_valueRole = other.d_ptr->m_valueRole; - - return *this; -} - -//void QItemModelScatterDataMapping::setLabelRole(const QString &role) -//{ -// d_ptr->m_labelRole = role; -// emit mappingChanged(); -//} - -//QString QItemModelScatterDataMapping::labelRole() const -//{ -// return d_ptr->m_labelRole; -//} - -void QItemModelScatterDataMapping::setXPosRole(const QString &role) -{ - d_ptr->m_xPosRole = role; - emit mappingChanged(); -} - -QString QItemModelScatterDataMapping::xPosRole() const -{ - return d_ptr->m_xPosRole; -} - -void QItemModelScatterDataMapping::setYPosRole(const QString &role) -{ - d_ptr->m_yPosRole = role; - emit mappingChanged(); -} - -QString QItemModelScatterDataMapping::yPosRole() const -{ - return d_ptr->m_yPosRole; -} - -void QItemModelScatterDataMapping::setZPosRole(const QString &role) -{ - d_ptr->m_zPosRole = role; - emit mappingChanged(); -} - -QString QItemModelScatterDataMapping::zPosRole() const -{ - return d_ptr->m_zPosRole; -} - -//void QItemModelScatterDataMapping::setValueRole(const QString &role) -//{ -// d_ptr->m_valueRole = role; -// emit mappingChanged(); -//} - -//QString QItemModelScatterDataMapping::valueRole() const -//{ -// return d_ptr->m_valueRole; -//} - -void QItemModelScatterDataMapping::remap(const QString &labelRole, const QString &xPosRole, - const QString &yPosRole, const QString &zPosRole, - const QString &valueRole) -{ - Q_UNUSED(labelRole); - Q_UNUSED(valueRole); - //d_ptr->m_labelRole = labelRole; - d_ptr->m_xPosRole = xPosRole; - d_ptr->m_yPosRole = yPosRole; - d_ptr->m_zPosRole = zPosRole; - //d_ptr->m_valueRole = valueRole; - - emit mappingChanged(); -} - -// QItemModelScatterDataMappingPrivate - -QItemModelScatterDataMappingPrivate::QItemModelScatterDataMappingPrivate( - QItemModelScatterDataMapping *q) - : QObject(0), - q_ptr(q) -{ -} - -QItemModelScatterDataMappingPrivate::~QItemModelScatterDataMappingPrivate() -{ -} - -QT_DATAVIS3D_END_NAMESPACE - diff --git a/src/datavis3d/data/qitemmodelscatterdataproxy.cpp b/src/datavis3d/data/qitemmodelscatterdataproxy.cpp deleted file mode 100644 index c4f4f0a7..00000000 --- a/src/datavis3d/data/qitemmodelscatterdataproxy.cpp +++ /dev/null @@ -1,305 +0,0 @@ -/**************************************************************************** -** -** 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 QtDataVis3D 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 <QTimer> - -QT_DATAVIS3D_BEGIN_NAMESPACE - -QItemModelScatterDataProxy::QItemModelScatterDataProxy() : - QScatterDataProxy(new QItemModelScatterDataProxyPrivate(this)) -{ -} - -QItemModelScatterDataProxy::QItemModelScatterDataProxy(QAbstractItemModel *itemModel, - QItemModelScatterDataMapping *mapping) : - QScatterDataProxy(new QItemModelScatterDataProxyPrivate(this)) -{ - dptr()->setItemModel(itemModel); - dptr()->setMapping(mapping); -} - -QItemModelScatterDataProxy::~QItemModelScatterDataProxy() -{ -} - -void QItemModelScatterDataProxy::setItemModel(QAbstractItemModel *itemModel) -{ - dptr()->setItemModel(itemModel); -} - -QAbstractItemModel *QItemModelScatterDataProxy::itemModel() -{ - return dptr()->m_itemModel.data(); -} - -void QItemModelScatterDataProxy::setMapping(QItemModelScatterDataMapping *mapping) -{ - dptr()->setMapping(mapping); -} - -QItemModelScatterDataMapping *QItemModelScatterDataProxy::mapping() -{ - return dptr()->m_mapping.data(); -} - -QItemModelScatterDataProxyPrivate *QItemModelScatterDataProxy::dptr() -{ - return static_cast<QItemModelScatterDataProxyPrivate *>(d_ptr.data()); -} - -// QItemModelScatterDataProxyPrivate - -QItemModelScatterDataProxyPrivate::QItemModelScatterDataProxyPrivate(QItemModelScatterDataProxy *q) - : QScatterDataProxyPrivate(q), - resolvePending(0) -{ - m_resolveTimer.setSingleShot(true); - QObject::connect(&m_resolveTimer, &QTimer::timeout, this, - &QItemModelScatterDataProxyPrivate::handlePendingResolve); -} - -QItemModelScatterDataProxyPrivate::~QItemModelScatterDataProxyPrivate() -{ -} - -void QItemModelScatterDataProxyPrivate::setItemModel(QAbstractItemModel *itemModel) -{ - if (!m_itemModel.isNull()) - QObject::disconnect(m_itemModel, 0, this, 0); - - m_itemModel = itemModel; - - if (!m_itemModel.isNull()) { - QObject::connect(m_itemModel, &QAbstractItemModel::columnsInserted, this, - &QItemModelScatterDataProxyPrivate::handleColumnsInserted); - QObject::connect(m_itemModel, &QAbstractItemModel::columnsMoved, this, - &QItemModelScatterDataProxyPrivate::handleColumnsMoved); - QObject::connect(m_itemModel, &QAbstractItemModel::columnsRemoved, this, - &QItemModelScatterDataProxyPrivate::handleColumnsRemoved); - QObject::connect(m_itemModel, &QAbstractItemModel::dataChanged, this, - &QItemModelScatterDataProxyPrivate::handleDataChanged); - QObject::connect(m_itemModel, &QAbstractItemModel::layoutChanged, this, - &QItemModelScatterDataProxyPrivate::handleLayoutChanged); - QObject::connect(m_itemModel, &QAbstractItemModel::modelReset, this, - &QItemModelScatterDataProxyPrivate::handleModelReset); - QObject::connect(m_itemModel, &QAbstractItemModel::rowsInserted, this, - &QItemModelScatterDataProxyPrivate::handleRowsInserted); - QObject::connect(m_itemModel, &QAbstractItemModel::rowsMoved, this, - &QItemModelScatterDataProxyPrivate::handleRowsMoved); - QObject::connect(m_itemModel, &QAbstractItemModel::rowsRemoved, this, - &QItemModelScatterDataProxyPrivate::handleRowsRemoved); - } - if (!m_resolveTimer.isActive()) - m_resolveTimer.start(0); -} - -void QItemModelScatterDataProxyPrivate::setMapping(QItemModelScatterDataMapping *mapping) -{ - if (!m_mapping.isNull()) - QObject::disconnect(m_mapping.data(), &QItemModelScatterDataMapping::mappingChanged, this, - &QItemModelScatterDataProxyPrivate::handleMappingChanged); - - m_mapping = mapping; - - if (!m_mapping.isNull()) - QObject::connect(m_mapping.data(), &QItemModelScatterDataMapping::mappingChanged, this, - &QItemModelScatterDataProxyPrivate::handleMappingChanged); - - if (!m_resolveTimer.isActive()) - m_resolveTimer.start(0); -} - -void QItemModelScatterDataProxyPrivate::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 QItemModelScatterDataProxyPrivate::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 QItemModelScatterDataProxyPrivate::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 QItemModelScatterDataProxyPrivate::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 QItemModelScatterDataProxyPrivate::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 QItemModelScatterDataProxyPrivate::handleModelReset() -{ - // Data cleared, reset array - if (!m_resolveTimer.isActive()) - m_resolveTimer.start(0); // TODO Resolving entire model is inefficient -} - -void QItemModelScatterDataProxyPrivate::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 QItemModelScatterDataProxyPrivate::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 QItemModelScatterDataProxyPrivate::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 QItemModelScatterDataProxyPrivate::handleMappingChanged() -{ - if (!m_resolveTimer.isActive()) - m_resolveTimer.start(0); -} - -void QItemModelScatterDataProxyPrivate::handlePendingResolve() -{ - resolveModel(); -} - -// Resolve entire item model into QScatterDataArray. -void QItemModelScatterDataProxyPrivate::resolveModel() -{ - if (m_itemModel.isNull() || m_mapping.isNull()) { - qptr()->resetArray(0); - return; - } - - static const int noRoleIndex = -1; - - QHash<int, QByteArray> roleHash = m_itemModel->roleNames(); - //const int labelRole = roleHash.key(m_mapping->labelRole().toLatin1(), noRoleIndex); - const int xPosRole = roleHash.key(m_mapping->xPosRole().toLatin1(), noRoleIndex); - const int yPosRole = roleHash.key(m_mapping->yPosRole().toLatin1(), noRoleIndex); - const int zPosRole = roleHash.key(m_mapping->zPosRole().toLatin1(), noRoleIndex); - // Default valueRole to display role if no mapping - //const int valueRole = roleHash.key(m_mapping->valueRole().toLatin1(), Qt::DisplayRole); - const int columnCount = m_itemModel->columnCount(); - const int rowCount = m_itemModel->rowCount(); - const int totalCount = rowCount * columnCount; - int runningCount = 0; - - // Parse data into newProxyArray - QScatterDataArray *newProxyArray = new QScatterDataArray(totalCount); - for (int i = 0; i < rowCount; i++) { - for (int j = 0; j < columnCount; j++) { - QModelIndex index = m_itemModel->index(i, j); - //if (labelRole != noRoleIndex) - // (*newProxyArray)[runningCount].setLabel(index.data(labelRole).toString()); - 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(); - (*newProxyArray)[runningCount].setPosition(QVector3D(xPos, yPos, zPos)); - //(*newProxyArray)[runningCount].setValue(index.data(valueRole).toReal()); - runningCount++; - } - } - - qDebug() << __FUNCTION__ << "Total count:" << newProxyArray->size(); - - qptr()->resetArray(newProxyArray); -} - -QItemModelScatterDataProxy *QItemModelScatterDataProxyPrivate::qptr() -{ - return static_cast<QItemModelScatterDataProxy *>(q_ptr); -} - -QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/data/qitemmodelscatterdataproxy_p.h b/src/datavis3d/data/qitemmodelscatterdataproxy_p.h deleted file mode 100644 index aed3d974..00000000 --- a/src/datavis3d/data/qitemmodelscatterdataproxy_p.h +++ /dev/null @@ -1,81 +0,0 @@ -/**************************************************************************** -** -** 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 QtDataVis3D 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 QtDataVis3D 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_DATAVIS3D_BEGIN_NAMESPACE - -class QItemModelScatterDataProxyPrivate : public QScatterDataProxyPrivate -{ - Q_OBJECT -public: - QItemModelScatterDataProxyPrivate(QItemModelScatterDataProxy *q); - virtual ~QItemModelScatterDataProxyPrivate(); - - void setItemModel(QAbstractItemModel *itemModel); - void setMapping(QItemModelScatterDataMapping *mapping); - -public slots: - void handleColumnsInserted(const QModelIndex &parent, int start, int end); - void handleColumnsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, - const QModelIndex &destinationParent, int destinationColumn); - void handleColumnsRemoved(const QModelIndex &parent, int start, int end); - void handleDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, - const QVector<int> &roles = QVector<int> ()); - void handleLayoutChanged(const QList<QPersistentModelIndex> &parents = QList<QPersistentModelIndex> (), - QAbstractItemModel::LayoutChangeHint hint = QAbstractItemModel::NoLayoutChangeHint); - void handleModelReset(); - void handleRowsInserted(const QModelIndex &parent, int start, int end); - void handleRowsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, - const QModelIndex &destinationParent, int destinationRow); - void handleRowsRemoved(const QModelIndex &parent, int start, int end); - - void handleMappingChanged(); - void handlePendingResolve(); - -private: - void resolveModel(); - QItemModelScatterDataProxy *qptr(); - - QPointer<QAbstractItemModel> m_itemModel; // Not owned - QPointer<QItemModelScatterDataMapping> m_mapping; // Not owned - bool resolvePending; - QTimer m_resolveTimer; - - friend class QItemModelScatterDataProxy; -}; - -QT_DATAVIS3D_END_NAMESPACE - -#endif diff --git a/src/datavis3d/data/qmapdataitem.cpp b/src/datavis3d/data/qmapdataitem.cpp deleted file mode 100644 index 2fe9b6e8..00000000 --- a/src/datavis3d/data/qmapdataitem.cpp +++ /dev/null @@ -1,100 +0,0 @@ -/**************************************************************************** -** -** 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 QtDataVis3D 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 "qmapdataitem_p.h" - -QT_DATAVIS3D_BEGIN_NAMESPACE - -/*! - * \class QMapDataItem - * \inmodule QtDataVis3D - * \brief The QMapDataItem class provides a container for resolved data to be added to maps graphs. - * \since 1.0.0 - * - * A QMapDataItem holds data for a single rendered bar in a maps graph. - * Maps data proxies parse data into QMapDataItem instances for visualizing. - * - * \sa QMapDataProxy, {Qt Data Visualization 3D C++ Classes} - */ - -/*! - * Constructs QMapDataItem. - */ -QMapDataItem::QMapDataItem() - : QBarDataItem() -{ -} - -QMapDataItem::QMapDataItem(const QMapDataItem &other) - : QBarDataItem(other) -{ - operator=(other); -} - -/*! - * Destroys QMapDataItem. - */ -QMapDataItem::~QMapDataItem() -{ -} - -QMapDataItem &QMapDataItem::operator=(const QMapDataItem &other) -{ - QBarDataItem::operator =(other); - m_mapPosition = other.m_mapPosition; - m_label = other.m_label; - - return *this; -} - -void QMapDataItem::setMapPosition(const QPointF &position) -{ - m_mapPosition = position; -} - -QPointF QMapDataItem::mapPosition() const -{ - return m_mapPosition; -} - -void QMapDataItem::setLabel(const QString &label) -{ - m_label = label; -} - -QString QMapDataItem::label() const -{ - return m_label; -} - -void QMapDataItem::createExtraData() -{ - if (!d_ptr) - d_ptr = new QMapDataItemPrivate; -} - -QMapDataItemPrivate::QMapDataItemPrivate() - : QBarDataItemPrivate() -{ -} - -QMapDataItemPrivate::~QMapDataItemPrivate() -{ -} - -QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/data/qmapdataitem.h b/src/datavis3d/data/qmapdataitem.h deleted file mode 100644 index 240b03dd..00000000 --- a/src/datavis3d/data/qmapdataitem.h +++ /dev/null @@ -1,57 +0,0 @@ -/**************************************************************************** -** -** 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 QtDataVis3D 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 QMAPDATAITEM_H -#define QMAPDATAITEM_H - -#include <QtDataVis3D/qdatavis3denums.h> -#include <QtDataVis3D/qbardataitem.h> -#include <QPointF> - -QT_DATAVIS3D_BEGIN_NAMESPACE - -class QMapDataItemPrivate; - -class QT_DATAVIS3D_EXPORT QMapDataItem : public QBarDataItem -{ -public: - QMapDataItem(); - QMapDataItem(const QMapDataItem &other); - ~QMapDataItem(); - - QMapDataItem &operator=(const QMapDataItem &other); - - void setMapPosition(const QPointF &position); - QPointF mapPosition() const; - - void setLabel(const QString &label); - QString label() const; - -protected: - virtual void createExtraData(); - - QMapDataItemPrivate *d_ptr; - -private: - QPointF m_mapPosition; - QString m_label; -}; - -QT_DATAVIS3D_END_NAMESPACE - -#endif diff --git a/src/datavis3d/data/qmapdataproxy.cpp b/src/datavis3d/data/qmapdataproxy.cpp deleted file mode 100644 index a7a0e9d5..00000000 --- a/src/datavis3d/data/qmapdataproxy.cpp +++ /dev/null @@ -1,111 +0,0 @@ -/**************************************************************************** -** -** 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 QtDataVis3D 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 "qmapdataproxy.h" -#include "qmapdataproxy_p.h" - -QT_DATAVIS3D_BEGIN_NAMESPACE - -QMapDataProxy::QMapDataProxy() : - QAbstractDataProxy(new QMapDataProxyPrivate(this)) -{ -} - -QMapDataProxy::QMapDataProxy(QMapDataProxyPrivate *d) : - QAbstractDataProxy(d) -{ -} - -QMapDataProxy::~QMapDataProxy() -{ -} - -void QMapDataProxy::resetArray(QMapDataArray *newArray) -{ - if (dptr()->resetArray(newArray)) - emit arrayReset(); -} - - -int QMapDataProxy::itemCount() const -{ - return dptrc()->m_dataArray.size(); -} - -const QMapDataArray *QMapDataProxy::array() const -{ - return &dptrc()->m_dataArray; -} - -const QMapDataItem *QMapDataProxy::itemAt(int index) const -{ - return &dptrc()->m_dataArray.at(index); -} - -QMapDataProxyPrivate *QMapDataProxy::dptr() -{ - return static_cast<QMapDataProxyPrivate *>(d_ptr.data()); -} - -const QMapDataProxyPrivate *QMapDataProxy::dptrc() const -{ - return static_cast<const QMapDataProxyPrivate *>(d_ptr.data()); -} - -// QBarDataProxyPrivate - -QMapDataProxyPrivate::QMapDataProxyPrivate(QMapDataProxy *q) - : QAbstractDataProxyPrivate(q, QAbstractDataProxy::DataTypeMap) -{ -} - -QMapDataProxyPrivate::~QMapDataProxyPrivate() -{ - m_dataArray.clear(); -} - -bool QMapDataProxyPrivate::resetArray(QMapDataArray *newArray) -{ - if (!m_dataArray.size() && (!newArray || !newArray->size())) - return false; - - m_dataArray.clear(); - - if (newArray) { - m_dataArray = *newArray; - delete newArray; - } - - return true; -} - -QPair<GLfloat, GLfloat> QMapDataProxyPrivate::limitValues() -{ - QPair<GLfloat, GLfloat> limits = qMakePair(0.0f, 0.0f); - for (int i = 0; i < m_dataArray.size(); i++) { - const QMapDataItem &item = m_dataArray.at(i); - qreal itemValue = item.value(); - if (limits.second < itemValue) - limits.second = itemValue; - if (limits.first > itemValue) - limits.first = itemValue; - } - return limits; -} - -QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/data/qmapdataproxy.h b/src/datavis3d/data/qmapdataproxy.h deleted file mode 100644 index 45bb95d5..00000000 --- a/src/datavis3d/data/qmapdataproxy.h +++ /dev/null @@ -1,88 +0,0 @@ -/**************************************************************************** -** -** 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 QtDataVis3D 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 QMAPDATAPROXY_H -#define QMAPDATAPROXY_H - -#include <QtDataVis3D/qabstractdataproxy.h> -#include <QtDataVis3D/qmapdataitem.h> - -QT_DATAVIS3D_BEGIN_NAMESPACE - -typedef QVector<QMapDataItem> QMapDataArray; - -class QMapDataProxyPrivate; - -class QT_DATAVIS3D_EXPORT QMapDataProxy : public QAbstractDataProxy -{ - Q_OBJECT - -public: - explicit QMapDataProxy(); - explicit QMapDataProxy(QMapDataProxyPrivate *d); - virtual ~QMapDataProxy(); - - // QMapDataProxy is also optimized to use cases where the only defining characteristics of an individual - // map item are it's value and position. Modifying other data such as color or mesh of individual bar - // requires allocating additional data object for the bar. - - // Item pointers are guaranteed to be valid only until next call that modifies data. - // Array pointer is guaranteed to be valid for lifetime of proxy. - int itemCount() const; - const QMapDataArray *array() const; - const QMapDataItem *itemAt(int index) const; // Index needs to exist or this crashes - - // TODO Should data manipulation/access methods be protected rather than public to enforce subclassing use of proxy? - // TODO Leaving them public gives user more options. - - // QMapDataProxy takes ownership of all QMapDataArrays and QMapDataItems passed to it. - - // Clears the existing array and sets it data to new array. - void resetArray(QMapDataArray *newArray); - - // TODO void setItem(int index, QMapDataItem *item); - // TODO void setItems(int index, QMapDataArray *items); - - // TODO int addItem(QMapDataItem *item); // returns the index of added item - // TODO int addItems(QMapDataArray *items); // returns the index of added item - - // TODO void insertItem(int index, QMapDataItem *item); - // TODO void insertItems(int index, QMapDataArray *items); - - // TODO 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); // Index may be over current array size if removed from end - void itemsInserted(int startIndex, int count); - -protected: - QMapDataProxyPrivate *dptr(); - const QMapDataProxyPrivate *dptrc() const; - -private: - Q_DISABLE_COPY(QMapDataProxy) - - friend class Maps3DController; -}; - -QT_DATAVIS3D_END_NAMESPACE - -#endif diff --git a/src/datavis3d/data/qscatterdataproxy.cpp b/src/datavis3d/data/qscatterdataproxy.cpp deleted file mode 100644 index d2f544ef..00000000 --- a/src/datavis3d/data/qscatterdataproxy.cpp +++ /dev/null @@ -1,210 +0,0 @@ -/**************************************************************************** -** -** 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 QtDataVis3D 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_DATAVIS3D_BEGIN_NAMESPACE - -QScatterDataProxy::QScatterDataProxy() : - QAbstractDataProxy(new QScatterDataProxyPrivate(this)) -{ -} - -QScatterDataProxy::QScatterDataProxy(QScatterDataProxyPrivate *d) : - QAbstractDataProxy(d) -{ -} - -QScatterDataProxy::~QScatterDataProxy() -{ -} - -void QScatterDataProxy::resetArray(QScatterDataArray *newArray) -{ - if (dptr()->resetArray(newArray)) - emit arrayReset(); -} - -void QScatterDataProxy::setItem(int index, const QScatterDataItem &item) -{ - dptr()->setItem(index, item); - emit itemsChanged(index, 1); -} - -void QScatterDataProxy::setItems(int index, const QScatterDataArray &items) -{ - dptr()->setItems(index, items); - emit itemsChanged(index, items.size()); -} - -int QScatterDataProxy::addItem(const QScatterDataItem &item) -{ - int addIndex = dptr()->addItem(item); - emit itemsAdded(addIndex, 1); - return addIndex; -} - -int QScatterDataProxy::addItems(const QScatterDataArray &items) -{ - int addIndex = dptr()->addItems(items); - emit itemsAdded(addIndex, items.size()); - return addIndex; -} - -void QScatterDataProxy::insertItem(int index, const QScatterDataItem &item) -{ - dptr()->insertItem(index, item); - emit itemsInserted(index, 1); -} - -void QScatterDataProxy::insertItems(int index, const QScatterDataArray &items) -{ - dptr()->insertItems(index, items); - emit itemsInserted(index, items.size()); -} - -void QScatterDataProxy::removeItems(int index, int removeCount) -{ - dptr()->removeItems(index, removeCount); - emit itemsRemoved(index, removeCount); -} - -int QScatterDataProxy::itemCount() const -{ - return dptrc()->m_dataArray->size(); -} - -const QScatterDataArray *QScatterDataProxy::array() const -{ - return dptrc()->m_dataArray; -} - -const QScatterDataItem *QScatterDataProxy::itemAt(int index) const -{ - return &dptrc()->m_dataArray->at(index); -} - -QScatterDataProxyPrivate *QScatterDataProxy::dptr() -{ - return static_cast<QScatterDataProxyPrivate *>(d_ptr.data()); -} - -const QScatterDataProxyPrivate *QScatterDataProxy::dptrc() const -{ - return static_cast<const QScatterDataProxyPrivate *>(d_ptr.data()); -} - -// QScatterDataProxyPrivate - -QScatterDataProxyPrivate::QScatterDataProxyPrivate(QScatterDataProxy *q) - : QAbstractDataProxyPrivate(q, QAbstractDataProxy::DataTypeScatter), - m_dataArray(new QScatterDataArray) -{ -} - -QScatterDataProxyPrivate::~QScatterDataProxyPrivate() -{ - m_dataArray->clear(); - delete m_dataArray; -} - -bool QScatterDataProxyPrivate::resetArray(QScatterDataArray *newArray) -{ - if (!m_dataArray->size() && (!newArray || !newArray->size())) - return false; - - m_dataArray->clear(); - delete m_dataArray; - - if (newArray) - m_dataArray = newArray; - else - m_dataArray = new QScatterDataArray; - - return true; -} - -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); - } - //qDebug() << __FUNCTION__ << limits << m_dataArray.size(); - return limits; -} - -QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/data/scatterrenderitem.cpp b/src/datavis3d/data/scatterrenderitem.cpp deleted file mode 100644 index 15281c0a..00000000 --- a/src/datavis3d/data/scatterrenderitem.cpp +++ /dev/null @@ -1,51 +0,0 @@ -/**************************************************************************** -** -** 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 QtDataVis3D 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_DATAVIS3D_BEGIN_NAMESPACE - -ScatterRenderItem::ScatterRenderItem() - : BarRenderItem() -{ -} - -ScatterRenderItem::~ScatterRenderItem() -{ -} - -void ScatterRenderItem::formatLabel() -{ - // TODO The label format specified in proxy should probably have additional custom formatting - // TODO specifiers in addition to standard printf specifiers for placement of item labels - // TODO and selection data (like row/column in bar selection) - - // Format the string on first access - QString numStr; - numStr.setNum(m_value); - // TODO actually format instead of just prepending the value - m_label.clear(); // Just in case - //m_label.append(m_itemLabel); - //m_label.append(QStringLiteral(" ")); - m_label.append(numStr); - m_label.append(m_renderer->itemLabelFormat()); -} - -QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/datavis3d.pro b/src/datavis3d/datavis3d.pro deleted file mode 100644 index fa548c22..00000000 --- a/src/datavis3d/datavis3d.pro +++ /dev/null @@ -1,24 +0,0 @@ -TARGET = QtDataVis3D -QT = core gui opengl #qml - -DEFINES += QT_DATAVIS3D_LIBRARY - -QMAKE_DOCS = $$PWD/doc/qtdatavis3d.qdocconf - -load(qt_module) - -include($$PWD/common.pri) -include($$PWD/engine/engine.pri) -include($$PWD/global/global.pri) -include($$PWD/utils/utils.pri) -include($$PWD/axis/axis.pri) -include($$PWD/data/data.pri) - -wince* { - # The Microsoft MIPS compiler crashes if /Og is specified. - # -O2/1 expands to /Og plus additional arguments. - contains(DEFINES, MIPS) { - QMAKE_CXXFLAGS_RELEASE ~= s/-O2/-Oi -Ot -Oy -Ob2/ - QMAKE_CXXFLAGS_RELEASE ~= s/-O1/-Os -Oy -Ob2/ - } -} diff --git a/src/datavis3d/doc/images/q3dbars-minimal.png b/src/datavis3d/doc/images/q3dbars-minimal.png Binary files differdeleted file mode 100644 index 63b77998..00000000 --- a/src/datavis3d/doc/images/q3dbars-minimal.png +++ /dev/null diff --git a/src/datavis3d/doc/qtdatavis3d.qdocconf b/src/datavis3d/doc/qtdatavis3d.qdocconf deleted file mode 100644 index 0e9f6d5b..00000000 --- a/src/datavis3d/doc/qtdatavis3d.qdocconf +++ /dev/null @@ -1,33 +0,0 @@ -include($QT_INSTALL_DOCS/global/qt-module-defaults.qdocconf) - -project = QtDataVis3D -description = Qt Data Visualization 3D Reference Documentation -version = 1.0.0 - -exampledirs += ../../../examples \ - snippets - -headerdirs += .. -imagedirs += ../images \ - images -sourcedirs += .. - -depends += qtcore \ - qtgui - -qhp.projects = qtdatavis3d - -qhp.qtdatavis3d.file = qtdatavis3d.qhp -qhp.qtdatavis3d.namespace = org.qt-project.qtdatavis3d.1.0.0 -qhp.qtdatavis3d.virtualFolder = qtdatavis3d -qhp.qtdatavis3d.indexTitle = Qt Data Visualization 3D -qhp.qtdatavis3d.indexRoot = - -qhp.qtdatavis3d.filterAttributes = qtdatavis3d 1.0.0 qtrefdoc -qhp.qtdatavis3d.customFilters.Qt.name = QtDataVis3D 1.0.0 -qhp.qtdatavis3d.customFilters.Qt.filterAttributes = qtdatavis3d 1.0.0 -qhp.qtdatavis3d.subprojects = classes -qhp.qtdatavis3d.subprojects.classes.title = C++ Classes -qhp.qtdatavis3d.subprojects.classes.indexTitle = Qt Data Visualization 3D C++ Classes -qhp.qtdatavis3d.subprojects.classes.selectors = class fake:headerfile -qhp.qtdatavis3d.subprojects.classes.sortPages = true diff --git a/src/datavis3d/doc/src/qtdatavis3d-index.qdoc b/src/datavis3d/doc/src/qtdatavis3d-index.qdoc deleted file mode 100644 index dae2a14d..00000000 --- a/src/datavis3d/doc/src/qtdatavis3d-index.qdoc +++ /dev/null @@ -1,62 +0,0 @@ -/**************************************************************************** -** -** 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 QtDataVis3D 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 -** -****************************************************************************/ - -/*! - \title Qt Data Visualization 3D - \page qtdatavis3d-index.html - \brief QtDataVis3D module provides functionality for 3D visualization. - - Qt Data Visualization module provides a way to visualize data in 3D. - It uses OpneGL for the data rendering. - - \section1 Getting Started - - Qt Data Visualization provides classes for rendering 3D data. To include - the definitions of the module's classes, use the following directive: - - \snippet doc_src_qtdatavis3d.cpp 0 - - To link against the module, add this line to your \l qmake \c - .pro file: - - \snippet doc_src_qtdatavis3d.pro 0 - - \section1 Articles - \list - \li \l{Qt Data Visualization 3D License Information}{License Information} - \endlist - - \section1 References - \list - \li \l{Qt Data Visualization 3D C++ Classes} - \endlist - - Qt Data Visualization 3D comes with the following examples: - - \list - \li \l{Barchart Example} - \li \l{Mapdata Example} - \li \l{Qt Quick 2 Barchart Example} - \li \l{Qt Quick 2 Maps Example} - \li \l{Qt Quick 2 Scatter Example} - \li \l{Rainfall Example} - \li \l{Scatter Chart Example} - \li \l{Spectrum Example} - \li \l{Widget Example} - \endlist -*/ diff --git a/src/datavis3d/engine/abstract3dcontroller.cpp b/src/datavis3d/engine/abstract3dcontroller.cpp deleted file mode 100644 index 12f76fd1..00000000 --- a/src/datavis3d/engine/abstract3dcontroller.cpp +++ /dev/null @@ -1,698 +0,0 @@ -/**************************************************************************** -** -** 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 QtDataVis3D 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 "abstract3dcontroller_p.h" -#include "camerahelper_p.h" -#include "qabstractaxis_p.h" -#include "qvalueaxis.h" -#include "abstract3drenderer_p.h" - -QT_DATAVIS3D_BEGIN_NAMESPACE - -Abstract3DController::Abstract3DController(QRect boundRect, QObject *parent) : - QObject(parent), - m_boundingRect(boundRect.x(), boundRect.y(), boundRect.width(), boundRect.height()), - m_horizontalRotation(-45.0f), - m_verticalRotation(15.0f), - m_theme(), - m_font(QFont(QStringLiteral("Arial"))), - m_selectionMode(QDataVis::ModeItem), - m_shadowQuality(QDataVis::ShadowLow), - m_labelTransparency(QDataVis::TransparencyFromTheme), - m_isBackgroundEnabled(true), - m_isGridEnabled(true), - m_cameraHelper(new CameraHelper()), - m_zoomLevel(100), - m_axisX(0), - m_axisY(0), - m_axisZ(0), - m_renderer(0), - m_isDataDirty(false) -{ - m_theme.useColorTheme(QDataVis::ThemeSystem); -} - -Abstract3DController::~Abstract3DController() -{ - delete m_cameraHelper; - delete m_axisX; - delete m_axisY; - delete m_axisZ; -} - -void Abstract3DController::setRenderer(Abstract3DRenderer *renderer) -{ - m_renderer = renderer; -} - -void Abstract3DController::synchDataToRenderer() -{ - // If we don't have a renderer, don't do anything - if (!m_renderer) - return; - - if (m_changeTracker.positionChanged) { - m_renderer->updatePosition(m_boundingRect); - m_changeTracker.positionChanged = false; - } - - if (m_changeTracker.zoomLevelChanged) { - m_renderer->updateZoomLevel(m_zoomLevel); - m_changeTracker.zoomLevelChanged = false; - } - - if (m_changeTracker.themeChanged) { - m_renderer->updateTheme(m_theme); - m_changeTracker.themeChanged = false; - } - - if (m_changeTracker.fontChanged) { - m_renderer->updateFont(m_font); - m_changeTracker.fontChanged = false; - } - - if (m_changeTracker.labelTransparencyChanged) { - m_renderer->updateLabelTransparency(m_labelTransparency); - m_changeTracker.labelTransparencyChanged = false; - } - - if (m_changeTracker.boundingRectChanged || m_changeTracker.sizeChanged) { - m_renderer->updateBoundingRect(m_boundingRect); - m_changeTracker.boundingRectChanged = false; - m_changeTracker.sizeChanged = false; - } - - if (m_changeTracker.shadowQualityChanged) { - m_renderer->updateShadowQuality(m_shadowQuality); - m_changeTracker.shadowQualityChanged = false; - } - - if (m_changeTracker.selectionModeChanged) { - m_renderer->updateSelectionMode(m_selectionMode); - m_changeTracker.selectionModeChanged = false; - } - - if (m_changeTracker.objFileChanged) { - m_renderer->updateMeshFileName(m_objFile); - m_changeTracker.objFileChanged = false; - } - - if (m_changeTracker.gridEnabledChanged) { - m_renderer->updateGridEnabled(m_isGridEnabled); - m_changeTracker.gridEnabledChanged = false; - } - - if (m_changeTracker.backgroundEnabledChanged) { - m_renderer->updateBackgroundEnabled(m_isBackgroundEnabled); - m_changeTracker.backgroundEnabledChanged = false; - } - - if (m_changeTracker.axisXTypeChanged) { - m_renderer->updateAxisType(QAbstractAxis::AxisOrientationX, m_axisX->type()); - m_changeTracker.axisXTypeChanged = false; - } - - if (m_changeTracker.axisYTypeChanged) { - m_renderer->updateAxisType(QAbstractAxis::AxisOrientationY, m_axisY->type()); - m_changeTracker.axisYTypeChanged = false; - } - - if (m_changeTracker.axisZTypeChanged) { - m_renderer->updateAxisType(QAbstractAxis::AxisOrientationZ, m_axisZ->type()); - m_changeTracker.axisZTypeChanged = false; - } - - if (m_changeTracker.axisXTitleChanged) { - m_renderer->updateAxisTitle(QAbstractAxis::AxisOrientationX, m_axisX->title()); - m_changeTracker.axisXTitleChanged = false; - } - - if (m_changeTracker.axisYTitleChanged) { - m_renderer->updateAxisTitle(QAbstractAxis::AxisOrientationY, m_axisY->title()); - m_changeTracker.axisYTitleChanged = false; - } - - if (m_changeTracker.axisZTitleChanged) { - m_renderer->updateAxisTitle(QAbstractAxis::AxisOrientationZ, m_axisZ->title()); - m_changeTracker.axisZTitleChanged = false; - } - - if (m_changeTracker.axisXLabelsChanged) { - m_renderer->updateAxisLabels(QAbstractAxis::AxisOrientationX, m_axisX->labels()); - m_changeTracker.axisXLabelsChanged = false; - } - - if (m_changeTracker.axisYLabelsChanged) { - m_renderer->updateAxisLabels(QAbstractAxis::AxisOrientationY, m_axisY->labels()); - m_changeTracker.axisYLabelsChanged = false; - } - if (m_changeTracker.axisZLabelsChanged) { - m_renderer->updateAxisLabels(QAbstractAxis::AxisOrientationZ, m_axisZ->labels()); - m_changeTracker.axisZLabelsChanged = false; - } - - if (m_changeTracker.axisXRangeChanged) { - m_changeTracker.axisXRangeChanged = false; - if (m_axisX->type() & QAbstractAxis::AxisTypeValue) { - QValueAxis *valueAxisX = static_cast<QValueAxis *>(m_axisX); - m_renderer->updateAxisRange(QAbstractAxis::AxisOrientationX, - valueAxisX->min(), valueAxisX->max()); - } - } - - if (m_changeTracker.axisYRangeChanged) { - m_changeTracker.axisYRangeChanged = false; - if (m_axisY->type() & QAbstractAxis::AxisTypeValue) { - QValueAxis *valueAxisY = static_cast<QValueAxis *>(m_axisY); - m_renderer->updateAxisRange(QAbstractAxis::AxisOrientationY, - valueAxisY->min(), valueAxisY->max()); - } - } - - if (m_changeTracker.axisZRangeChanged) { - m_changeTracker.axisZRangeChanged = false; - if (m_axisZ->type() & QAbstractAxis::AxisTypeValue) { - QValueAxis *valueAxisZ = static_cast<QValueAxis *>(m_axisZ); - m_renderer->updateAxisRange(QAbstractAxis::AxisOrientationZ, - valueAxisZ->min(), valueAxisZ->max()); - } - } - - if (m_changeTracker.axisXSegmentCountChanged) { - m_changeTracker.axisXSegmentCountChanged = false; - if (m_axisX->type() & QAbstractAxis::AxisTypeValue) { - QValueAxis *valueAxisX = static_cast<QValueAxis *>(m_axisX); - m_renderer->updateAxisSegmentCount(QAbstractAxis::AxisOrientationX, - valueAxisX->segmentCount()); - } - } - - if (m_changeTracker.axisYSegmentCountChanged) { - m_changeTracker.axisYSegmentCountChanged = false; - if (m_axisY->type() & QAbstractAxis::AxisTypeValue) { - QValueAxis *valueAxisY = static_cast<QValueAxis *>(m_axisY); - m_renderer->updateAxisSegmentCount(QAbstractAxis::AxisOrientationY, - valueAxisY->segmentCount()); - } - } - - if (m_changeTracker.axisZSegmentCountChanged) { - m_changeTracker.axisZSegmentCountChanged = false; - if (m_axisZ->type() & QAbstractAxis::AxisTypeValue) { - QValueAxis *valueAxisZ = static_cast<QValueAxis *>(m_axisZ); - m_renderer->updateAxisSegmentCount(QAbstractAxis::AxisOrientationZ, - valueAxisZ->segmentCount()); - } - } - - if (m_changeTracker.axisXSubSegmentCountChanged) { - m_changeTracker.axisXSubSegmentCountChanged = false; - if (m_axisX->type() & QAbstractAxis::AxisTypeValue) { - QValueAxis *valueAxisX = static_cast<QValueAxis *>(m_axisX); - m_renderer->updateAxisSubSegmentCount(QAbstractAxis::AxisOrientationX, - valueAxisX->subSegmentCount()); - } - } - - if (m_changeTracker.axisYSubSegmentCountChanged) { - m_changeTracker.axisYSubSegmentCountChanged = false; - if (m_axisY->type() & QAbstractAxis::AxisTypeValue) { - QValueAxis *valueAxisY = static_cast<QValueAxis *>(m_axisY); - m_renderer->updateAxisSubSegmentCount(QAbstractAxis::AxisOrientationY, - valueAxisY->subSegmentCount()); - } - } - - if (m_changeTracker.axisZSubSegmentCountChanged) { - m_changeTracker.axisZSubSegmentCountChanged = false; - if (m_axisZ->type() & QAbstractAxis::AxisTypeValue) { - QValueAxis *valueAxisZ = static_cast<QValueAxis *>(m_axisZ); - m_renderer->updateAxisSubSegmentCount(QAbstractAxis::AxisOrientationZ, - valueAxisZ->subSegmentCount()); - } - } -} - -void Abstract3DController::render(const GLuint defaultFboHandle) -{ - // If not initialized, do nothing. - if (!m_renderer) - return; - - m_renderer->render(m_cameraHelper, defaultFboHandle); -} - -void Abstract3DController::setSize(const int width, const int height) -{ - m_boundingRect.setWidth(width); - m_boundingRect.setHeight(height); - - m_changeTracker.boundingRectChanged = true; - emit boundingRectChanged(m_boundingRect); -} - -const QSize Abstract3DController::size() -{ - return m_boundingRect.size(); -} - -const QRect Abstract3DController::boundingRect() -{ - return m_boundingRect; -} - -void Abstract3DController::setBoundingRect(const QRect boundingRect) -{ - m_boundingRect = boundingRect; - - m_changeTracker.boundingRectChanged = true; - emit boundingRectChanged(m_boundingRect); -} - -void Abstract3DController::setWidth(const int width) -{ - m_boundingRect.setWidth(width); - - m_changeTracker.sizeChanged = true; - emit sizeChanged(m_boundingRect); -} - -int Abstract3DController::width() -{ - return m_boundingRect.width(); -} - -void Abstract3DController::setHeight(const int height) -{ - m_boundingRect.setHeight(height); - - m_changeTracker.sizeChanged = true; - emit sizeChanged(m_boundingRect); -} - -int Abstract3DController::height() -{ - return m_boundingRect.height(); -} - -void Abstract3DController::setX(const int x) -{ - m_boundingRect.setX(x); - - m_changeTracker.positionChanged = true; - emit positionChanged(m_boundingRect); -} - -int Abstract3DController::x() -{ - return m_boundingRect.x(); -} - -void Abstract3DController::setY(const int y) -{ - m_boundingRect.setY(y); - - m_changeTracker.positionChanged = true; - emit positionChanged(m_boundingRect); -} - -int Abstract3DController::y() -{ - return m_boundingRect.y(); -} - -void Abstract3DController::setAxisX(QAbstractAxis *axis) -{ - setAxisHelper(QAbstractAxis::AxisOrientationX, axis, &m_axisX); -} - -QAbstractAxis *Abstract3DController::axisX() -{ - return m_axisX; -} - -void Abstract3DController::setAxisY(QAbstractAxis *axis) -{ - setAxisHelper(QAbstractAxis::AxisOrientationY, axis, &m_axisY); -} - -QAbstractAxis *Abstract3DController::axisY() -{ - return m_axisY; -} - -void Abstract3DController::setAxisZ(QAbstractAxis *axis) -{ - setAxisHelper(QAbstractAxis::AxisOrientationZ, axis, &m_axisZ); -} - -QAbstractAxis *Abstract3DController::axisZ() -{ - return m_axisZ; -} - -int Abstract3DController::zoomLevel() -{ - return m_zoomLevel; -} - -void Abstract3DController::setZoomLevel(int zoomLevel) -{ - m_zoomLevel = zoomLevel; - - m_changeTracker.zoomLevelChanged = true; - emit zoomLevelChanged(zoomLevel); -} - -void Abstract3DController::setCameraPreset(QDataVis::CameraPreset preset) -{ - m_cameraHelper->setCameraPreset(preset); -} - -void Abstract3DController::setCameraPosition(GLfloat horizontal, GLfloat vertical, GLint distance) -{ - m_horizontalRotation = qBound(-180.0f, horizontal, 180.0f); - m_verticalRotation = qBound(0.0f, vertical, 90.0f); - m_zoomLevel = qBound(10, distance, 500); - m_cameraHelper->setCameraRotation(QPointF(m_horizontalRotation, - m_verticalRotation)); - //qDebug() << "camera rotation set to" << m_horizontalRotation << m_verticalRotation; -} - -void Abstract3DController::setObjectColor(QColor baseColor, QColor heightColor, QColor depthColor, - bool uniform) -{ - m_theme.m_baseColor = baseColor; - m_theme.m_heightColor = heightColor; - m_theme.m_depthColor = depthColor; - m_theme.m_uniformColor = uniform; - - m_changeTracker.themeChanged = true; - emit themeChanged(m_theme); -} - -void Abstract3DController::setColorTheme(QDataVis::ColorTheme colorTheme) -{ - m_theme.useColorTheme(colorTheme); - - m_changeTracker.themeChanged = true; - emit themeChanged(m_theme); -} - -Theme Abstract3DController::theme() -{ - return m_theme; -} - -void Abstract3DController::setFontSize(float fontsize) -{ - m_font.setPointSizeF(fontsize); - - m_changeTracker.fontChanged = true; - emit fontChanged(m_font); -} - -float Abstract3DController::fontSize() -{ - return m_font.pointSizeF(); -} - -void Abstract3DController::setFont(const QFont &font) -{ - m_font = font; - - m_changeTracker.fontChanged = true; - emit fontChanged(m_font); -} - -QFont Abstract3DController::font() -{ - return m_font; -} - -void Abstract3DController::setSelectionMode(QDataVis::SelectionMode mode) -{ - m_selectionMode = mode; - m_changeTracker.selectionModeChanged = true; - emit selectionModeChanged(m_selectionMode); -} - -QDataVis::SelectionMode Abstract3DController::selectionMode() -{ - return m_selectionMode; -} - -void Abstract3DController::setShadowQuality(QDataVis::ShadowQuality quality) -{ - m_shadowQuality = quality; - - m_changeTracker.shadowQualityChanged = true; - emit shadowQualityChanged(m_shadowQuality); -} - -QDataVis::ShadowQuality Abstract3DController::shadowQuality() -{ - return m_shadowQuality; -} - -void Abstract3DController::setLabelTransparency(QDataVis::LabelTransparency transparency) -{ - m_labelTransparency = transparency; - - m_changeTracker.labelTransparencyChanged = true; - emit labelTransparencyChanged(m_labelTransparency); -} - -QDataVis::LabelTransparency Abstract3DController::labelTransparency() -{ - return m_labelTransparency; -} - -void Abstract3DController::setBackgroundEnabled(bool enable) -{ - m_isBackgroundEnabled = enable; - m_changeTracker.backgroundEnabledChanged = true; - emit backgroundEnabledChanged(m_isBackgroundEnabled); -} - -bool Abstract3DController::backgroundEnabled() -{ - return m_isBackgroundEnabled; -} - -void Abstract3DController::setGridEnabled(bool enable) -{ - m_isGridEnabled = enable; - m_changeTracker.gridEnabledChanged = true; - emit gridEnabledChanged(m_isGridEnabled); -} - -bool Abstract3DController::gridEnabled() -{ - return m_isGridEnabled; -} - -void Abstract3DController::setMeshFileName(const QString &fileName) -{ - m_objFile = fileName; - m_changeTracker.objFileChanged = true; - emit meshFileNameChanged(m_objFile); -} - -QString Abstract3DController::meshFileName() -{ - return m_objFile; -} - -void Abstract3DController::handleAxisTitleChanged(const QString &title) -{ - handleAxisTitleChangedBySender(sender(), title); -} - -void Abstract3DController::handleAxisTitleChangedBySender(QObject *sender, const QString &title) -{ - if (sender == m_axisX) { - m_changeTracker.axisXTitleChanged = true; - emit axisTitleChanged(QAbstractAxis::AxisOrientationX, title); - } else if (sender == m_axisY) { - m_changeTracker.axisYTitleChanged = true; - emit axisTitleChanged(QAbstractAxis::AxisOrientationY, title); - } else if (sender == m_axisZ) { - m_changeTracker.axisZTitleChanged = true; - emit axisTitleChanged(QAbstractAxis::AxisOrientationZ, title); - } else { - qWarning() << __FUNCTION__ << "invoked for invalid axis"; - } -} - -void Abstract3DController::handleAxisLabelsChanged() -{ - handleAxisLabelsChangedBySender(sender()); -} - -void Abstract3DController::handleAxisLabelsChangedBySender(QObject *sender) -{ - if (sender == m_axisX) { - m_changeTracker.axisXLabelsChanged = true; - emit axisLabelsChanged(QAbstractAxis::AxisOrientationX, m_axisX->labels()); - } else if (sender == m_axisY) { - m_changeTracker.axisYLabelsChanged = true; - emit axisLabelsChanged(QAbstractAxis::AxisOrientationY, m_axisY->labels()); - } else if (sender == m_axisZ) { - m_changeTracker.axisZLabelsChanged = true; - emit axisLabelsChanged(QAbstractAxis::AxisOrientationZ, m_axisZ->labels()); - } else { - qWarning() << __FUNCTION__ << "invoked for invalid axis"; - } -} - -void Abstract3DController::handleAxisRangeChanged(qreal min, qreal max) -{ - handleAxisRangeChangedBySender(sender(), min, max); -} - -void Abstract3DController::handleAxisRangeChangedBySender(QObject *sender, qreal min, qreal max) -{ - if (sender == m_axisX) { - m_isDataDirty = true; - m_changeTracker.axisXRangeChanged = true; - emit axisRangeChanged(QAbstractAxis::AxisOrientationX, min, max); - } else if (sender == m_axisY) { - m_isDataDirty = true; - m_changeTracker.axisYRangeChanged = true; - emit axisRangeChanged(QAbstractAxis::AxisOrientationY, min, max); - } else if (sender == m_axisZ) { - m_isDataDirty = true; - - m_changeTracker.axisZRangeChanged = true; - emit axisRangeChanged(QAbstractAxis::AxisOrientationZ, min, max); - } else { - qWarning() << __FUNCTION__ << "invoked for invalid axis"; - } -} - -void Abstract3DController::handleAxisSegmentCountChanged(int count) -{ - handleAxisSegmentCountChangedBySender(sender(), count); -} - -void Abstract3DController::handleAxisSegmentCountChangedBySender(QObject *sender, int count) -{ - if (sender == m_axisX) { - m_changeTracker.axisXSegmentCountChanged = true; - emit axisSegmentCountChanged(QAbstractAxis::AxisOrientationX, count); - } else if (sender == m_axisY) { - m_changeTracker.axisYSegmentCountChanged = true; - emit axisSegmentCountChanged(QAbstractAxis::AxisOrientationY, count); - } else if (sender == m_axisZ) { - m_changeTracker.axisZSegmentCountChanged = true; - emit axisSegmentCountChanged(QAbstractAxis::AxisOrientationZ, count); - } else { - qWarning() << __FUNCTION__ << "invoked for invalid axis"; - } -} - -void Abstract3DController::handleAxisSubSegmentCountChanged(int count) -{ - handleAxisSubSegmentCountChangedBySender(sender(), count); -} - -void Abstract3DController::handleAxisSubSegmentCountChangedBySender(QObject *sender, int count) -{ - if (sender == m_axisX) { - m_changeTracker.axisXSubSegmentCountChanged = true; - emit axisSubSegmentCountChanged(QAbstractAxis::AxisOrientationX, count); - } else if (sender == m_axisY) { - m_changeTracker.axisYSubSegmentCountChanged = true; - emit axisSubSegmentCountChanged(QAbstractAxis::AxisOrientationY, count); - } else if (sender == m_axisZ) { - m_changeTracker.axisZSubSegmentCountChanged = true; - emit axisSubSegmentCountChanged(QAbstractAxis::AxisOrientationZ, count); - } else { - qWarning() << __FUNCTION__ << "invoked for invalid axis"; - } -} - -void Abstract3DController::handleAxisAutoAdjustRangeChanged(bool autoAdjust) -{ - QObject *sender = QObject::sender(); - if (sender != m_axisX && sender != m_axisY && sender != m_axisZ) - return; - - QAbstractAxis *axis = static_cast<QAbstractAxis*>(sender); - handleAxisAutoAdjustRangeChangedInOrientation(axis->orientation(), autoAdjust); -} - -void Abstract3DController::setAxisHelper(QAbstractAxis::AxisOrientation orientation, - QAbstractAxis *axis, QAbstractAxis **axisPtr) -{ - Q_ASSERT(axis); - - delete *axisPtr; - *axisPtr = axis; - - axis->setParent(0); // Assume ownership - axis->d_ptr->setOrientation(orientation); - - - QObject::connect(axis, &QAbstractAxis::titleChanged, - this, &Abstract3DController::handleAxisTitleChanged); - QObject::connect(axis, &QAbstractAxis::labelsChanged, - this, &Abstract3DController::handleAxisLabelsChanged); - - - if (orientation == QAbstractAxis::AxisOrientationX) - m_changeTracker.axisXTypeChanged = true; - else if (orientation == QAbstractAxis::AxisOrientationY) - m_changeTracker.axisYTypeChanged = true; - else if (orientation == QAbstractAxis::AxisOrientationZ) - m_changeTracker.axisZTypeChanged = true; - emit axisTypeChanged(orientation, axis->type()); - - handleAxisTitleChangedBySender(axis, axis->title()); - emit axisTitleChanged(orientation, axis->title()); - - handleAxisLabelsChangedBySender(axis); - emit axisLabelsChanged(orientation, axis->labels()); - - if (axis->type() & QAbstractAxis::AxisTypeValue) { - QValueAxis *valueAxis = static_cast<QValueAxis *>(axis); - QObject::connect(valueAxis, &QValueAxis::rangeChanged, - this, &Abstract3DController::handleAxisRangeChanged); - QObject::connect(valueAxis, &QValueAxis::segmentCountChanged, - this, &Abstract3DController::handleAxisSegmentCountChanged); - QObject::connect(valueAxis, &QValueAxis::subSegmentCountChanged, - this, &Abstract3DController::handleAxisSubSegmentCountChanged); - QObject::connect(valueAxis, &QValueAxis::autoAdjustRangeChanged, - this, &Abstract3DController::handleAxisAutoAdjustRangeChanged); - - handleAxisRangeChangedBySender(valueAxis, valueAxis->min(), valueAxis->max()); - emit axisRangeChanged(orientation, valueAxis->min(), valueAxis->max()); - - handleAxisSegmentCountChangedBySender(valueAxis, valueAxis->segmentCount()); - emit axisSegmentCountChanged(orientation, valueAxis->segmentCount()); - - handleAxisSubSegmentCountChangedBySender(valueAxis, valueAxis->subSegmentCount()); - emit axisSubSegmentCountChanged(orientation, valueAxis->subSegmentCount()); - - handleAxisAutoAdjustRangeChangedInOrientation(valueAxis->orientation(), - valueAxis->isAutoAdjustRange()); - } -} - -QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/engine/abstract3drenderer.cpp b/src/datavis3d/engine/abstract3drenderer.cpp deleted file mode 100644 index b25e5a15..00000000 --- a/src/datavis3d/engine/abstract3drenderer.cpp +++ /dev/null @@ -1,219 +0,0 @@ -/**************************************************************************** -** -** 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 QtDataVis3D 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 "abstract3drenderer_p.h" -#include "qvalueaxis.h" - -QT_DATAVIS3D_BEGIN_NAMESPACE - -Abstract3DRenderer::Abstract3DRenderer(Abstract3DController *controller) - : QObject(controller), - m_controller(controller), - m_isInitialized(false), - m_hasNegativeValues(false), - m_drawer(new Drawer(m_cachedTheme, m_cachedFont, m_cachedLabelTransparency)), - m_autoScaleAdjustment(1.0f), - m_cachedZoomLevel(100) - -{ - QObject::connect(m_drawer, &Drawer::drawerChanged, this, &Abstract3DRenderer::updateTextures); -} - -void Abstract3DRenderer::initializeOpenGL() -{ - axisCacheForOrientation(QAbstractAxis::AxisOrientationX).setDrawer(m_drawer); - axisCacheForOrientation(QAbstractAxis::AxisOrientationY).setDrawer(m_drawer); - axisCacheForOrientation(QAbstractAxis::AxisOrientationZ).setDrawer(m_drawer); -} - -void Abstract3DRenderer::updateDataModel(QAbstractDataProxy *dataProxy) -{ - m_cachedItemLabelFormat = dataProxy->itemLabelFormat(); -} - -QString Abstract3DRenderer::itemLabelFormat() const -{ - return m_cachedItemLabelFormat; -} - -void Abstract3DRenderer::updateBoundingRect(const QRect boundingRect) -{ - m_cachedBoundingRect = boundingRect; - handleResize(); -} - -void Abstract3DRenderer::updatePosition(const QRect boundingRect) -{ - m_cachedBoundingRect = boundingRect; -} - -void Abstract3DRenderer::updateTheme(Theme theme) -{ - m_cachedTheme.setFromTheme(theme); - - m_drawer->setTheme(m_cachedTheme); - // Re-initialize shaders - handleShadowQualityChange(); -} - -void Abstract3DRenderer::handleShadowQualityChange() -{ -#if !defined(QT_OPENGL_ES_2) - if (m_cachedShadowQuality > QDataVis::ShadowNone) { - if (!m_cachedTheme.m_uniformColor) { - initShaders(QStringLiteral(":/shaders/vertexShadow"), - QStringLiteral(":/shaders/fragmentShadowNoTexColorOnY")); - } else { - initShaders(QStringLiteral(":/shaders/vertexShadow"), - QStringLiteral(":/shaders/fragmentShadowNoTex")); - } - initBackgroundShaders(QStringLiteral(":/shaders/vertexShadow"), - QStringLiteral(":/shaders/fragmentShadowNoTex")); - } else { - if (!m_cachedTheme.m_uniformColor) { - initShaders(QStringLiteral(":/shaders/vertex"), - QStringLiteral(":/shaders/fragmentColorOnY")); - } else { - initShaders(QStringLiteral(":/shaders/vertex"), - QStringLiteral(":/shaders/fragment")); - } - initBackgroundShaders(QStringLiteral(":/shaders/vertex"), - QStringLiteral(":/shaders/fragment")); - } -#else - if (!m_cachedTheme.m_uniformColor) { - initShaders(QStringLiteral(":/shaders/vertexES2"), - QStringLiteral(":/shaders/fragmentColorOnYES2")); - } else { - initShaders(QStringLiteral(":/shaders/vertexES2"), - QStringLiteral(":/shaders/fragmentES2")); - } - initBackgroundShaders(QStringLiteral(":/shaders/vertexES2"), - QStringLiteral(":/shaders/fragmentES2")); -#endif -} - -void Abstract3DRenderer::updateFont(const QFont &font) -{ - m_cachedFont = font; - m_drawer->setFont(font); -} - -void Abstract3DRenderer::updateLabelTransparency(QDataVis::LabelTransparency transparency) -{ - m_cachedLabelTransparency = transparency; - m_drawer->setTransparency(transparency); -} - -void Abstract3DRenderer::updateMeshFileName(const QString &objFileName) -{ - m_cachedObjFile = objFileName; -} - -void Abstract3DRenderer::updateSelectionMode(QDataVis::SelectionMode mode) -{ - m_cachedSelectionMode = mode; -} - -void Abstract3DRenderer::updateGridEnabled(bool enable) -{ - m_cachedIsGridEnabled = enable; -} - -void Abstract3DRenderer::updateBackgroundEnabled(bool enable) -{ - m_cachedIsBackgroundEnabled = enable; -} - -void Abstract3DRenderer::handleResize() -{ - if (m_cachedBoundingRect.width() == 0 || m_cachedBoundingRect.height() == 0) - return; - qDebug() << __FUNCTION__ << m_cachedBoundingRect.width() << "x" << m_cachedBoundingRect.height(); - // Calculate zoom level based on aspect ratio - GLfloat div; - GLfloat zoomAdjustment; - div = qMin(m_cachedBoundingRect.width(), m_cachedBoundingRect.height()); - zoomAdjustment = defaultRatio * ((m_cachedBoundingRect.width() / div) - / (m_cachedBoundingRect.height() / div)); - //qDebug() << "zoom adjustment" << zoomAdjustment; - m_autoScaleAdjustment = qMin(zoomAdjustment, 1.0f); // clamp to 1.0f - - // Re-init selection buffer - initSelectionBuffer(); - -#if !defined(QT_OPENGL_ES_2) - // Re-init depth buffer - updateDepthBuffer(); -#endif -} - -void Abstract3DRenderer::updateZoomLevel(int newZoomLevel) -{ - m_cachedZoomLevel = newZoomLevel; -} - -void Abstract3DRenderer::updateAxisType(QAbstractAxis::AxisOrientation orientation, QAbstractAxis::AxisType type) -{ - axisCacheForOrientation(orientation).setType(type); -} - -void Abstract3DRenderer::updateAxisTitle(QAbstractAxis::AxisOrientation orientation, const QString &title) -{ - axisCacheForOrientation(orientation).setTitle(title); -} - -void Abstract3DRenderer::updateAxisLabels(QAbstractAxis::AxisOrientation orientation, const QStringList &labels) -{ - axisCacheForOrientation(orientation).setLabels(labels); -} - -void Abstract3DRenderer::updateAxisRange(QAbstractAxis::AxisOrientation orientation, qreal min, qreal max) -{ - AxisRenderCache &cache = axisCacheForOrientation(orientation); - cache.setMin(min); - cache.setMax(max); -} - -void Abstract3DRenderer::updateAxisSegmentCount(QAbstractAxis::AxisOrientation orientation, int count) -{ - axisCacheForOrientation(orientation).setSegmentCount(count); -} - -void Abstract3DRenderer::updateAxisSubSegmentCount(QAbstractAxis::AxisOrientation orientation, int count) -{ - axisCacheForOrientation(orientation).setSubSegmentCount(count); -} - -AxisRenderCache &Abstract3DRenderer::axisCacheForOrientation(QAbstractAxis::AxisOrientation orientation) -{ - switch (orientation) { - case QAbstractAxis::AxisOrientationX: - return m_axisCacheX; - case QAbstractAxis::AxisOrientationY: - return m_axisCacheY; - case QAbstractAxis::AxisOrientationZ: - return m_axisCacheZ; - default: - qFatal(__FUNCTION__); - return m_axisCacheX; - } -} - - -QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/engine/bars3dcontroller.cpp b/src/datavis3d/engine/bars3dcontroller.cpp deleted file mode 100644 index 86ceff72..00000000 --- a/src/datavis3d/engine/bars3dcontroller.cpp +++ /dev/null @@ -1,459 +0,0 @@ -/**************************************************************************** -** -** 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 QtDataVis3D 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 "bars3dcontroller_p.h" -#include "bars3drenderer_p.h" -#include "camerahelper_p.h" -#include "qabstractaxis_p.h" -#include "qvalueaxis_p.h" -#include "qcategoryaxis.h" -#include "qbardataproxy_p.h" - -#include <QMatrix4x4> -#include <QMouseEvent> -#include <qmath.h> - -QT_DATAVIS3D_BEGIN_NAMESPACE - -Bars3dController::Bars3dController(QRect boundRect) - : Abstract3DController(boundRect), - m_rowCount(0), - m_columnCount(0), - m_mouseState(MouseNone), - m_mousePos(QPoint(0, 0)), - m_isSlicingActivated(false), - m_isBarSpecRelative(true), - m_barThickness(QSizeF(0.75f, 0.75f)), - m_barSpacing(m_barThickness * 3.0f), - m_renderer(0), - m_data(0) -{ - // Default axes - setAxisX(new QCategoryAxis()); - setAxisY(new QValueAxis()); - setAxisZ(new QCategoryAxis()); - - // Default bar type; specific to bars - setBarType(QDataVis::Bars, false); - - setDataProxy(new QBarDataProxy); -} - -Bars3dController::~Bars3dController() -{ - delete m_data; -} - -void Bars3dController::initializeOpenGL() -{ - // Initialization is called multiple times when Qt Quick components are used - if (isInitialized()) - return; - - m_renderer = new Bars3dRenderer(this); - setRenderer(m_renderer); - synchDataToRenderer(); -} - -void Bars3dController::synchDataToRenderer() -{ - Abstract3DController::synchDataToRenderer(); - - if (!isInitialized()) - return; - - // Notify changes to renderer - if (m_changeTracker.slicingActiveChanged) { - m_renderer->updateSlicingActive(m_isSlicingActivated); - m_changeTracker.slicingActiveChanged = false; - } - - if (m_changeTracker.sampleSpaceChanged) { - m_renderer->updateSampleSpace(m_rowCount, m_columnCount); - m_changeTracker.sampleSpaceChanged = false; - } - - if (m_changeTracker.barSpecsChanged) { - m_renderer->updateBarSpecs(m_barThickness, m_barSpacing, m_isBarSpecRelative); - m_changeTracker.barSpecsChanged = false; - } - - if (m_isDataDirty) { - m_renderer->updateDataModel(m_data); - m_isDataDirty = false; - } -} - -QMatrix4x4 Bars3dController::calculateViewMatrix(int zoom, int viewPortWidth, - int viewPortHeight, bool showUnder) -{ - return m_cameraHelper->calculateViewMatrix(m_mousePos, - zoom, - viewPortWidth, - viewPortHeight, - showUnder); -} - -bool Bars3dController::isSlicingActive() -{ - return m_isSlicingActivated; -} - -void Bars3dController::setSlicingActive(bool isSlicing) -{ - m_isSlicingActivated = isSlicing; - - m_changeTracker.slicingActiveChanged = true; - emit slicingActiveChanged(m_isSlicingActivated); -} - -Bars3dController::MouseState Bars3dController::mouseState() -{ - return m_mouseState; -} - - -#if defined(Q_OS_ANDROID) -void Bars3dController::mouseDoubleClickEvent(QMouseEvent *event) -{ - if (!m_isSlicingActivated) { - m_mouseState = Bars3dController::MouseOnScene; - // update mouse positions to prevent jumping when releasing or repressing a button - m_mousePos = event->pos(); - } -} - -void Bars3dController::touchEvent(QTouchEvent *event) -{ - static int prevDistance = 0; - - QList<QTouchEvent::TouchPoint> points; - points = event->touchPoints(); - - if (!m_isSlicingActivated && points.count() == 2) { - m_mouseState = Bars3dController::MouseOnPinch; - - QPointF distance = points.at(0).pos() - points.at(1).pos(); - int newDistance = distance.manhattanLength(); - int zoomRate = 1; - int zoomLevel = m_zoomLevel; - if (zoomLevel > 100) - zoomRate = 5; - if (newDistance > prevDistance) - zoomLevel += zoomRate; - else - zoomLevel -= zoomRate; - if (zoomLevel > 500) - zoomLevel = 500; - else if (zoomLevel < 10) - zoomLevel = 10; - setZoomLevel(zoomLevel); - prevDistance = newDistance; - //qDebug() << "distance" << distance.manhattanLength(); - } -} -#endif - -void Bars3dController::mousePressEvent(QMouseEvent *event, const QPoint &mousePos) -{ - QRect mainViewPort = m_renderer->mainViewPort(); - if (Qt::LeftButton == event->button()) { - if (m_isSlicingActivated) { - if (mousePos.x() <= mainViewPort.width() - && mousePos.y() <= mainViewPort.height()) { - m_mouseState = Bars3dController::MouseOnOverview; - //qDebug() << "Mouse pressed on overview"; - } else { - m_mouseState = Bars3dController::MouseOnZoom; - //qDebug() << "Mouse pressed on zoom"; - } - } else { -#if !defined(Q_OS_ANDROID) - m_mouseState = Bars3dController::MouseOnScene; -#else - m_mouseState = Bars3dController::MouseRotating; -#endif - // update mouse positions to prevent jumping when releasing or repressing a button - m_mousePos = mousePos; - //qDebug() << "Mouse pressed on scene"; - } - } else if (Qt::MiddleButton == event->button()) { - // reset rotations - m_mousePos = QPoint(0, 0); - } else if (!m_isSlicingActivated && Qt::RightButton == event->button()) { - // disable rotating when in slice view -#if !defined(Q_OS_ANDROID) - m_mouseState = Bars3dController::MouseRotating; -#else - m_mouseState = Bars3dController::MouseOnScene; -#endif - // update mouse positions to prevent jumping when releasing or repressing a button - m_mousePos = mousePos; - } - m_cameraHelper->updateMousePos(m_mousePos); -} - -void Bars3dController::mouseReleaseEvent(QMouseEvent *event, const QPoint &mousePos) -{ - Q_UNUSED(event); - if (Bars3dController::MouseRotating == m_mouseState) { - // update mouse positions to prevent jumping when releasing or repressing a button - m_mousePos = mousePos; - m_cameraHelper->updateMousePos(mousePos); - } - m_mouseState = Bars3dController::MouseNone; -} - -void Bars3dController::mouseMoveEvent(QMouseEvent *event, const QPoint &mousePos) -{ - Q_UNUSED(event); - if (Bars3dController::MouseRotating == m_mouseState) - m_mousePos = mousePos; -} - -void Bars3dController::wheelEvent(QWheelEvent *event) -{ - // disable zooming if in slice view - if (m_isSlicingActivated) - return; - - int zoomLevel = m_zoomLevel; - if (zoomLevel > 100) - zoomLevel += event->angleDelta().y() / 12; - else if (zoomLevel > 50) - zoomLevel += event->angleDelta().y() / 60; - else - zoomLevel += event->angleDelta().y() / 120; - if (zoomLevel > 500) - zoomLevel = 500; - else if (zoomLevel < 10) - zoomLevel = 10; - - setZoomLevel(zoomLevel); -} - -void Bars3dController::setDataProxy(QBarDataProxy *proxy) -{ - delete m_data; - m_data = proxy; - - QObject::connect(m_data, &QBarDataProxy::arrayReset, this, - &Bars3dController::handleArrayReset); - QObject::connect(m_data, &QBarDataProxy::rowsAdded, this, - &Bars3dController::handleRowsAdded); - QObject::connect(m_data, &QBarDataProxy::rowsChanged, this, - &Bars3dController::handleRowsChanged); - QObject::connect(m_data, &QBarDataProxy::rowsRemoved, this, - &Bars3dController::handleRowsRemoved); - QObject::connect(m_data, &QBarDataProxy::rowsInserted, this, - &Bars3dController::handleRowsInserted); - QObject::connect(m_data, &QBarDataProxy::itemChanged, this, - &Bars3dController::handleItemChanged); - - adjustValueAxisRange(); - m_isDataDirty = true; -} - -QBarDataProxy *Bars3dController::dataProxy() -{ - return m_data; -} - -void Bars3dController::handleArrayReset() -{ - setSlicingActive(false); - adjustValueAxisRange(); - m_isDataDirty = true; -} - -void Bars3dController::handleRowsAdded(int startIndex, int count) -{ - Q_UNUSED(startIndex) - Q_UNUSED(count) - // TODO check if affects data window - // TODO should update slice instead of deactivating? - setSlicingActive(false); - adjustValueAxisRange(); - m_isDataDirty = true; -} - -void Bars3dController::handleRowsChanged(int startIndex, int count) -{ - Q_UNUSED(startIndex) - Q_UNUSED(count) - // TODO check if affects data window - // TODO should update slice instead of deactivating? - setSlicingActive(false); - adjustValueAxisRange(); - m_isDataDirty = true; -} - -void Bars3dController::handleRowsRemoved(int startIndex, int count) -{ - Q_UNUSED(startIndex) - Q_UNUSED(count) - // TODO check if affects data window - // TODO should update slice instead of deactivating? - setSlicingActive(false); - adjustValueAxisRange(); - m_isDataDirty = true; -} - -void Bars3dController::handleRowsInserted(int startIndex, int count) -{ - Q_UNUSED(startIndex) - Q_UNUSED(count) - // TODO check if affects data window - // TODO should update slice instead of deactivating? - setSlicingActive(false); - adjustValueAxisRange(); - m_isDataDirty = true; -} - -void Bars3dController::handleItemChanged(int rowIndex, int columnIndex) -{ - Q_UNUSED(rowIndex) - Q_UNUSED(columnIndex) - // TODO check if affects data window - // TODO should update slice instead of deactivating? - setSlicingActive(false); - adjustValueAxisRange(); - m_isDataDirty = true; -} - -void Bars3dController::handleAxisAutoAdjustRangeChangedInOrientation(QAbstractAxis::AxisOrientation orientation, bool autoAdjust) -{ - Q_UNUSED(orientation) - Q_UNUSED(autoAdjust) - adjustValueAxisRange(); -} - -void Bars3dController::setBarSpecs(QSizeF thickness, QSizeF spacing, bool relative) -{ - m_barThickness = thickness; - m_barSpacing = spacing; - m_isBarSpecRelative = relative; - - m_changeTracker.barSpecsChanged = true; - emit barSpecsChanged(thickness, spacing, relative); -} - -QSizeF Bars3dController::barThickness() -{ - return m_barThickness; -} - -QSizeF Bars3dController::barSpacing() -{ - return m_barSpacing; -} - -bool Bars3dController::isBarSpecRelative() -{ - return m_isBarSpecRelative; -} - -void Bars3dController::setBarType(QDataVis::MeshStyle style, bool smooth) -{ - QString objFile; - if (style == QDataVis::Bars) { - if (smooth) - objFile = QStringLiteral(":/defaultMeshes/barSmooth"); - else - objFile = QStringLiteral(":/defaultMeshes/bar"); - } else if (style == QDataVis::Pyramids) { - if (smooth) - objFile = QStringLiteral(":/defaultMeshes/pyramidSmooth"); - else - objFile = QStringLiteral(":/defaultMeshes/pyramid"); - } else if (style == QDataVis::Cones) { - if (smooth) - objFile = QStringLiteral(":/defaultMeshes/coneSmooth"); - else - objFile = QStringLiteral(":/defaultMeshes/cone"); - } else if (style == QDataVis::Cylinders) { - if (smooth) - objFile = QStringLiteral(":/defaultMeshes/cylinderSmooth"); - else - objFile = QStringLiteral(":/defaultMeshes/cylinder"); - } else if (style == QDataVis::BevelBars) { - if (smooth) - objFile = QStringLiteral(":/defaultMeshes/bevelbarSmooth"); - else - objFile = QStringLiteral(":/defaultMeshes/bevelbar"); - } - Abstract3DController::setMeshFileName(objFile); -} - -// TODO: This sets data window. Needs more parameters, now assumes window always starts at 0,0. -void Bars3dController::setupSampleSpace(int rowCount, int columnCount) -{ - // Disable zoom mode if we're in it (causes crash if not, as zoom selection is deleted) - setSlicingActive(false); - - m_rowCount = rowCount; - m_columnCount = columnCount; - - adjustValueAxisRange(); - - m_changeTracker.sampleSpaceChanged = true; - emit sampleSpaceChanged(rowCount, columnCount); -} - -void Bars3dController::setSelectionMode(QDataVis::SelectionMode mode) -{ - // Disable zoom if selection mode changes - setSlicingActive(false); - Abstract3DController::setSelectionMode(mode); -} - -QPoint Bars3dController::mousePosition() -{ - return m_mousePos; -} - -int Bars3dController::columnCount() -{ - return m_columnCount; -} - -int Bars3dController::rowCount() -{ - return m_rowCount; -} - -void Bars3dController::adjustValueAxisRange() -{ - QValueAxis *valueAxis = static_cast<QValueAxis *>(m_axisY); - if (valueAxis && valueAxis->isAutoAdjustRange() && m_data) { - QPair<GLfloat, GLfloat> limits = m_data->dptr()->limitValues(0, m_rowCount, - 0, m_columnCount); - if (limits.first < 0) { - // TODO: Currently we only support symmetric y-axis for bar chart if there are negative values - qreal maxAbs = qMax(qFabs(limits.first), qFabs(limits.second)); - // Call private implementation to avoid unsetting auto adjust flag - valueAxis->dptr()->setRange(-maxAbs, maxAbs); - } else if (limits.second == 0.0) { - valueAxis->dptr()->setRange(0.0, 1.0); // Only zero value values in data set, set range to something. - } else { - valueAxis->dptr()->setRange(0.0, limits.second); - } - } -} - -QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/engine/maps3dcontroller.cpp b/src/datavis3d/engine/maps3dcontroller.cpp deleted file mode 100644 index e86bdfa2..00000000 --- a/src/datavis3d/engine/maps3dcontroller.cpp +++ /dev/null @@ -1,1763 +0,0 @@ -/**************************************************************************** -** -** 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 QtDataVis3D 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 "maps3dcontroller_p.h" -#include "maps3drenderer_p.h" -#include "camerahelper_p.h" -#include "shaderhelper_p.h" -#include "objecthelper_p.h" -#include "texturehelper_p.h" -#include "theme_p.h" -#include "utils_p.h" -#include "drawer_p.h" -#include "maprenderitem_p.h" -#include "qmapdataproxy_p.h" - -#include <QOpenGLFunctions> -#include <QMatrix4x4> -#include <QMouseEvent> -#include <qmath.h> - -#include <QDebug> - -//#define DISPLAY_RENDER_SPEED - -// Commenting this draws the shadow map with perspective projection. Otherwise it's drawn in -// orthographic projection. -//#define USE_WIDER_SHADOWS - -// You can verify that depth buffer drawing works correctly by uncommenting this. -// You should see the scene from where the light is -//#define SHOW_DEPTH_TEXTURE_SCENE - -#ifdef DISPLAY_RENDER_SPEED -#include <QTime> -#endif - -QT_DATAVIS3D_BEGIN_NAMESPACE - -//#define DISPLAY_FULL_DATA_ON_SELECTION // Append selection value text with row and column labels - -const GLfloat gridLineWidth = 0.005f; -GLfloat distanceMod = 0.0f; -static QVector3D skipColor = QVector3D(255, 255, 255); // Selection texture's background color - -Maps3DController::Maps3DController(const QRect &rect) - : m_camera(new CameraHelper()), - m_barShader(0), - m_depthShader(0), - m_selectionShader(0), - m_backgroundShader(0), - m_labelShader(0), - m_barObj(0), - m_backgroundObj(0), - m_gridLineObj(0), - m_labelObj(0), - m_objFile(QStringLiteral(":/defaultMeshes/bar")), - m_mousePressed(MouseNone), - m_mousePos(QPoint(0, 0)), - m_zoomLevel(100), - m_autoScaleAdjustment(1.0f), - m_horizontalRotation(0.0f), - m_verticalRotation(45.0f), - m_barThickness(QVector3D(1.0f, 1.0f, 1.0f)), - m_heightNormalizer(0.0f), - m_yAdjustment(0.0f), - m_scaleFactor(1.0f), - m_theme(new Theme()), - m_isInitialized(false), - m_selectionMode(QDataVis::ModeItem), - m_selectedBar(0), - m_previouslySelectedBar(0), - m_axisLabelX(QStringLiteral("X")), - m_axisLabelZ(QStringLiteral("Z")), - m_axisLabelY(QStringLiteral("Y")), - m_sceneViewPort(rect.x(), rect.y(), rect.width(), rect.height()), - m_zoomViewPort(rect.x(), rect.y(), rect.width(), rect.height()), - m_zoomActivated(false), - m_textureHelper(new TextureHelper()), - m_labelTransparency(QDataVis::TransparencyFromTheme), - m_font(QFont(QStringLiteral("Arial"))), - m_drawer(new Drawer(*m_theme, m_font, m_labelTransparency)), - m_areaSize(QSizeF(1.0f, 1.0f)), - m_bgrTexture(0), - m_depthTexture(0), - m_selectionTexture(0), - m_depthFrameBuffer(0), - m_selectionFrameBuffer(0), - m_selectionDepthBuffer(0), - m_updateLabels(true), - m_adjustDirection(Q3DMaps::AdjustHeight), - m_shadowQuality(QDataVis::ShadowLow), - m_shadowQualityToShader(33.3f), - m_bgrHasAlpha(false), - m_boundingRect(rect.x(), rect.y(), rect.width(), rect.height()), - m_data(0), - m_valuesDirty(false) -{ - //m_data->setDrawer(m_drawer); - //QObject::connect(m_drawer, &Drawer::drawerChanged, this, &Maps3DController::updateTextures); -} - -Maps3DController::~Maps3DController() -{ - m_textureHelper->glDeleteFramebuffers(1, &m_depthFrameBuffer); - m_textureHelper->glDeleteFramebuffers(1, &m_selectionFrameBuffer); - m_textureHelper->glDeleteRenderbuffers(1, &m_selectionDepthBuffer); - m_textureHelper->deleteTexture(&m_selectionTexture); - m_textureHelper->deleteTexture(&m_bgrTexture); - delete m_barShader; - delete m_selectionShader; - delete m_backgroundShader; - delete m_barObj; - delete m_backgroundObj; - delete m_gridLineObj; - delete m_textureHelper; - delete m_drawer; - delete m_camera; -} - -void Maps3DController::initializeOpenGL() -{ - // Initialization is called multiple times when Qt Quick components are used - if (m_isInitialized) - return; - - m_renderer = new Maps3DRenderer(this); - initializeOpenGLFunctions(); - - m_textureHelper = new TextureHelper(); - m_drawer->initializeOpenGL(); - - // Initialize shaders -#if !defined(QT_OPENGL_ES_2) - if (m_shadowQuality > QDataVis::ShadowNone) { - if (!m_theme->m_uniformColor) { - initShaders(QStringLiteral(":/shaders/vertexShadow"), - QStringLiteral(":/shaders/fragmentShadowNoTexColorOnY")); - } else { - initShaders(QStringLiteral(":/shaders/vertexShadow"), - QStringLiteral(":/shaders/fragmentShadowNoTex")); - } - initBackgroundShaders(QStringLiteral(":/shaders/vertexShadow"), - QStringLiteral(":/shaders/fragmentShadow")); - } else { - if (!m_theme->m_uniformColor) { - initShaders(QStringLiteral(":/shaders/vertex"), - QStringLiteral(":/shaders/fragmentColorOnY")); - } else { - initShaders(QStringLiteral(":/shaders/vertex"), - QStringLiteral(":/shaders/fragment")); - } - initBackgroundShaders(QStringLiteral(":/shaders/vertexTexture"), - QStringLiteral(":/shaders/fragmentTexture")); - } -#else - if (!m_theme->m_uniformColor) { - initShaders(QStringLiteral(":/shaders/vertexES2"), - QStringLiteral(":/shaders/fragmentColorOnYES2")); - } else { - initShaders(QStringLiteral(":/shaders/vertexES2"), - QStringLiteral(":/shaders/fragmentES2")); - } - initBackgroundShaders(QStringLiteral(":/shaders/vertexTexture"), // Same vertex shader ok for ES2 - QStringLiteral(":/shaders/fragmentTextureES2")); -#endif - initLabelShaders(QStringLiteral(":/shaders/vertexLabel"), - QStringLiteral(":/shaders/fragmentLabel")); - -#if !defined(QT_OPENGL_ES_2) - // Init depth shader (for shadows). Init in any case, easier to handle shadow activation if done via api. - initDepthShader(); -#endif - - // Init selection shader - initSelectionShader(); - - // Load default mesh - loadBarMesh(); - - // Load grid line mesh - loadGridLineMesh(); - - // Load label mesh - loadLabelMesh(); - - // Set OpenGL features - glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_LESS); - glEnable(GL_CULL_FACE); - glCullFace(GL_BACK); - -#if !defined(QT_OPENGL_ES_2) - glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); - glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); - glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST); -#endif - - // Set initial camera position - // X must be 0 for rotation to work - we can use "setCameraRotation" for setting it later - m_camera->setDefaultCameraOrientation(QVector3D(0.0f, 0.0f, 1.0f + 2.9f * zComp), - QVector3D(0.0f, 0.0f, zComp), - QVector3D(0.0f, 1.0f, 0.0f)); - - // Adjust to default rotation - setCameraPosition(m_horizontalRotation, m_verticalRotation, m_zoomLevel); - - // Set view port - glViewport(0, 0, width(), height()); - - // Set initialized -flag - m_isInitialized = true; - - // Resize in case we've missed resize events - // Resize calls initSelectionBuffer and initDepthBuffer, so they don't need to be called here - resizeNotify(); - - // Load background mesh (we need to be initialized first) - loadBackgroundMesh(); - - // Update default light position -#ifndef USE_WIDER_SHADOWS - distanceMod = 5.0f; -#endif -} - -void Maps3DController::synchDataToRenderer() -{ - // TODO: Implement! -} - - -/*! - * \internal - */ -void Maps3DController::render(const GLuint defaultFboHandle) -{ - if (!m_isInitialized) - return; - -#ifdef DISPLAY_RENDER_SPEED - // For speed computation - static bool firstRender = true; - static QTime lastTime; - static GLint nbFrames = 0; - if (firstRender) { - lastTime.start(); - firstRender = false; - } - - // Measure speed (as milliseconds per frame) - nbFrames++; - if (lastTime.elapsed() >= 1000) { // print only if last measurement was more than 1s ago - qDebug() << qreal(lastTime.elapsed()) / qreal(nbFrames) << "ms/frame (=" << qreal(nbFrames) << "fps)"; - nbFrames = 0; - lastTime.restart(); - } -#endif - - // Update cached values - if (m_valuesDirty) { - const QMapDataArray &dataArray = *m_data->array(); - int dataSize = dataArray.size(); - m_renderItemArray.resize(dataSize); - for (int i = 0; i < dataSize ; i++) { - qreal value = dataArray.at(i).value(); - m_renderItemArray[i].setValue(value); - m_renderItemArray[i].setMapPosition(dataArray.at(i).mapPosition()); - m_renderItemArray[i].setHeight(value / m_heightNormalizer); - m_renderItemArray[i].setItemLabel(dataArray.at(i).label()); - calculateTranslation(m_renderItemArray[i]); - m_renderItemArray[i].setRenderer(this); - } - m_valuesDirty = false; - } - - if (defaultFboHandle) { - glDepthMask(true); - glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_LESS); - glEnable(GL_CULL_FACE); - glCullFace(GL_BACK); - } - - // Draw scene - drawScene(defaultFboHandle); -} - -/*! - * \internal - */ -void Maps3DController::drawScene(const GLuint defaultFboHandle) -{ - // Set clear color - QVector3D clearColor = Utils::vectorFromColor(m_theme->m_windowColor); - glClearColor(clearColor.x(), clearColor.y(), clearColor.z(), 1.0f); - - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - static QVector3D selection = skipColor; - - // Specify viewport - glViewport(m_sceneViewPort.x(), m_sceneViewPort.y(), - m_sceneViewPort.width(), m_sceneViewPort.height()); - - // Set up projection matrix - QMatrix4x4 projectionMatrix; - projectionMatrix.perspective(45.0f, (GLfloat)m_sceneViewPort.width() - / (GLfloat)m_sceneViewPort.height(), 0.1f, 100.0f); - - // Calculate view matrix - QMatrix4x4 viewMatrix = m_camera->calculateViewMatrix(m_mousePos, - m_zoomLevel * m_autoScaleAdjustment, - m_sceneViewPort.width(), - m_sceneViewPort.height()); - - // Get light position (rotate light with camera, a bit above it (as set in defaultLightPos)) - QVector3D lightPos = m_camera->calculateLightPosition(defaultLightPos, 0.0f, distanceMod); - - // Map adjustment direction to model matrix scaling - GLfloat heightMultiplier = 0.0f; - GLfloat widthMultiplier = 0.0f; - GLfloat depthMultiplier = 0.0f; - GLfloat heightScaler = 0.0f; - GLfloat widthScaler = 0.0f; - GLfloat depthScaler = 0.0f; - switch (m_adjustDirection) { - case Q3DMaps::AdjustHeight: - widthMultiplier = 0.0f; - heightMultiplier = 1.0f; - depthMultiplier = 0.0f; - widthScaler = m_barThickness.x() / m_scaleFactor; - heightScaler = 0.0f; - depthScaler = m_barThickness.z() / m_scaleFactor; - break; - case Q3DMaps::AdjustWidth: - widthMultiplier = 1.0f; - heightMultiplier = 0.0f; - depthMultiplier = 0.0f; - widthScaler = 0.0f; - heightScaler = m_barThickness.y() / m_scaleFactor; - depthScaler = m_barThickness.z() / m_scaleFactor; - break; - case Q3DMaps::AdjustDepth: - widthMultiplier = 0.0f; - heightMultiplier = 0.0f; - depthMultiplier = 1.0f; - widthScaler = m_barThickness.x() / m_scaleFactor; - heightScaler = m_barThickness.y() / m_scaleFactor; - depthScaler = 0.0f; - break; - case Q3DMaps::AdjustRadius: - widthMultiplier = 1.0f; - heightMultiplier = 0.0f; - depthMultiplier = 1.0f; - widthScaler = 0.0f; - heightScaler = m_barThickness.y() / m_scaleFactor; - depthScaler = 0.0f; - break; - case Q3DMaps::AdjustAll: - widthMultiplier = 1.0f; - heightMultiplier = 1.0f; - depthMultiplier = 1.0f; - widthScaler = 0.0f; - heightScaler = 0.0f; - depthScaler = 0.0f; - break; - } - - // Introduce regardless of shadow quality to simplify logic - QMatrix4x4 depthViewMatrix; - QMatrix4x4 depthProjectionMatrix; - -#if !defined(QT_OPENGL_ES_2) - if (m_shadowQuality > QDataVis::ShadowNone) { - // Render scene into a depth texture for using with shadow mapping - // Bind depth shader - m_depthShader->bind(); - - // Set viewport for depth map rendering. Must match texture size. Larger values give smoother shadows. - glViewport(m_sceneViewPort.x(), m_sceneViewPort.y(), - m_sceneViewPort.width() * m_shadowQuality, - m_sceneViewPort.height() * m_shadowQuality); - - // Enable drawing to framebuffer - glBindFramebuffer(GL_FRAMEBUFFER, m_depthFrameBuffer); - glClear(GL_DEPTH_BUFFER_BIT); - - // Set front face culling to reduce self-shadowing issues - glCullFace(GL_FRONT); - - // Get the depth view matrix - // It may be possible to hack lightPos here if we want to make some tweaks to shadow - QVector3D depthLightPos = m_camera->calculateLightPosition( - defaultLightPos, 0.0f, (distanceMod + 1.5f) / m_autoScaleAdjustment); - depthViewMatrix.lookAt(depthLightPos, QVector3D(0.0f, -m_yAdjustment, zComp), - QVector3D(0.0f, 1.0f, 0.0f)); - // TODO: Why does depthViewMatrix.column(3).y() goes to zero when we're directly above? That causes the scene to be not drawn from above -> must be fixed - //qDebug() << lightPos << depthViewMatrix << depthViewMatrix.column(3); - // Set the depth projection matrix -#ifndef USE_WIDER_SHADOWS - // Use this for perspective shadows - depthProjectionMatrix.perspective(15.0f, (GLfloat)m_sceneViewPort.width() - / (GLfloat)m_sceneViewPort.height(), 3.0f, 200.0f); -#else - // Use these for orthographic shadows - //qDebug() << m_areaSize.width() / m_scaleFactor << m_yAdjustment; - GLfloat testAspectRatio = (GLfloat)m_sceneViewPort.width() / (GLfloat)m_sceneViewPort.height(); - depthProjectionMatrix.ortho(-(2.0f * m_areaSize.width()) / m_scaleFactor, - (2.0f * m_areaSize.width()) / m_scaleFactor, - -m_yAdjustment * 4.0f * testAspectRatio, - m_yAdjustment * 4.0f * testAspectRatio, - 0.0f, 100.0f); -#endif -#if 0 - // Draw background to depth buffer (You don't want to do this, except maybe for debugging purposes) - if (m_backgroundObj) { - QMatrix4x4 modelMatrix; - QMatrix4x4 MVPMatrix; - - modelMatrix.translate(0.0f, -m_yAdjustment, zComp); - modelMatrix.scale(QVector3D(m_areaSize.width() / m_scaleFactor, - 1.0f, - m_areaSize.height() / m_scaleFactor)); - modelMatrix.rotate(-90.0f, 1.0f, 0.0f, 0.0f); - - MVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; - - m_depthShader->setUniformValue(m_depthShader->MVP(), MVPMatrix); - - // 1st attribute buffer : vertices - glEnableVertexAttribArray(m_depthShader->posAtt()); - glBindBuffer(GL_ARRAY_BUFFER, m_backgroundObj->vertexBuf()); - glVertexAttribPointer(m_depthShader->posAtt(), 3, GL_FLOAT, GL_FALSE, 0, (void *)0); - - // Index buffer - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_backgroundObj->elementBuf()); - - // Draw the triangles - glDrawElements(GL_TRIANGLES, m_backgroundObj->indexCount(), GL_UNSIGNED_SHORT, - (void *)0); - - // Free buffers - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - glBindBuffer(GL_ARRAY_BUFFER, 0); - - glDisableVertexAttribArray(m_depthShader->posAtt()); - } -#endif - // Draw bars to depth buffer - for (int bar = 0; bar < m_renderItemArray.size(); bar++) { - const MapRenderItem &item = m_renderItemArray.at(bar); - if (!item.value()) - continue; - - QMatrix4x4 modelMatrix; - QMatrix4x4 MVPMatrix; - - modelMatrix.translate(item.translation().x(), - heightMultiplier * item.height() + heightScaler - m_yAdjustment, - item.translation().z()); - modelMatrix.scale(QVector3D(widthMultiplier * item.height() + widthScaler, - heightMultiplier * item.height() + heightScaler, - depthMultiplier * item.height() + depthScaler)); - - MVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; - - m_depthShader->setUniformValue(m_depthShader->MVP(), MVPMatrix); - - // 1st attribute buffer : vertices - glEnableVertexAttribArray(m_depthShader->posAtt()); - glBindBuffer(GL_ARRAY_BUFFER, m_barObj->vertexBuf()); - glVertexAttribPointer(m_depthShader->posAtt(), 3, GL_FLOAT, GL_FALSE, 0, (void *)0); - - // Index buffer - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_barObj->elementBuf()); - - // Draw the triangles - glDrawElements(GL_TRIANGLES, m_barObj->indexCount(), GL_UNSIGNED_SHORT, (void *)0); - - // Free buffers - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - glBindBuffer(GL_ARRAY_BUFFER, 0); - - glDisableVertexAttribArray(m_depthShader->posAtt()); - } - - // Disable drawing to framebuffer (= enable drawing to screen) - glBindFramebuffer(GL_FRAMEBUFFER, defaultFboHandle); - - // Reset culling to normal - glCullFace(GL_BACK); - - // Release depth shader - m_depthShader->release(); - - // Revert to original viewport - glViewport(m_sceneViewPort.x(), m_sceneViewPort.y(), - m_sceneViewPort.width(), m_sceneViewPort.height()); - -#if 0 // Use this if you want to see what is being drawn to the framebuffer - // You'll also have to comment out GL_COMPARE_R_TO_TEXTURE -line in texturehelper (if using it) - m_labelShader->bind(); - glEnable(GL_TEXTURE_2D); - QMatrix4x4 modelMatrix; - QMatrix4x4 viewmatrix; - viewmatrix.lookAt(QVector3D(0.0f, 0.0f, 2.5f + zComp), - QVector3D(0.0f, 0.0f, zComp), - QVector3D(0.0f, 1.0f, 0.0f)); - modelMatrix.translate(0.0, 0.0, zComp); - QMatrix4x4 MVPMatrix = projectionMatrix * viewmatrix * modelMatrix; - m_labelShader->setUniformValue(m_labelShader->MVP(), MVPMatrix); - m_drawer->drawObject(m_labelShader, m_labelObj, - m_depthTexture); - glDisable(GL_TEXTURE_2D); - m_labelShader->release(); -#endif - } -#endif - -#if 1 - // Skip selection mode drawing if we're zoomed or have no selection mode - if (!m_zoomActivated && m_selectionMode > QDataVis::ModeNone) { - // Bind selection shader - m_selectionShader->bind(); - - // Draw bars to selection buffer - glBindFramebuffer(GL_FRAMEBUFFER, m_selectionFrameBuffer); - glEnable(GL_DEPTH_TEST); // Needed, otherwise the depth render buffer is not used - glClearColor(skipColor.x() / 255, skipColor.y() / 255, skipColor.z() / 255, 1.0f); // Set clear color to white (= skipColor) - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Needed for clearing the frame buffer - glDisable(GL_DITHER); // disable dithering, it may affect colors if enabled - GLint barIdxRed = 0; - GLint barIdxGreen = 0; - GLint barIdxBlue = 0; - for (int bar = 0; bar < m_renderItemArray.size(); bar++, barIdxRed++) { - const MapRenderItem &item = m_renderItemArray.at(bar); - if (!item.value()) - continue; - - QMatrix4x4 modelMatrix; - QMatrix4x4 MVPMatrix; - - modelMatrix.translate(item.translation().x(), - heightMultiplier * item.height() + heightScaler - m_yAdjustment, - item.translation().z()); - modelMatrix.scale(QVector3D(widthMultiplier * item.height() + widthScaler, - heightMultiplier * item.height() + heightScaler, - depthMultiplier * item.height() + depthScaler)); - - MVPMatrix = projectionMatrix * viewMatrix * modelMatrix; - - if (barIdxRed > 0 && barIdxRed % 256 == 0) { - barIdxRed = 0; - barIdxGreen++; - } - if (barIdxGreen > 0 && barIdxGreen % 256 == 0) { - barIdxGreen = 0; - barIdxBlue++; - } - if (barIdxBlue > 255) - qFatal("Too many objects"); - - QVector3D barColor = QVector3D((GLfloat)barIdxRed / 255.0f, - (GLfloat)barIdxGreen / 255.0f, - (GLfloat)barIdxBlue / 255.0f); - - m_selectionShader->setUniformValue(m_selectionShader->MVP(), MVPMatrix); - m_selectionShader->setUniformValue(m_selectionShader->color(), barColor); - - // 1st attribute buffer : vertices - glEnableVertexAttribArray(m_selectionShader->posAtt()); - glBindBuffer(GL_ARRAY_BUFFER, m_barObj->vertexBuf()); - glVertexAttribPointer(m_selectionShader->posAtt(), 3, GL_FLOAT, GL_FALSE, 0, (void *)0); - - // Index buffer - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_barObj->elementBuf()); - - // Draw the triangles - glDrawElements(GL_TRIANGLES, m_barObj->indexCount(), GL_UNSIGNED_SHORT, (void *)0); - - // Free buffers - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - glBindBuffer(GL_ARRAY_BUFFER, 0); - - glDisableVertexAttribArray(m_selectionShader->posAtt()); - } - glEnable(GL_DITHER); - - // Read color under cursor - if (Maps3DController::MouseOnScene == m_mousePressed) - selection = Utils::getSelection(m_mousePos, height()); - - glBindFramebuffer(GL_FRAMEBUFFER, defaultFboHandle); - - // Release selection shader - m_selectionShader->release(); - -#if 0 // Use this if you want to see what is being drawn to the framebuffer - m_labelShader->bind(); - glDisable(GL_DEPTH_TEST); - glEnable(GL_TEXTURE_2D); - QMatrix4x4 modelMatrix; - QMatrix4x4 viewmatrix; - viewmatrix.lookAt(QVector3D(0.0f, 0.0f, 2.0f + zComp), - QVector3D(0.0f, 0.0f, zComp), - QVector3D(0.0f, 1.0f, 0.0f)); - modelMatrix.translate(0.0, 0.0, zComp); - QMatrix4x4 MVPMatrix = projectionMatrix * viewmatrix * modelMatrix; - m_labelShader->setUniformValue(m_labelShader->MVP(), MVPMatrix); - m_drawer->drawObject(m_labelShader, m_labelObj, - m_selectionTexture); - glDisable(GL_TEXTURE_2D); - m_labelShader->release(); -#endif - } -#if 1 - // Bind bar shader - m_barShader->bind(); - - // Enable texture - glEnable(GL_TEXTURE_2D); - - // Draw bars - // TODO: Handle zoom by camera transformations - //if (!m_zoomActivated) - - bool barSelectionFound = false; - for (int bar = 0; bar < m_renderItemArray.size(); bar++) { - MapRenderItem &item = m_renderItemArray[bar]; - if (!item.value()) - continue; - - QMatrix4x4 modelMatrix; - QMatrix4x4 MVPMatrix; - QMatrix4x4 depthMVPMatrix; - QMatrix4x4 itModelMatrix; - - modelMatrix.translate(item.translation().x(), - heightMultiplier * item.height() + heightScaler - m_yAdjustment, - item.translation().z()); - modelMatrix.scale(QVector3D(widthMultiplier * item.height() + widthScaler, - heightMultiplier * item.height() + heightScaler, - depthMultiplier * item.height() + depthScaler)); - itModelMatrix.scale(QVector3D(widthMultiplier * item.height() + widthScaler, - heightMultiplier * item.height() + heightScaler, - depthMultiplier * item.height() + depthScaler)); - -#ifdef SHOW_DEPTH_TEXTURE_SCENE - MVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; -#else - MVPMatrix = projectionMatrix * viewMatrix * modelMatrix; -#endif - depthMVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; - - QVector3D baseColor = Utils::vectorFromColor(m_theme->m_baseColor); - QVector3D heightColor = Utils::vectorFromColor(m_theme->m_heightColor) * item.height(); - - QVector3D barColor = baseColor + heightColor; - - GLfloat lightStrength = m_theme->m_lightStrength; - if (m_selectionMode > QDataVis::ModeNone) { - Maps3DController::SelectionType selectionType = isSelected(bar, selection); - switch (selectionType) { - case Maps3DController::SelectionBar: { - barColor = Utils::vectorFromColor(m_theme->m_highlightBarColor); - lightStrength = m_theme->m_highlightLightStrength; - // Insert data to QDataItem. We have no ownership, don't delete the previous one - if (!m_zoomActivated) { - m_selectedBar = &item; - barSelectionFound = true; - } - break; - } - case Maps3DController::SelectionNone: { - // Current bar is not selected, nor on a row or column - // do nothing - break; - } - default: { - // Unsupported selection mode - // do nothing - break; - } - } - } - - if (item.height() != 0) { - // Set shader bindings - m_barShader->setUniformValue(m_barShader->lightP(), lightPos); - m_barShader->setUniformValue(m_barShader->view(), viewMatrix); - m_barShader->setUniformValue(m_barShader->model(), modelMatrix); - m_barShader->setUniformValue(m_barShader->nModel(), - itModelMatrix.inverted().transposed()); - m_barShader->setUniformValue(m_barShader->MVP(), MVPMatrix); - m_barShader->setUniformValue(m_barShader->color(), barColor); - m_barShader->setUniformValue(m_barShader->ambientS(), m_theme->m_ambientStrength); - -#if !defined(QT_OPENGL_ES_2) - if (m_shadowQuality > QDataVis::ShadowNone) { - // Set shadow shader bindings - m_barShader->setUniformValue(m_barShader->shadowQ(), m_shadowQualityToShader); - m_barShader->setUniformValue(m_barShader->depth(), depthMVPMatrix); - m_barShader->setUniformValue(m_barShader->lightS(), lightStrength / 10.0f); - - // Draw the object - m_drawer->drawObject(m_barShader, m_barObj, 0, m_depthTexture); - } else -#endif - { - // Set shadowless shader bindings - m_barShader->setUniformValue(m_barShader->lightS(), lightStrength); - - // Draw the object - m_drawer->drawObject(m_barShader, m_barObj); - } - } - } - - // Release bar shader - m_barShader->release(); -#if 1 - // Bind background shader - m_backgroundShader->bind(); - if (m_bgrHasAlpha) { - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - } - - // Draw background - if (m_backgroundObj) { - QMatrix4x4 modelMatrix; - QMatrix4x4 MVPMatrix; - QMatrix4x4 depthMVPMatrix; - QMatrix4x4 itModelMatrix; - - modelMatrix.translate(0.0f, -m_yAdjustment, zComp); - modelMatrix.scale(QVector3D(m_areaSize.width() / m_scaleFactor, - 1.0f, - m_areaSize.height() / m_scaleFactor)); - modelMatrix.rotate(-90.0f, 1.0f, 0.0f, 0.0f); - itModelMatrix.scale(QVector3D(m_areaSize.width() / m_scaleFactor, - 1.0f, - m_areaSize.height() / m_scaleFactor)); - -#ifdef SHOW_DEPTH_TEXTURE_SCENE - MVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; -#else - MVPMatrix = projectionMatrix * viewMatrix * modelMatrix; -#endif - depthMVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; - - // Set shader bindings - m_backgroundShader->setUniformValue(m_backgroundShader->lightP(), lightPos); - m_backgroundShader->setUniformValue(m_backgroundShader->view(), viewMatrix); - m_backgroundShader->setUniformValue(m_backgroundShader->model(), modelMatrix); - m_backgroundShader->setUniformValue(m_backgroundShader->nModel(), - itModelMatrix.inverted().transposed()); - m_backgroundShader->setUniformValue(m_backgroundShader->MVP(), MVPMatrix); - m_backgroundShader->setUniformValue(m_backgroundShader->ambientS(), - m_theme->m_ambientStrength * 3.0f); - -#if !defined(QT_OPENGL_ES_2) - if (m_shadowQuality > QDataVis::ShadowNone) { - // Set shadow shader bindings - m_backgroundShader->setUniformValue(m_backgroundShader->shadowQ(), - m_shadowQualityToShader); - m_backgroundShader->setUniformValue(m_backgroundShader->depth(), - depthMVPMatrix); - m_backgroundShader->setUniformValue(m_backgroundShader->lightS(), - m_theme->m_lightStrength / 25.0f); - - // Draw the object - m_drawer->drawObject(m_backgroundShader, m_backgroundObj, m_bgrTexture, m_depthTexture); - } else -#endif - { - // Set shadowless shader bindings - m_backgroundShader->setUniformValue(m_backgroundShader->lightS(), - m_theme->m_lightStrength); - - // Draw the object - m_drawer->drawObject(m_backgroundShader, m_backgroundObj, m_bgrTexture); - } - } - - // Disable textures - glDisable(GL_TEXTURE_2D); - if (m_bgrHasAlpha) - glDisable(GL_BLEND); - - // Release background shader - m_backgroundShader->release(); -#endif - - // Handle zoom activation and label drawing - if (!barSelectionFound) { - // We have no ownership, don't delete. Just NULL the pointer. - m_selectedBar = NULL; - //if (m_zoomActivated && Maps3DController::MouseOnOverview == m_mousePressed) { - //m_sceneViewPort = QRect(0, 0, width(), height()); - //m_zoomActivated = false; - //} - } /*else if (m_selectionMode >= ModeZoomRow - && Maps3DController::MouseOnScene == m_mousePressed) { - // Activate zoom mode - m_zoomActivated = true; - m_sceneViewPort = QRect(0, height() - height() / 5, width() / 5, height() / 5); - - // Create label textures - for (int col = 0; col < m_zoomSelection->row().size(); col++) { - QDataItem *item = m_zoomSelection->getItem(col); - m_drawer->generateLabelTexture(item); - } - }*/ else { - // Print value of selected bar - m_labelShader->bind(); - glDisable(GL_DEPTH_TEST); - glEnable(GL_TEXTURE_2D); - if (m_labelTransparency > QDataVis::TransparencyNone) { - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - } -#ifndef DISPLAY_FULL_DATA_ON_SELECTION - // Draw just the value string of the selected bar - if (m_previouslySelectedBar != m_selectedBar || m_updateLabels) { - m_drawer->generateLabelTexture(m_selectedBar); - m_previouslySelectedBar = m_selectedBar; - } - - m_drawer->drawLabel(*m_selectedBar, m_selectedBar->labelItem(), - viewMatrix, projectionMatrix, - QVector3D(0.0f, m_yAdjustment, zComp), - QVector3D(0.0f, 0.0f, 0.0f), m_selectedBar->height(), - m_selectionMode, m_labelShader, - m_labelObj, m_camera, true); -#else - // Draw the value string followed by row label and column label - LabelItem &labelItem = m_selectedBar->selectionLabel(); - if (m_previouslySelectedBar != m_selectedBar || m_updateLabels || !labelItem.textureId()) { - QString labelText = m_selectedBar->label(); - // TODO More elaborate label? - m_drawer->generateLabelItem(&labelItem, labelText); - m_previouslySelectedBar = m_selectedBar; - } - - m_drawer->drawLabel(*m_selectedBar, labelItem, viewMatrix, projectionMatrix, - QVector3D(0.0f, m_yAdjustment, zComp), - QVector3D(0.0f, 0.0f, 0.0f), m_selectedBar->height(), - m_selectionMode, m_labelShader, - m_labelObj, true, false); -#endif - glDisable(GL_TEXTURE_2D); - if (m_labelTransparency > QDataVis::TransparencyNone) - glDisable(GL_BLEND); - glEnable(GL_DEPTH_TEST); - - // Release label shader - m_labelShader->release(); - - // Reset label update flag; they should have been updated when we get here - m_updateLabels = false; - } -#if 0 - // TODO: Calculations done temporarily here. When optimizing, move to after data set addition? Keep drawing of the labels here. - // Bind label shader - m_labelShader->bind(); - - glEnable(GL_TEXTURE_2D); - if (m_labelTransparency > TransparencyNone) { - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - } - - // Calculate the positions for row and column labels and store them into QDataItems (and QDataRows?) - for (int row = 0; row != m_sampleCount.second; row += 1) { - // Go through all rows and get position of max+1 or min-1 column, depending on x flip - // We need only positions for them, labels have already been generated at QDataSet. Just add LabelItems - rowPos = (row + 1) * (m_barSpacing.height()); - barPos = 0; - GLfloat rotLabelX = -90.0f; - GLfloat rotLabelY = 0.0f; - Qt::AlignmentFlag alignment = Qt::AlignRight; - if (m_zFlipped) - rotLabelY = 180.0f; - if (m_xFlipped) { - barPos = (m_sampleCount.first + 1) * (m_barSpacing.width()); - alignment = Qt::AlignLeft; - } - QVector3D labelPos = QVector3D((m_rowWidth - barPos) / m_scaleFactor, - -m_yAdjustment + 0.005f, // raise a bit over background to avoid depth "glimmering" - (m_columnDepth - rowPos) / m_scaleFactor + zComp); - - // TODO: Try it; draw the label here - - // Create a data item - QDataItem *label = new QDataItem(); - label->setTranslation(labelPos); - if (m_data->d_ptr->rowLabelItems().size() > row) { - label->setLabel(m_data->d_ptr->rowLabelItems().at(m_data->d_ptr->rowLabelItems().size() - - row - 1)); - } - - //qDebug() << "labelPos, row" << row + 1 << ":" << labelPos << m_dataSet->rowLabels().at(row); - - m_drawer->drawLabel(*label, label->label(), viewMatrix, projectionMatrix, - QVector3D(0.0f, m_yAdjustment, zComp), - QVector3D(rotLabelX, rotLabelY, 0.0f), m_heightNormalizer, - m_selectionMode, m_labelShader, - m_labelObj, true, true, Drawer::LabelMid, alignment); - - delete label; - } - for (int bar = 0; bar != m_sampleCount.first; bar += 1) { - // Go through all columns and get position of max+1 or min-1 row, depending on z flip - // We need only positions for them, labels have already been generated at QDataSet. Just add LabelItems - barPos = (bar + 1) * (m_barSpacing.width()); - rowPos = 0; - GLfloat rotLabelX = -90.0f; - GLfloat rotLabelY = 90.0f; - Qt::AlignmentFlag alignment = Qt::AlignLeft; - if (m_xFlipped) - rotLabelY = -90.0f; - if (m_zFlipped) { - rowPos = (m_sampleCount.second + 1) * (m_barSpacing.height()); - alignment = Qt::AlignRight; - } - QVector3D labelPos = QVector3D((m_rowWidth - barPos) / m_scaleFactor, - -m_yAdjustment + 0.005f, // raise a bit over background to avoid depth "glimmering" - (m_columnDepth - rowPos) / m_scaleFactor + zComp); - - // TODO: Try it; draw the label here - - // Create a data item - QDataItem *label = new QDataItem(); - label->setTranslation(labelPos); - if (m_data->d_ptr->columnLabelItems().size() > bar) { - label->setLabel(m_data->d_ptr->columnLabelItems().at( - m_data->d_ptr->columnLabelItems().size() - bar - 1)); - } - - //qDebug() << "labelPos, col" << bar + 1 << ":" << labelPos << m_dataSet->columnLabels().at(bar); - - m_drawer->drawLabel(*label, label->label(), viewMatrix, projectionMatrix, - QVector3D(0.0f, m_yAdjustment, zComp), - QVector3D(rotLabelX, rotLabelY, 0.0f), m_heightNormalizer, - m_selectionMode, m_labelShader, - m_labelObj, true, true, Drawer::LabelMid, alignment); - - delete label; - } - glDisable(GL_TEXTURE_2D); - if (m_labelTransparency > TransparencyNone) - glDisable(GL_BLEND); - - // Release label shader - m_labelShader->release(); -#endif -#endif -#endif -} - -#if defined(Q_OS_ANDROID) -/*! - * \internal - */ -void Maps3DController::mouseDoubleClickEvent(QMouseEvent *event) -{ - if (!m_zoomActivated) { - m_mousePressed = Maps3DController::MouseOnScene; - // update mouse positions to prevent jumping when releasing or repressing a button - m_mousePos = event->pos(); - } -} - -/*! - * \internal - */ -void Maps3DController::touchEvent(QTouchEvent *event) -{ - static int prevDistance = 0; - - QList<QTouchEvent::TouchPoint> points; - points = event->touchPoints(); - - if (points.count() == 2) { - m_mousePressed = Maps3DController::MouseOnPinch; - - QPointF distance = points.at(0).pos() - points.at(1).pos(); - int newDistance = distance.manhattanLength(); - int zoomRate = 1; - if (m_zoomLevel > 100) - zoomRate = 5; - if (newDistance > prevDistance) - m_zoomLevel += zoomRate; - else - m_zoomLevel -= zoomRate; - if (m_zoomLevel > 500) - m_zoomLevel = 500; - else if (m_zoomLevel < 10) - m_zoomLevel = 10; - prevDistance = newDistance; - //qDebug() << "distance" << distance.manhattanLength(); - } -} -#endif - -/*! - * \internal - */ -void Maps3DController::mousePressEvent(QMouseEvent *event, const QPoint &mousePos) -{ - if (Qt::LeftButton == event->button()) { - if (m_zoomActivated) { - //qDebug() << event->pos().x() << event->pos().y() << m_sceneViewPort << m_zoomViewPort; - if (mousePos.x() <= m_sceneViewPort.width() - && mousePos.y() <= m_sceneViewPort.height()) { - m_mousePressed = Maps3DController::MouseOnOverview; - //qDebug() << "Mouse pressed on overview"; - } else { - m_mousePressed = Maps3DController::MouseOnZoom; - //qDebug() << "Mouse pressed on zoom"; - } - } else { -#if !defined(Q_OS_ANDROID) - m_mousePressed = Maps3DController::MouseOnScene; -#else - m_mousePressed = Maps3DController::MouseRotating; -#endif - // update mouse positions to prevent jumping when releasing or repressing a button - m_mousePos = mousePos; - //qDebug() << "Mouse pressed on scene"; - } - } else if (Qt::MiddleButton == event->button()) { - // reset rotations - m_mousePos = QPoint(0, 0); - } else if (Qt::RightButton == event->button()) { -#if !defined(Q_OS_ANDROID) - m_mousePressed = Maps3DController::MouseRotating; -#else - m_mousePressed = Maps3DController::MouseOnScene; -#endif - // update mouse positions to prevent jumping when releasing or repressing a button - m_mousePos = mousePos; - } - m_camera->updateMousePos(m_mousePos); -} - -/*! - * \internal - */ -void Maps3DController::mouseReleaseEvent(QMouseEvent *event, const QPoint &mousePos) -{ - Q_UNUSED(event); - //qDebug() << "mouse button released" << event->button(); - if (Maps3DController::MouseRotating == m_mousePressed) { - // update mouse positions to prevent jumping when releasing or repressing a button - m_mousePos = mousePos; - m_camera->updateMousePos(mousePos); - } - m_mousePressed = Maps3DController::MouseNone; -} - -/*! - * \internal - */ -void Maps3DController::mouseMoveEvent(QMouseEvent *event, const QPoint &mousePos) -{ - Q_UNUSED(event); - if (Maps3DController::MouseRotating == m_mousePressed) { - //qDebug() << "mouse moved while pressed" << event->pos(); - m_mousePos = mousePos; - } -#if 0 - // TODO: Testi - laske kursorin sijainti scenessä - QPointF mouse3D((2.0f * event->pos().x() - width()) / height(), - 1.0f - (2.0f * event->pos().y()) / height()); - //qDebug() << "mouse position in scene" << mouse3D; - - // TODO: Testi laske focal point - GLfloat focalPoint = tan(45.0f / 2.0f); - - // TODO: Testi - laske viewmatriisin kerroin - QVector3D worldRay = QVector3D(0.0f, 0.0f, 0.0f) - QVector3D(mouse3D.x(), mouse3D.y(), - -focalPoint); - //qDebug() << "worldRay" << worldRay; - // multiply viewmatrix with this to get something? -#endif -} - -/*! - * \internal - */ -void Maps3DController::wheelEvent(QWheelEvent *event) -{ - if (m_zoomLevel > 100) - m_zoomLevel += event->angleDelta().y() / 12; - else if (m_zoomLevel > 50) - m_zoomLevel += event->angleDelta().y() / 60; - else - m_zoomLevel += event->angleDelta().y() / 120; - if (m_zoomLevel > 500) - m_zoomLevel = 500; - else if (m_zoomLevel < 10) - m_zoomLevel = 10; -} - -/*! - * \internal - */ -void Maps3DController::resizeNotify() -{ - if (!m_isInitialized) - return; - - // Set view port - if (m_zoomActivated) - m_sceneViewPort = QRect(0, height() - height() / 5, width() / 5, height() / 5); - else - m_sceneViewPort = QRect(0, 0, width(), height()); - m_zoomViewPort = QRect(0, 0, width(), height()); - - // Calculate zoom level based on aspect ratio - GLfloat div; - GLfloat zoomAdjustment; - div = qMin(width(), height()); - zoomAdjustment = defaultRatio * ((width() / div) / (height() / div)); - //qDebug() << "zoom adjustment" << zoomAdjustment; - m_autoScaleAdjustment = qMin(zoomAdjustment, 1.0f); // clamp to 1.0f - - // Re-init selection buffer - initSelectionBuffer(); - -#if !defined(QT_OPENGL_ES_2) - // Re-init depth buffer - initDepthBuffer(); -#endif -} - -void Maps3DController::setBarSpecs(const QVector3D &thickness, - Q3DMaps::AdjustmentDirection direction) -{ - m_barThickness = thickness; - m_adjustDirection = direction; -} - -void Maps3DController::setBarType(QDataVis::MeshStyle style, bool smooth) -{ - if (style == QDataVis::Bars) { - if (smooth) - m_objFile = QStringLiteral(":/defaultMeshes/barSmooth"); - else - m_objFile = QStringLiteral(":/defaultMeshes/bar"); - } else if (style == QDataVis::Pyramids) { - if (smooth) - m_objFile = QStringLiteral(":/defaultMeshes/pyramidSmooth"); - else - m_objFile = QStringLiteral(":/defaultMeshes/pyramid"); - } else if (style == QDataVis::Cones) { - if (smooth) - m_objFile = QStringLiteral(":/defaultMeshes/coneSmooth"); - else - m_objFile = QStringLiteral(":/defaultMeshes/cone"); - } else if (style == QDataVis::Cylinders) { - if (smooth) - m_objFile = QStringLiteral(":/defaultMeshes/cylinderSmooth"); - else - m_objFile = QStringLiteral(":/defaultMeshes/cylinder"); - } else if (style == QDataVis::BevelBars) { - if (smooth) - m_objFile = QStringLiteral(":/defaultMeshes/bevelbarSmooth"); - else - m_objFile = QStringLiteral(":/defaultMeshes/bevelbar"); - } else if (style == QDataVis::Spheres) { - if (smooth) - m_objFile = QStringLiteral(":/defaultMeshes/sphereSmooth"); - else - m_objFile = QStringLiteral(":/defaultMeshes/sphere"); - } - // Reload mesh data - if (m_isInitialized) - loadBarMesh(); -} - -void Maps3DController::setMeshFileName(const QString &objFileName) -{ - m_objFile = objFileName; -} - -void Maps3DController::setCameraPreset(QDataVis::CameraPreset preset) -{ - m_camera->setCameraPreset(preset); -} - -void Maps3DController::setCameraPosition(GLfloat horizontal, GLfloat vertical, GLint distance) -{ - m_horizontalRotation = qBound(-180.0f, horizontal, 180.0f); - m_verticalRotation = qBound(0.0f, vertical, 90.0f); - m_zoomLevel = qBound(10, distance, 500); - m_camera->setCameraRotation(QPointF(m_horizontalRotation, m_verticalRotation)); - //qDebug() << "camera rotation set to" << m_horizontalRotation << m_verticalRotation; -} - -void Maps3DController::setTheme(QDataVis::ColorTheme colorTheme) -{ - m_theme->useColorTheme(colorTheme); - m_drawer->setTheme(*m_theme); -#if !defined(QT_OPENGL_ES_2) - if (m_shadowQuality > QDataVis::ShadowNone) { - // Re-init shaders - if (!m_theme->m_uniformColor) { - initShaders(QStringLiteral(":/shaders/vertexShadow"), - QStringLiteral(":/shaders/fragmentShadowNoTexColorOnY")); - } else { - initShaders(QStringLiteral(":/shaders/vertexShadow"), - QStringLiteral(":/shaders/fragmentShadowNoTex")); - } - } else { - // Re-init shaders - if (!m_theme->m_uniformColor) { - initShaders(QStringLiteral(":/shaders/vertex"), - QStringLiteral(":/shaders/fragmentColorOnY")); - } else { - initShaders(QStringLiteral(":/shaders/vertex"), - QStringLiteral(":/shaders/fragment")); - } - } -#else - if (!m_theme->m_uniformColor) { - initShaders(QStringLiteral(":/shaders/vertexES2"), - QStringLiteral(":/shaders/fragmentColorOnYES2")); - } else { - initShaders(QStringLiteral(":/shaders/vertexES2"), - QStringLiteral(":/shaders/fragmentES2")); - } -#endif - m_updateLabels = true; -} - -void Maps3DController::setBarColor(QColor baseColor, QColor heightColor, bool uniform) -{ - m_theme->m_baseColor = baseColor; - m_theme->m_heightColor = heightColor; - if (m_theme->m_uniformColor != uniform) { -#if !defined(QT_OPENGL_ES_2) - if (m_shadowQuality > QDataVis::ShadowNone) { - // Re-init shaders - if (!m_theme->m_uniformColor) { - initShaders(QStringLiteral(":/shaders/vertexShadow"), - QStringLiteral(":/shaders/fragmentShadowNoTexColorOnY")); - } else { - initShaders(QStringLiteral(":/shaders/vertexShadow"), - QStringLiteral(":/shaders/fragmentShadowNoTex")); - } - } else { - // Re-init shaders - if (!m_theme->m_uniformColor) { - initShaders(QStringLiteral(":/shaders/vertex"), - QStringLiteral(":/shaders/fragmentColorOnY")); - } else { - initShaders(QStringLiteral(":/shaders/vertex"), - QStringLiteral(":/shaders/fragment")); - } - } -#else - if (!m_theme->m_uniformColor) { - initShaders(QStringLiteral(":/shaders/vertexES2"), - QStringLiteral(":/shaders/fragmentColorOnYES2")); - } else { - initShaders(QStringLiteral(":/shaders/vertexES2"), - QStringLiteral(":/shaders/fragmentES2")); - } -#endif - } - m_theme->m_uniformColor = uniform; -} - -void Maps3DController::setAreaSpecs(const QRect &areaRect, const QImage &image) -{ - calculateSceneScalingFactors(areaRect); - setImage(image); -} - -void Maps3DController::setImage(const QImage &image) -{ - m_bgrHasAlpha = image.hasAlphaChannel(); - if (m_bgrTexture) - glDeleteTextures(1, &m_bgrTexture); - m_bgrTexture = m_textureHelper->create2DTexture(image, true, true); -} - -void Maps3DController::setSelectionMode(QDataVis::SelectionMode mode) -{ - m_selectionMode = mode; - // Disable zoom if mode changes - //m_zoomActivated = false; - //m_sceneViewPort = QRect(0, 0, width(), height()); -} - -QDataVis::SelectionMode Maps3DController::selectionMode() -{ - return m_selectionMode; -} - -void Maps3DController::setFontSize(float fontsize) -{ - m_font.setPointSizeF(fontsize); - m_drawer->setFont(m_font); - m_updateLabels = true; -} - -float Maps3DController::fontSize() -{ - return m_font.pointSizeF(); -} - -void Maps3DController::setFont(const QFont &font) -{ - m_font = font; - m_drawer->setFont(font); - m_updateLabels = true; -} - -QFont Maps3DController::font() -{ - return m_font; -} - -void Maps3DController::setLabelTransparency(QDataVis::LabelTransparency transparency) -{ - m_labelTransparency = transparency; - m_drawer->setTransparency(transparency); - m_updateLabels = true; -} - -QDataVis::LabelTransparency Maps3DController::labelTransparency() -{ - return m_labelTransparency; -} - -QDataVis::ShadowQuality Maps3DController::setShadowQuality(QDataVis::ShadowQuality quality) -{ - m_shadowQuality = quality; - switch (quality) { - case QDataVis::ShadowLow: - //qDebug() << "ShadowLow"; - m_shadowQualityToShader = 33.3f; - break; - case QDataVis::ShadowMedium: - //qDebug() << "ShadowMedium"; - m_shadowQualityToShader = 100.0f; - break; - case QDataVis::ShadowHigh: - //qDebug() << "ShadowHigh"; - m_shadowQualityToShader = 200.0f; - break; - default: - m_shadowQualityToShader = 0.0f; - break; - } - if (m_isInitialized) { -#if !defined(QT_OPENGL_ES_2) - if (m_shadowQuality > QDataVis::ShadowNone) { - // Re-init shaders - if (!m_theme->m_uniformColor) { - initShaders(QStringLiteral(":/shaders/vertexShadow"), - QStringLiteral(":/shaders/fragmentShadowNoTexColorOnY")); - } else { - initShaders(QStringLiteral(":/shaders/vertexShadow"), - QStringLiteral(":/shaders/fragmentShadowNoTex")); - } - initBackgroundShaders(QStringLiteral(":/shaders/vertexShadow"), - QStringLiteral(":/shaders/fragmentShadow")); - } else { - // Re-init shaders - if (!m_theme->m_uniformColor) { - initShaders(QStringLiteral(":/shaders/vertex"), - QStringLiteral(":/shaders/fragmentColorOnY")); - } else { - initShaders(QStringLiteral(":/shaders/vertex"), - QStringLiteral(":/shaders/fragment")); - } - initBackgroundShaders(QStringLiteral(":/shaders/vertexTexture"), - QStringLiteral(":/shaders/fragmentTexture")); - } - // Re-init depth buffer - initDepthBuffer(); -#else - if (!m_theme->m_uniformColor) { - initShaders(QStringLiteral(":/shaders/vertexES2"), - QStringLiteral(":/shaders/fragmentColorOnYES2")); - } else { - initShaders(QStringLiteral(":/shaders/vertexES2"), - QStringLiteral(":/shaders/fragmentES2")); - } - initBackgroundShaders(QStringLiteral(":/shaders/vertexTexture"), // Same vertex shader ok for ES2 - QStringLiteral(":/shaders/fragmentTextureES2")); -#endif - } - return m_shadowQuality; -} - -QDataVis::ShadowQuality Maps3DController::shadowQuality() -{ - return m_shadowQuality; -} - - - -const QSize Maps3DController::size() -{ - return m_boundingRect.size(); -} - -const QRect Maps3DController::boundingRect() -{ - return m_boundingRect; -} - -void Maps3DController::setBoundingRect(const QRect boundingRect) -{ - m_boundingRect = boundingRect; - resizeNotify(); -} - -void Maps3DController::setWidth(const int width) -{ - m_boundingRect.setWidth(width); - resizeNotify(); -} - -int Maps3DController::width() -{ - return m_boundingRect.width(); -} - -void Maps3DController::setHeight(const int height) -{ - m_boundingRect.setHeight(height); - resizeNotify(); -} - -int Maps3DController::height() -{ - return m_boundingRect.height(); -} - -void Maps3DController::setX(const int x) -{ - m_boundingRect.setX(x); -} - -int Maps3DController::x() -{ - return m_boundingRect.x(); -} - -void Maps3DController::setY(const int y) -{ - m_boundingRect.setY(y); -} - -int Maps3DController::y() -{ - return m_boundingRect.y(); -} - -void Maps3DController::loadBarMesh() -{ - if (m_barObj) - delete m_barObj; - m_barObj = new ObjectHelper(m_objFile); - m_barObj->load(); -} - -void Maps3DController::loadBackgroundMesh() -{ - if (m_backgroundObj) - delete m_backgroundObj; - m_backgroundObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/label")); - m_backgroundObj->load(); -} - -void Maps3DController::loadGridLineMesh() -{ - if (m_gridLineObj) - delete m_gridLineObj; - m_gridLineObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/bar")); - m_gridLineObj->load(); -} - -void Maps3DController::loadLabelMesh() -{ - if (m_labelObj) - delete m_labelObj; - m_labelObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/label")); - m_labelObj->load(); -} - -void Maps3DController::initShaders(const QString &vertexShader, const QString &fragmentShader) -{ - if (m_barShader) - delete m_barShader; - m_barShader = new ShaderHelper(this, vertexShader, fragmentShader); - m_barShader->initialize(); -} - -void Maps3DController::initSelectionShader() -{ - if (m_selectionShader) - delete m_selectionShader; - m_selectionShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexSelection"), - QStringLiteral(":/shaders/fragmentSelection")); - m_selectionShader->initialize(); -} - -void Maps3DController::initSelectionBuffer() -{ - if (m_selectionTexture) - m_textureHelper->deleteTexture(&m_selectionTexture); - - m_selectionTexture = m_textureHelper->createSelectionTexture(this->size(), - m_selectionFrameBuffer, - m_selectionDepthBuffer); -} - -#if !defined(QT_OPENGL_ES_2) -void Maps3DController::initDepthShader() -{ - if (m_depthShader) - delete m_depthShader; - m_depthShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexDepth"), - QStringLiteral(":/shaders/fragmentDepth")); - m_depthShader->initialize(); -} - -void Maps3DController::initDepthBuffer() -{ - if (!m_isInitialized) - return; - - if (m_depthTexture) { - m_textureHelper->deleteTexture(&m_depthTexture); - m_depthTexture = 0; - } - - if (m_shadowQuality > QDataVis::ShadowNone) { - m_depthTexture = m_textureHelper->createDepthTexture(this->size(), m_depthFrameBuffer, - m_shadowQuality); - if (!m_depthTexture) { - switch (m_shadowQuality) { - case QDataVis::ShadowHigh: - qWarning("Creating high quality shadows failed. Changing to medium quality."); - (void)setShadowQuality(QDataVis::ShadowMedium); - break; - case QDataVis::ShadowMedium: - qWarning("Creating medium quality shadows failed. Changing to low quality."); - (void)setShadowQuality(QDataVis::ShadowLow); - break; - case QDataVis::ShadowLow: - qWarning("Creating low quality shadows failed. Switching shadows off."); - (void)setShadowQuality(QDataVis::ShadowNone); - break; - default: - // Cannot get here - break; - } - } - } -} -#endif - -void Maps3DController::initBackgroundShaders(const QString &vertexShader, - const QString &fragmentShader) -{ - if (m_backgroundShader) - delete m_backgroundShader; - m_backgroundShader = new ShaderHelper(this, vertexShader, fragmentShader); - m_backgroundShader->initialize(); -} - -void Maps3DController::initLabelShaders(const QString &vertexShader, const QString &fragmentShader) -{ - if (m_labelShader) - delete m_labelShader; - m_labelShader = new ShaderHelper(this, vertexShader, fragmentShader); - m_labelShader->initialize(); -} - -void Maps3DController::updateTextures() -{ - // Drawer has changed; this flag needs to be checked when checking if we need to update labels - m_updateLabels = true; -} - -void Maps3DController::calculateSceneScalingFactors(const QRect &areaRect) -{ - m_areaSize = areaRect.size(); - // Calculate scaling factor so that we can be sure the whole area fits to positive z space - if (zComp > 1.0f) - m_scaleFactor = qMax(m_areaSize.width(), m_areaSize.height()) / zComp; - else - m_scaleFactor = qMax(m_areaSize.width(), m_areaSize.height()); - //qDebug() << "scaleFactor" << m_scaleFactor; -} - -void Maps3DController::calculateHeightAdjustment(const QPair<GLfloat, GLfloat> &limits) -{ - // 2.0f = max difference between minimum and maximum value after scaling with m_heightNormalizer - m_yAdjustment = 2.0f - ((limits.second - limits.first) / m_heightNormalizer); - //qDebug() << m_yAdjustment; -} - -void Maps3DController::calculateTranslation(MapRenderItem &item) -{ - // We need to convert position (which is in coordinates), to translation (which has origin in the center and is scaled) - // -> move pos(center, center) to trans(0, 0) and pos(0, 0) to trans(left, top) - GLfloat xTrans = 2.0f * (item.mapPosition().x() - (m_areaSize.width() / 2.0f)) - / m_scaleFactor; - GLfloat zTrans = 2.0f * (item.mapPosition().y() - (m_areaSize.height() / 2.0f)) - / m_scaleFactor; - //qDebug() << "x, y" << item.mapPosition().x() << item.mapPosition().y(); - item.setTranslation(QVector3D(xTrans, 0.0f, zTrans + zComp)); - //qDebug() << item.translation(); -} - -Maps3DController::SelectionType Maps3DController::isSelected(GLint bar, const QVector3D &selection) -{ - GLubyte barIdxRed = 0; - GLubyte barIdxGreen = 0; - GLubyte barIdxBlue = 0; - //static QVector3D prevSel = selection; // TODO: For debugging - SelectionType isSelectedType = SelectionNone; - - if (selection == skipColor) - return isSelectedType; // skip window - - if (bar <= 255) { - barIdxRed = bar; - } else if (bar <= 65535) { - barIdxGreen = bar / 256; - barIdxRed = bar % 256; - } else { - barIdxBlue = bar / 65535; - barIdxGreen = bar % 65535; - barIdxRed = bar % 256; - } - - QVector3D current = QVector3D(barIdxRed, barIdxGreen, barIdxBlue); - - // TODO: For debugging - //if (selection != prevSel) { - // qDebug() << selection.x() << selection .y() << selection.z(); - // prevSel = selection; - //} - - if (current == selection) - isSelectedType = SelectionBar; - - return isSelectedType; -} - -bool Maps3DController::isValid(const MapRenderItem &item) -{ - bool retval = true; - if (item.value() < 0) { - qCritical("Data item value out of range"); - retval = false; - } else if (item.mapPosition().x() < 0 || item.mapPosition().x() > m_areaSize.width()) { - qCritical("Data item x position out of range"); - retval = false; - } else if (item.mapPosition().y() < 0 || item.mapPosition().y() > m_areaSize.height()) { - qCritical("Data item y position out of range"); - retval = false; - } - return retval; -} - -void Maps3DController::setDataProxy(QMapDataProxy *proxy) -{ - delete m_data; - m_data = proxy; - - QObject::connect(m_data, &QMapDataProxy::arrayReset, this, &Maps3DController::handleArrayReset); - QObject::connect(m_data, &QMapDataProxy::itemsAdded, this, &Maps3DController::handleItemsAdded); - QObject::connect(m_data, &QMapDataProxy::itemsChanged, this, &Maps3DController::handleItemsChanged); - QObject::connect(m_data, &QMapDataProxy::itemsRemoved, this, &Maps3DController::handleItemsRemoved); - QObject::connect(m_data, &QMapDataProxy::itemsInserted, this, &Maps3DController::handleItemsInserted); - - // emit something? Renderer might be interested? -} - -QMapDataProxy *Maps3DController::dataProxy() -{ - return m_data; -} - -void Maps3DController::handleLimitChange() -{ - QPair<GLfloat, GLfloat> limits = m_data->dptr()->limitValues(); - m_heightNormalizer = qMax(qAbs(limits.second), qAbs(limits.first)); - calculateHeightAdjustment(limits); - - //emit limitsChanged(limits); -} - -void Maps3DController::handleArrayReset() -{ - handleLimitChange(); - m_valuesDirty = true; -} - -void Maps3DController::handleItemsAdded(int startIndex, int count) -{ - Q_UNUSED(startIndex) - Q_UNUSED(count) - // TODO should dirty only affected values? - handleLimitChange(); - m_valuesDirty = true; -} - -void Maps3DController::handleItemsChanged(int startIndex, int count) -{ - Q_UNUSED(startIndex) - Q_UNUSED(count) - // TODO should dirty only affected values? - handleLimitChange(); - m_valuesDirty = true; -} - -void Maps3DController::handleItemsRemoved(int startIndex, int count) -{ - Q_UNUSED(startIndex) - Q_UNUSED(count) - // TODO should dirty only affected values? - handleLimitChange(); - m_valuesDirty = true; -} - -void Maps3DController::handleItemsInserted(int startIndex, int count) -{ - Q_UNUSED(startIndex) - Q_UNUSED(count) - // TODO should dirty only affected values? - handleLimitChange(); - m_valuesDirty = true; -} - -QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/engine/maps3dcontroller_p.h b/src/datavis3d/engine/maps3dcontroller_p.h deleted file mode 100644 index d0c2e74e..00000000 --- a/src/datavis3d/engine/maps3dcontroller_p.h +++ /dev/null @@ -1,253 +0,0 @@ -/**************************************************************************** -** -** 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 QtDataVis3D 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 QtDataVis3D 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 MAPS3DCONTROLLER_P_H -#define MAPS3DCONTROLLER_P_H - -#include "datavis3dglobal_p.h" -#include "q3dmaps.h" -#include "maprenderitem_p.h" -#include <QOpenGLFunctions> -#include <QFont> - -//#define DISPLAY_RENDER_SPEED - -class QPoint; -class QSizeF; - -QT_DATAVIS3D_BEGIN_NAMESPACE - -class ShaderHelper; -class ObjectHelper; -class TextureHelper; -class Theme; -class Drawer; -class Maps3DRenderer; -class CameraHelper; -class QMapDataProxy; - -class QT_DATAVIS3D_EXPORT Maps3DController : public QObject, public QOpenGLFunctions -{ - Q_OBJECT -public: - enum SelectionType { - SelectionNone = 0, - SelectionBar, - SelectionRow, - SelectionColumn - }; - - enum MousePressType { - MouseNone = 0, - MouseOnScene, - MouseOnOverview, - MouseOnZoom, - MouseRotating, - MouseOnPinch - }; - -public: - Maps3DController(const QRect &rect); - ~Maps3DController(); - - void initializeOpenGL(); - virtual void synchDataToRenderer(); - void render(const GLuint defaultFboHandle = 0); - - // bar specifications; base thickness in x, y and z, enum to indicate which direction is increased with value - // TODO: Start using thickness also in adjustment direction; use it as a relative value. - // For example, in AdjustAll mode setting thickness to (0.1f, 1.0f, 0.5f) would apply value to - // x at 10%, y at 100% and z at 50%. If a dimension is not included, given thickness states its absolute value. - void setBarSpecs(const QVector3D &thickness = QVector3D(1.0f, 1.0f, 1.0f), - Q3DMaps::AdjustmentDirection direction = Q3DMaps::AdjustHeight); - - // bar type; bars (=cubes), pyramids, cones, cylinders, balls, etc. - void setBarType(QDataVis::MeshStyle style, bool smooth = false); - - // override bar type with own mesh - void setMeshFileName(const QString &objFileName); - - // Select preset camera placement - void setCameraPreset(QDataVis::CameraPreset preset); - - // Set camera rotation if you don't want to use the presets (in horizontal (-180...180) and - // vertical (0...90) angles and distance in percentage (10...500)) - void setCameraPosition(GLfloat horizontal, GLfloat vertical, GLint distance = 100); - - // Set theme (bar colors, shaders, window color, background colors, light intensity and text colors are affected) - void setTheme(QDataVis::ColorTheme theme); - - // Set color if you don't want to use themes. Set uniform to false if you want the (height) color to change from bottom to top - void setBarColor(QColor baseColor, QColor heightColor, bool uniform = true); - - // Set area specs - void setAreaSpecs(const QRect &areaRect, const QImage &image); - - // Set area image - void setImage(const QImage &image); - - // TODO: light placement API - - // Change selection mode; single bar, bar and row, bar and column, or all - void setSelectionMode(QDataVis::SelectionMode mode); - QDataVis::SelectionMode selectionMode(); - - // Font size adjustment - void setFontSize(float fontsize); - float fontSize(); - - // Set font - void setFont(const QFont &font); - QFont font(); - - // Label transparency adjustment - void setLabelTransparency(QDataVis::LabelTransparency transparency); - QDataVis::LabelTransparency labelTransparency(); - - // Adjust shadow quality - QDataVis::ShadowQuality setShadowQuality(QDataVis::ShadowQuality quality); - QDataVis::ShadowQuality shadowQuality(); - - // Size - const QSize size(); - const QRect boundingRect(); - void setBoundingRect(const QRect boundingRect); - void setWidth(const int width); - int width(); - void setHeight(const int height); - int height(); - void setX(const int x); - int x(); - void setY(const int y); - int y(); - -#if defined(Q_OS_ANDROID) - void mouseDoubleClickEvent(QMouseEvent *event); - void touchEvent(QTouchEvent *event); -#endif - void mousePressEvent(QMouseEvent *event, const QPoint &mousePos); - void mouseReleaseEvent(QMouseEvent *event, const QPoint &mousePos); - void mouseMoveEvent(QMouseEvent *event, const QPoint &mousePos); - void wheelEvent(QWheelEvent *event); - void resizeNotify(); - - void loadBarMesh(); - void loadBackgroundMesh(); - void loadGridLineMesh(); - void loadLabelMesh(); - void initShaders(const QString &vertexShader, const QString &fragmentShader); - void initSelectionShader(); - void initBackgroundShaders(const QString &vertexShader, const QString &fragmentShader); - void initLabelShaders(const QString &vertexShader, const QString &fragmentShader); - void initSelectionBuffer(); -#if !defined(QT_OPENGL_ES_2) - void initDepthShader(); - void initDepthBuffer(); -#endif - void updateTextures(); - void calculateSceneScalingFactors(const QRect &areaRect); - void calculateHeightAdjustment(const QPair<GLfloat, GLfloat> &limits); - void calculateTranslation(MapRenderItem &item); - SelectionType isSelected(GLint bar, const QVector3D &selection); - bool isValid(const MapRenderItem &item); - - // Sets the data proxy. Assumes ownership of the data proxy. Deletes old proxy. - void setDataProxy(QMapDataProxy *proxy); - QMapDataProxy *dataProxy(); - - void handleLimitChange(); - -public slots: - void handleArrayReset(); - void handleItemsAdded(int startIndex, int count); - void handleItemsChanged(int startIndex, int count); - void handleItemsRemoved(int startIndex, int count); - void handleItemsInserted(int startIndex, int count); - -private: - void drawScene(const GLuint defaultFboHandle); - - Maps3DRenderer *m_renderer; - CameraHelper *m_camera; - - ShaderHelper *m_barShader; - ShaderHelper *m_depthShader; - ShaderHelper *m_selectionShader; - ShaderHelper *m_backgroundShader; - ShaderHelper *m_labelShader; - ObjectHelper *m_barObj; - ObjectHelper *m_backgroundObj; - ObjectHelper *m_gridLineObj; - ObjectHelper *m_labelObj; - QString m_objFile; - MousePressType m_mousePressed; - QPoint m_mousePos; - GLint m_zoomLevel; - GLfloat m_autoScaleAdjustment; - GLfloat m_horizontalRotation; - GLfloat m_verticalRotation; - QVector3D m_barThickness; - GLfloat m_heightNormalizer; - GLfloat m_yAdjustment; - GLfloat m_scaleFactor; - Theme *m_theme; - bool m_isInitialized; - QDataVis::SelectionMode m_selectionMode; - BarRenderItem *m_selectedBar; // points to renderitem array - BarRenderItem *m_previouslySelectedBar; // points to renderitem array - QString m_axisLabelX; - QString m_axisLabelZ; - QString m_axisLabelY; - QRect m_sceneViewPort; - QRect m_zoomViewPort; - bool m_zoomActivated; - TextureHelper *m_textureHelper; - QDataVis::LabelTransparency m_labelTransparency; - QFont m_font; - Drawer *m_drawer; - QSizeF m_areaSize; - GLuint m_bgrTexture; - GLuint m_depthTexture; - GLuint m_selectionTexture; - GLuint m_depthFrameBuffer; - GLuint m_selectionFrameBuffer; - GLuint m_selectionDepthBuffer; - bool m_updateLabels; - Q3DMaps::AdjustmentDirection m_adjustDirection; - QDataVis::ShadowQuality m_shadowQuality; - GLfloat m_shadowQualityToShader; - bool m_bgrHasAlpha; - QRect m_boundingRect; - QMapDataProxy *m_data; - bool m_valuesDirty; - MapRenderItemArray m_renderItemArray; -}; - -QT_DATAVIS3D_END_NAMESPACE - -#endif diff --git a/src/datavis3d/engine/maps3drenderer.cpp b/src/datavis3d/engine/maps3drenderer.cpp deleted file mode 100644 index c05f2f51..00000000 --- a/src/datavis3d/engine/maps3drenderer.cpp +++ /dev/null @@ -1,74 +0,0 @@ -/**************************************************************************** -** -** 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 QtDataVis3D 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 "maps3dcontroller_p.h" -#include "maps3drenderer_p.h" -#include "camerahelper_p.h" -#include "shaderhelper_p.h" -#include "objecthelper_p.h" -#include "texturehelper_p.h" -#include "theme_p.h" -#include "utils_p.h" -#include "drawer_p.h" - -#include <QOpenGLFunctions> -#include <QMatrix4x4> -#include <QOpenGLPaintDevice> -#include <QPainter> -#include <QScreen> -#include <QMouseEvent> - -#include <qmath.h> - -#include <QDebug> - -//#define DISPLAY_RENDER_SPEED - -// Uncommenting this draws the shadow map with wider FOV than scene itself, making the light -// seem to be closer to scene than it actually is. This way shadows look slightly better (to me anyway) -#define USE_WIDER_SHADOWS - -// You can verify that depth buffer drawing works correctly by uncommenting this. -// You should see the scene from where the light is -//#define SHOW_DEPTH_TEXTURE_SCENE - -#ifdef DISPLAY_RENDER_SPEED -#include <QTime> -#endif - -QT_DATAVIS3D_BEGIN_NAMESPACE - -//#define DISPLAY_FULL_DATA_ON_SELECTION // Append selection value text with row and column labels - -Maps3DRenderer::Maps3DRenderer(Maps3DController *controller) : QObject(controller) -{ -} - -Maps3DRenderer::~Maps3DRenderer() -{ -} - -void Maps3DRenderer::render(CameraHelper *camera, const GLuint defaultFboHandle) -{ - Q_UNUSED(camera) - Q_UNUSED(defaultFboHandle) - // TODO: Implement -} - - -QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/engine/maps3drenderer_p.h b/src/datavis3d/engine/maps3drenderer_p.h deleted file mode 100644 index 89054e83..00000000 --- a/src/datavis3d/engine/maps3drenderer_p.h +++ /dev/null @@ -1,53 +0,0 @@ -/**************************************************************************** -** -** 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 QtDataVis3D 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 QtDataVis3D 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 MAPS3DRENDERER_P_H -#define MAPS3DRENDERER_P_H - -#include <QOpenGLFunctions> - -#include "datavis3dglobal_p.h" -#include "camerahelper_p.h" - -QT_DATAVIS3D_BEGIN_NAMESPACE - -class Maps3DController; - -class QT_DATAVIS3D_EXPORT Maps3DRenderer : public QObject, public QOpenGLFunctions -{ - -public: - explicit Maps3DRenderer(Maps3DController *controller); - ~Maps3DRenderer(); - - void render(CameraHelper *camera, const GLuint defaultFboHandle); -}; - -QT_DATAVIS3D_END_NAMESPACE - -#endif diff --git a/src/datavis3d/engine/q3dbars.cpp b/src/datavis3d/engine/q3dbars.cpp deleted file mode 100644 index bd9f9f09..00000000 --- a/src/datavis3d/engine/q3dbars.cpp +++ /dev/null @@ -1,487 +0,0 @@ -/**************************************************************************** -** -** 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 QtDataVis3D 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 "q3dbars.h" -#include "q3dbars_p.h" -#include "bars3dcontroller_p.h" -#include "qvalueaxis.h" - -#include <QMouseEvent> - -#include <QDebug> - -QT_DATAVIS3D_BEGIN_NAMESPACE - -/*! - * \class Q3DBars - * \inmodule QtDataVis3D - * \brief The Q3DBars class provides methods for rendering 3D bar graphs. - * \since 1.0.0 - * - * This class enables developers to render bar graphs in 3D and to view them by rotating the scene - * freely. Rotation is done by holding down the right mouse button and moving the mouse. Zooming - * is done by mouse wheel. Selection, if enabled, is done by left mouse button. The scene can be - * reset to default camera view by clicking mouse wheel. In touch devices rotation is done - * by tap-and-move, selection by tap-and-hold and zoom by pinch. - * - * Methods are provided for changing bar types, themes, bar selection modes and so on. See the - * methods for more detailed descriptions. - * - * \section1 How to construct a minimal Q3DBars chart - * - * After constructing Q3DBars, you need to set up sample space using setupSampleSpace(). Let's - * set the sample space to 5 rows and 5 columns: - * - * \snippet doc_src_q3dbars_construction.cpp 0 - * - * Now Q3DBars is ready to receive data to be rendered. Add one row of 5 floats into the data - * set: - * - * \snippet doc_src_q3dbars_construction.cpp 1 - * - * \note We set the sample space to 5 x 5, but we are inserting only one row of data. This is ok, - * the rest of the rows will just be blank. - * - * Finally you will need to set it visible: - * - * \snippet doc_src_q3dbars_construction.cpp 2 - * - * The complete code needed to create and display this chart is: - * - * \snippet doc_src_q3dbars_construction.cpp 3 - * - * And this is what those few lines of code produce: - * - * \image q3dbars-minimal.png - * - * The scene can be rotated and zoomed into, but no other interaction is included in this minimal - * code example. You can learn more by familiarizing yourself with the examples provided, like - * the \l{Rainfall Example} or the \l{Widget Example}. - * - * \sa Q3DMaps, {Qt Data Visualization 3D C++ Classes} - */ - -/*! - * Constructs a new 3D bar window. - */ -Q3DBars::Q3DBars() - : d_ptr(new Q3DBarsPrivate(this, geometry())) -{ - d_ptr->m_shared->initializeOpenGL(); - QObject::connect(d_ptr->m_shared, &Abstract3DController::shadowQualityChanged, this, - &Q3DBars::handleShadowQualityUpdate); -} - -/*! - * Destroys the 3d bar window. - */ -Q3DBars::~Q3DBars() -{ -} - -/*! - * \internal - */ -void Q3DBars::render() -{ - d_ptr->m_shared->synchDataToRenderer(); - d_ptr->m_shared->render(); -} - -void Q3DBars::handleShadowQualityUpdate(QDataVis::ShadowQuality quality) -{ - emit shadowQualityChanged(quality); -} - -#if defined(Q_OS_ANDROID) -/*! - * \internal - */ -void Q3DBars::mouseDoubleClickEvent(QMouseEvent *event) -{ - d_ptr->m_shared->mouseDoubleClickEvent(event); -} - -/*! - * \internal - */ -void Q3DBars::touchEvent(QTouchEvent *event) -{ - d_ptr->m_shared->touchEvent(event); -} -#endif - -/*! - * \internal - */ -void Q3DBars::mousePressEvent(QMouseEvent *event) -{ - d_ptr->m_shared->mousePressEvent(event, event->pos()); -} - -/*! - * \internal - */ -void Q3DBars::mouseReleaseEvent(QMouseEvent *event) -{ - d_ptr->m_shared->mouseReleaseEvent(event, event->pos()); -} - -/*! - * \internal - */ -void Q3DBars::mouseMoveEvent(QMouseEvent *event) -{ - d_ptr->m_shared->mouseMoveEvent(event, event->pos()); -} - -/*! - * \internal - */ -void Q3DBars::wheelEvent(QWheelEvent *event) -{ - d_ptr->m_shared->wheelEvent(event); -} - -/*! - * \internal - */ -void Q3DBars::resizeEvent(QResizeEvent *event) -{ - Q_UNUSED(event); - d_ptr->m_shared->setSize(width(), height()); -} - -// TODO: Document -// Size -void Q3DBars::setWidth(const int width) -{ - d_ptr->m_shared->setWidth(width); - QWindow::setWidth(width); -} - -void Q3DBars::setHeight(const int height) -{ - d_ptr->m_shared->setHeight(height); - QWindow::setHeight(height); -} - -/*! - * \a thickness Thickness of a bar in x and z axes. - * - * \a spacing Spacing between bars in x and z axes. If relative -flag is true, value of 0.0f - * means the bars are side-to-side and for example 1.0f means there is one thickness in between the - * bars. - * - * \a relative A flag to indicate if spacing is meant to be absolute or relative. \c true by - * default. - * - * Sets bar specifications. Bar thickness is relative, as scene is automatically scaled to fit into - * the view. - */ -void Q3DBars::setBarSpecs(QSizeF thickness, QSizeF spacing, bool relative) -{ - d_ptr->m_shared->setBarSpecs(thickness, spacing, relative); -} - -/*! - * \a style One of the values in \c MeshStyle. \c Bars by default. - * - * \a smooth A flag to set shading to smooth. \c false by default. - * - * Sets the bar type to one of the supplied ones. - * - * \sa setMeshFileName() - */ -void Q3DBars::setBarType(QDataVis::MeshStyle style, bool smooth) -{ - d_ptr->m_shared->setBarType(style, smooth); -} - -/*! - * \a samplesRow How many rows of data there will be. - * - * \a samplesColumn How many items there are per row. - * - * Set up sample space. This must be called to initialize the sample space before adding data to the - * Q3DBars. - * - * \sa addDataRow(), addDataSet() - */ -void Q3DBars::setupSampleSpace(int samplesRow, int samplesColumn) -{ - d_ptr->m_shared->setupSampleSpace(samplesRow, samplesColumn); -} - -QSize Q3DBars::sampleSpace() const -{ - return QSize(d_ptr->m_shared->rowCount(), d_ptr->m_shared->columnCount()); -} - -/*! - * \a preset Move camera to a predefined position from \c QDataVis::CameraPreset. - * - * Moves camera to a predefined position. - */ -void Q3DBars::setCameraPreset(QDataVis::CameraPreset preset) -{ - d_ptr->m_shared->setCameraPreset(preset); -} - -/*! - * \a horizontal Horizontal angle for camera. - * - * \a vertical Vertical angle for camera. - * - * \a distance Distance from the center. \c 100 by default. - * - * Move camera to a wanted position based on horizontal and veritcal angles. Angles are limited - * to -180...180 in horizontal direction and either -90...90 or 0...90 in vertical, depending - * on data values. Negative vertical angles are allowed only if there are negative bar values. - * Distance is adjustable between 10 and 500. - */ -void Q3DBars::setCameraPosition(qreal horizontal, qreal vertical, int distance) -{ - d_ptr->m_shared->setCameraPosition(GLfloat(horizontal), GLfloat(vertical), GLint(distance)); -} - -/*! - * \a theme Apply a predefined theme from \c QDataVis::ColorTheme. - * - * Sets a predefined theme. Theme affects bar colors, label colors, text color, background color, - * window color and grid color. Lighting is also adjusted by themes. - */ -void Q3DBars::setTheme(QDataVis::ColorTheme theme) -{ - d_ptr->m_shared->setColorTheme(theme); -} - -/*! - * \a baseColor The base color of a bar. If all other colors are black, this sets the final color of - * the bar. - * - * \a heightColor This color is added to the bar based on its height. The higher the bar, the more - * prominent this color becomes. Setting this black keeps the color unchanged regardless of height. - * - * \a depthColor This color becomes more prominent the further away from the first row the bar is. - * Setting this black keeps bars the same color regardless of "depth" in the set. - * - * \a uniform A flag to define if color needs to be uniform throughout bar's length, or will the - * colors be applied by height. \c true by default. - * - * Set bar color using your own colors. This overrides colors from theme. - */ -void Q3DBars::setBarColor(QColor baseColor, QColor heightColor, QColor depthColor, bool uniform) -{ - d_ptr->m_shared->setObjectColor(baseColor, heightColor, depthColor, uniform); -} - -/*! - * \property Q3DBars::selectionMode - * - * \a mode Set bar selection mode from \c QDataVis::SelectionMode. \c ModeItem by default. - * - * Sets bar selection mode to be used. - */ -void Q3DBars::setSelectionMode(QDataVis::SelectionMode mode) -{ - d_ptr->m_shared->setSelectionMode(mode); -} - -QDataVis::SelectionMode Q3DBars::selectionMode() const -{ - return d_ptr->m_shared->selectionMode(); -} - -/*! - * \property Q3DBars::windowTitle - * - * \a title QString label to be used as window title. - * - * Sets the window title. The default is application executable name. - */ -void Q3DBars::setWindowTitle(const QString &title) -{ - setTitle(title); -} - -QString Q3DBars::windowTitle() const -{ - return title(); -} - -/*! - * \a objFileName File name of a mesh object. Object needs to be in Wavefront obj format - * and include vertices, normals and UVs. It also needs to be in triangles. - * - * Override bar type with an object mesh. \sa setBarType() - */ -void Q3DBars::setMeshFileName(const QString &objFileName) -{ - d_ptr->m_shared->setMeshFileName(objFileName); -} - -/*! - * \property Q3DBars::fontSize - * - * \a fontsize Size of the font. - * - * Sets font size. - */ -void Q3DBars::setFontSize(float fontsize) -{ - d_ptr->m_shared->setFontSize(fontsize); -} - -float Q3DBars::fontSize() -{ - return d_ptr->m_shared->fontSize(); -} - -/*! - * \property Q3DBars::font - * - * \a font QFont to be used for labels. \c Arial by default. - * - * Sets the font for labels. - */ -void Q3DBars::setFont(const QFont &font) -{ - d_ptr->m_shared->setFont(font); -} - -QFont Q3DBars::font() const -{ - return d_ptr->m_shared->font(); -} - -/*! - * \property Q3DBars::labelTransparency - * - * \a transparency Transparency level of labels from \c QDataVis::LabelTransparency. - * \c TransparencyFromTheme by default. - * - * Sets label transparency. - */ -void Q3DBars::setLabelTransparency(QDataVis::LabelTransparency transparency) -{ - d_ptr->m_shared->setLabelTransparency(transparency); -} - -QDataVis::LabelTransparency Q3DBars::labelTransparency() const -{ - return d_ptr->m_shared->labelTransparency(); -} - -/*! - * \property Q3DBars::gridVisible - * - * \a visible Flag to enable or disable grid. \c true by default. - * - * Sets grid drawing on or off. - */ -void Q3DBars::setGridVisible(bool visible) -{ - d_ptr->m_shared->setGridEnabled(visible); -} - -bool Q3DBars::isGridVisible() const -{ - return d_ptr->m_shared->gridEnabled(); -} - -/*! - * \property Q3DBars::backgroundVisible - * - * \a visible Flag to enable or disable background. \c true by default. - * - * Sets backround rendering on or off. - */ -void Q3DBars::setBackgroundVisible(bool visible) -{ - d_ptr->m_shared->setBackgroundEnabled(visible); -} - -bool Q3DBars::isBackgroundVisible() const -{ - return d_ptr->m_shared->backgroundEnabled(); -} - -/*! - * \property Q3DBars::shadowQuality - * - * \a quality Shadow quality from \c QDataVis::ShadowQuality. \c ShadowLow by default. - * - * Sets shadow quality. If setting QDataVis::ShadowQuality of a certain level fails, a level is lowered - * until it is successful and shadowQualityChanged signal is emitted for each time the change is done. - */ -void Q3DBars::setShadowQuality(QDataVis::ShadowQuality quality) -{ - return d_ptr->m_shared->setShadowQuality(quality); -} - -QDataVis::ShadowQuality Q3DBars::shadowQuality() const -{ - return d_ptr->m_shared->shadowQuality(); -} - -QCategoryAxis *Q3DBars::rowAxis() -{ - return reinterpret_cast<QCategoryAxis *>(d_ptr->m_shared->axisX()); -} - -QCategoryAxis *Q3DBars::columnAxis() -{ - return reinterpret_cast<QCategoryAxis *>(d_ptr->m_shared->axisZ()); -} - -void Q3DBars::setValueAxis(QValueAxis *axis) -{ - Q_ASSERT(axis); - - return d_ptr->m_shared->setAxisY(axis); -} - -QValueAxis *Q3DBars::valueAxis() -{ - return static_cast<QValueAxis *>(d_ptr->m_shared->axisY()); -} - -void Q3DBars::setDataProxy(QBarDataProxy *proxy) -{ - d_ptr->m_shared->setDataProxy(proxy); -} - -QBarDataProxy *Q3DBars::dataProxy() -{ - return d_ptr->m_shared->dataProxy(); -} - -Q3DBarsPrivate::Q3DBarsPrivate(Q3DBars *q, QRect rect) - : q_ptr(q), - m_shared(new Bars3dController(rect)) -{ -} - -Q3DBarsPrivate::~Q3DBarsPrivate() -{ - qDebug() << "Destroying Q3DBarsPrivate"; - delete m_shared; -} - -QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/engine/q3dbars.h b/src/datavis3d/engine/q3dbars.h deleted file mode 100644 index a0eb9cb5..00000000 --- a/src/datavis3d/engine/q3dbars.h +++ /dev/null @@ -1,163 +0,0 @@ -/**************************************************************************** -** -** 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 QtDataVis3D 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 Q3DBARS_H -#define Q3DBARS_H - -#include <QtDataVis3D/qdatavis3denums.h> -#include <QtDataVis3D/q3dwindow.h> -#include <QFont> - -QT_DATAVIS3D_BEGIN_NAMESPACE - -class Q3DBarsPrivate; -class QCategoryAxis; -class QValueAxis; -class QBarDataProxy; - -class QT_DATAVIS3D_EXPORT Q3DBars : public Q3DWindow -{ - Q_OBJECT - Q_PROPERTY(QtDataVis3D::QDataVis::SelectionMode selectionMode READ selectionMode WRITE setSelectionMode) - Q_PROPERTY(QtDataVis3D::QDataVis::LabelTransparency labelTransparency READ labelTransparency WRITE setLabelTransparency) - Q_PROPERTY(QtDataVis3D::QDataVis::ShadowQuality shadowQuality READ shadowQuality WRITE setShadowQuality) - Q_PROPERTY(QString windowTitle READ windowTitle WRITE setWindowTitle) - Q_PROPERTY(QFont font READ font WRITE setFont) - Q_PROPERTY(float fontSize READ fontSize WRITE setFontSize) - Q_PROPERTY(bool gridVisible READ isGridVisible WRITE setGridVisible) - Q_PROPERTY(bool backgroundVisible READ isBackgroundVisible WRITE setBackgroundVisible) - Q_ENUMS(QtDataVis3D::QDataVis::SelectionMode) - Q_ENUMS(QtDataVis3D::QDataVis::ShadowQuality) - Q_ENUMS(QtDataVis3D::QDataVis::LabelTransparency) - -public: - explicit Q3DBars(); - ~Q3DBars(); - - // bar thickness, spacing between bars, and is spacing relative to thickness or absolute - // y -component sets the thickness/spacing of z -direction - // With relative 0.0f means side-to-side, 1.0f = one thickness in between - void setBarSpecs(QSizeF thickness = QSizeF(1.0f, 1.0f), - QSizeF spacing = QSizeF(1.0f, 1.0f), - bool relative = true); - - // bar type; bars (=cubes), pyramids, cones, cylinders, etc. - void setBarType(QDataVis::MeshStyle style, bool smooth = false); - - // how many samples per row and column, and names for axes - // TODO: This defines the data window, needs additional parameters startRow, startColumn - void setupSampleSpace(int samplesRow, int samplesColumn); - QSize sampleSpace() const; // TODO: Return QRect once data window properly implemented? - - // Select preset camera placement - void setCameraPreset(QDataVis::CameraPreset preset); - - // Set camera rotation if you don't want to use the presets (in horizontal (-180...180) and - // vertical (0...90) (or (-90...90) if there are negative values) angles and distance in - // percentage (10...500)) - void setCameraPosition(qreal horizontal, qreal vertical, int distance = 100); - - // Set theme (bar colors, shaders, window color, background colors, light intensity and text - // colors are affected) - void setTheme(QDataVis::ColorTheme theme); - - // Set color if you don't want to use themes. Set uniform to false if you want the (height) - // color to change from bottom to top - void setBarColor(QColor baseColor, QColor heightColor, QColor depthColor, - bool uniform = true); - - // override bar type with own mesh - void setMeshFileName(const QString &objFileName); - // TODO: light placement API - - // Change selection mode; single bar, bar and row, bar and column, or all - void setSelectionMode(QDataVis::SelectionMode mode); - QDataVis::SelectionMode selectionMode() const; - - // Set window title - void setWindowTitle(const QString &title); - QString windowTitle() const; - - // Font size adjustment - void setFontSize(float fontsize); - float fontSize(); - - // Set font - void setFont(const QFont &font); - QFont font() const; - - // Label transparency adjustment - void setLabelTransparency(QDataVis::LabelTransparency transparency); - QDataVis::LabelTransparency labelTransparency() const; - - // Enable or disable background grid - void setGridVisible(bool visible); - bool isGridVisible() const; - - // Size - void setWidth(const int width); - void setHeight(const int height); - - // Enable or disable background mesh - void setBackgroundVisible(bool visible); - bool isBackgroundVisible() const; - - // Adjust shadow quality - void setShadowQuality(QDataVis::ShadowQuality quality); - QDataVis::ShadowQuality shadowQuality() const; - - // Axes - row & column axes are fixed to category axes, value axis can be - // customized. - QCategoryAxis *rowAxis(); - QCategoryAxis *columnAxis(); - void setValueAxis(QValueAxis *axis); - QValueAxis *valueAxis(); - - // Sets the data proxy. Assumes ownership of the data proxy. Deletes old proxy. - void setDataProxy(QBarDataProxy *proxy); - QBarDataProxy *dataProxy(); - -public slots: - // Used to detect when shadow quality changes autonomously due to e.g. resizing. - void handleShadowQualityUpdate(QDataVis::ShadowQuality quality); - -signals: - // Signals shadow quality changes. - void shadowQualityChanged(QDataVis::ShadowQuality quality); - -protected: - void render(); - -#if defined(Q_OS_ANDROID) - void mouseDoubleClickEvent(QMouseEvent *event); - void touchEvent(QTouchEvent *event); -#endif - void mousePressEvent(QMouseEvent *event); - void mouseReleaseEvent(QMouseEvent *event); - void mouseMoveEvent(QMouseEvent *event); - void wheelEvent(QWheelEvent *event); - void resizeEvent(QResizeEvent *event); - -private: - QScopedPointer<Q3DBarsPrivate> d_ptr; - Q_DISABLE_COPY(Q3DBars) -}; - -QT_DATAVIS3D_END_NAMESPACE - -#endif diff --git a/src/datavis3d/engine/q3dmaps.cpp b/src/datavis3d/engine/q3dmaps.cpp deleted file mode 100644 index ffa5ed1b..00000000 --- a/src/datavis3d/engine/q3dmaps.cpp +++ /dev/null @@ -1,270 +0,0 @@ -/**************************************************************************** -** -** 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 QtDataVis3D 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 "q3dmaps.h" -#include "q3dmaps_p.h" -#include "maps3dcontroller_p.h" - -#include <QMouseEvent> - -#include <QDebug> - -QT_DATAVIS3D_BEGIN_NAMESPACE - -/*! - * \class Q3DMaps - * \inmodule QtDataVis3D - * \brief The Q3DMaps class provides methods for rendering 3D bars on maps or other planes. - * \since 1.0.0 - * - * This class enables developers to render bars or objects on maps or other planes in 3D and to - * view them by rotating the scene freely. Methods are provided for changing object types, themes - * and so on. - * - * See methods themselves for more complete description. - * - * \sa Q3DBars, {Qt Data Visualization 3D C++ Classes} - */ - -/*! - * Constructs Q3DMaps. - */ -Q3DMaps::Q3DMaps() - : d_ptr(new Q3DMapsPrivate(this, geometry())) -{ - d_ptr->m_shared->initializeOpenGL(); -} - -/*! - * Destructs Q3DMaps. - */ -Q3DMaps::~Q3DMaps() -{ -} - -/*! - * \internal - */ -void Q3DMaps::render() -{ - d_ptr->m_shared->render(); -} - -#if defined(Q_OS_ANDROID) -/*! - * \internal - */ -void Q3DMaps::mouseDoubleClickEvent(QMouseEvent *event) -{ - d_ptr->m_shared->mouseDoubleClickEvent(event); -} - -/*! - * \internal - */ -void Q3DMaps::touchEvent(QTouchEvent *event) -{ - d_ptr->m_shared->touchEvent(event); -} -#endif - -/*! - * \internal - */ -void Q3DMaps::mousePressEvent(QMouseEvent *event) -{ - d_ptr->m_shared->mousePressEvent(event, event->pos()); -} - -/*! - * \internal - */ -void Q3DMaps::mouseReleaseEvent(QMouseEvent *event) -{ - d_ptr->m_shared->mouseReleaseEvent(event, event->pos()); -} - -/*! - * \internal - */ -void Q3DMaps::mouseMoveEvent(QMouseEvent *event) -{ - d_ptr->m_shared->mouseMoveEvent(event, event->pos()); -} - -/*! - * \internal - */ -void Q3DMaps::wheelEvent(QWheelEvent *event) -{ - d_ptr->m_shared->wheelEvent(event); -} - -/*! - * \internal - */ -void Q3DMaps::resizeEvent(QResizeEvent *event) -{ - Q_UNUSED(event); - d_ptr->m_shared->setWidth(width()); - d_ptr->m_shared->setHeight(height()); - d_ptr->m_shared->resizeNotify(); -} - -// TODO: Document -// Size -void Q3DMaps::setWidth(const int width) -{ - d_ptr->m_shared->setWidth(width); - QWindow::setWidth(width); -} - -void Q3DMaps::setHeight(const int height) -{ - d_ptr->m_shared->setHeight(height); - QWindow::setHeight(height); -} - -void Q3DMaps::setBarSpecs(const QVector3D &thickness, AdjustmentDirection direction) -{ - d_ptr->m_shared->setBarSpecs(thickness, direction); -} - -void Q3DMaps::setBarType(QDataVis::MeshStyle style, bool smooth) -{ - d_ptr->m_shared->setBarType(style, smooth); -} - -void Q3DMaps::setMeshFileName(const QString &objFileName) -{ - d_ptr->m_shared->setMeshFileName(objFileName); -} - -void Q3DMaps::setCameraPreset(QDataVis::CameraPreset preset) -{ - d_ptr->m_shared->setCameraPreset(preset); -} - -void Q3DMaps::setCameraPosition(GLfloat horizontal, GLfloat vertical, GLint distance) -{ - d_ptr->m_shared->setCameraPosition(horizontal, vertical, distance); -} - -void Q3DMaps::setTheme(QDataVis::ColorTheme theme) -{ - d_ptr->m_shared->setTheme(theme); -} - -void Q3DMaps::setBarColor(QColor baseColor, QColor heightColor, bool uniform) -{ - d_ptr->m_shared->setBarColor(baseColor, heightColor, uniform); -} - -void Q3DMaps::setAreaSpecs(const QRect &areaRect, const QImage &image) -{ - d_ptr->m_shared->setAreaSpecs(areaRect, image); -} - -void Q3DMaps::setImage(const QImage &image) -{ - d_ptr->m_shared->setImage(image); -} - -void Q3DMaps::setSelectionMode(QDataVis::SelectionMode mode) -{ - d_ptr->m_shared->setSelectionMode(mode); -} - -QDataVis::SelectionMode Q3DMaps::selectionMode() const -{ - return d_ptr->m_shared->selectionMode(); -} - -void Q3DMaps::setWindowTitle(const QString &title) -{ - setTitle(title); -} - -QString Q3DMaps::windowTitle() const -{ - return title(); -} - -void Q3DMaps::setFontSize(float fontsize) -{ - d_ptr->m_shared->setFontSize(fontsize); -} - -float Q3DMaps::fontSize() const -{ - return d_ptr->m_shared->fontSize(); -} - -void Q3DMaps::setFont(const QFont &font) -{ - d_ptr->m_shared->setFont(font); -} - -QFont Q3DMaps::font() const -{ - return d_ptr->m_shared->font(); -} - -void Q3DMaps::setLabelTransparency(QDataVis::LabelTransparency transparency) -{ - d_ptr->m_shared->setLabelTransparency(transparency); -} - -QDataVis::LabelTransparency Q3DMaps::labelTransparency() const -{ - return d_ptr->m_shared->labelTransparency(); -} - -QDataVis::ShadowQuality Q3DMaps::setShadowQuality(QDataVis::ShadowQuality quality) -{ - return d_ptr->m_shared->setShadowQuality(quality); -} - -QDataVis::ShadowQuality Q3DMaps::shadowQuality() const -{ - return d_ptr->m_shared->shadowQuality(); -} - -void Q3DMaps::setDataProxy(QMapDataProxy *proxy) -{ - d_ptr->m_shared->setDataProxy(proxy); -} - -QMapDataProxy *Q3DMaps::dataProxy() -{ - return d_ptr->m_shared->dataProxy(); -} - -Q3DMapsPrivate::Q3DMapsPrivate(Q3DMaps *q, const QRect &rect) - : q_ptr(q), - m_shared(new Maps3DController(rect)) -{ -} - -Q3DMapsPrivate::~Q3DMapsPrivate() -{ - qDebug() << "Destroying Q3DMapsPrivate"; - delete m_shared; -} - -QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/engine/q3dmaps.h b/src/datavis3d/engine/q3dmaps.h deleted file mode 100644 index 195b91e0..00000000 --- a/src/datavis3d/engine/q3dmaps.h +++ /dev/null @@ -1,143 +0,0 @@ -/**************************************************************************** -** -** 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 QtDataVis3D 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 Q3DMAPS_H -#define Q3DMAPS_H - -#include <QtDataVis3D/qdatavis3denums.h> -#include <QtDataVis3D/q3dwindow.h> - -#include <QFont> -#include <QVector3D> - -class QImage; -class QRect; - -QT_DATAVIS3D_BEGIN_NAMESPACE - -class Maps3DController; -class Q3DMapsPrivate; -class QMapDataProxy; - -class QT_DATAVIS3D_EXPORT Q3DMaps : public Q3DWindow -{ - Q_OBJECT - Q_PROPERTY(QString windowTitle READ windowTitle WRITE setWindowTitle) - Q_PROPERTY(QFont font READ font WRITE setFont) - Q_PROPERTY(float fontSize READ fontSize WRITE setFontSize) - -public: - - enum AdjustmentDirection { - AdjustHeight = 0, // map value to y - AdjustWidth, // map value to x - AdjustDepth, // map value to z - AdjustRadius, // map value to x and z - AdjustAll // map value to all (x, y, z) - }; - -public: - explicit Q3DMaps(); - ~Q3DMaps(); - - void setWidth(const int width); - void setHeight(const int height); - - // bar specifications; base thickness in x, y and z, enum to indicate which direction is increased with value - // TODO: Start using thickness also in adjustment direction; use it as a relative value. - // For example, in AdjustAll mode setting thickness to (0.1f, 1.0f, 0.5f) would apply value to - // x at 10%, y at 100% and z at 50%. If a dimension is not included, given thickness states its absolute value. - void setBarSpecs(const QVector3D &thickness = QVector3D(1.0f, 1.0f, 1.0f), - AdjustmentDirection direction = AdjustHeight); - - // bar type; bars (=cubes), pyramids, cones, cylinders, balls, etc. - void setBarType(QDataVis::MeshStyle style, bool smooth = false); - - // override bar type with own mesh - void setMeshFileName(const QString &objFileName); - - // Select preset camera placement - void setCameraPreset(QDataVis::CameraPreset preset); - - // Set camera rotation if you don't want to use the presets (in horizontal (-180...180) and - // vertical (0...90) angles and distance in percentage (10...500)) - void setCameraPosition(GLfloat horizontal, GLfloat vertical, GLint distance = 100); - - // Set theme (bar colors, shaders, window color, background colors, light intensity and text colors are affected) - void setTheme(QDataVis::ColorTheme theme); - - // Set color if you don't want to use themes. Set uniform to false if you want the (height) color to change from bottom to top - void setBarColor(QColor baseColor, QColor heightColor, bool uniform = true); - - // Set area specs - void setAreaSpecs(const QRect &areaRect, const QImage &image); - - // Set area image - void setImage(const QImage &image); - - // TODO: light placement API - - // Change selection mode; single bar, bar and row, bar and column, or all - void setSelectionMode(QDataVis::SelectionMode mode); - QDataVis::SelectionMode selectionMode() const; - - // Set window title - void setWindowTitle(const QString &title); - QString windowTitle() const; - - // Font size adjustment - void setFontSize(float fontsize); - float fontSize() const; - - // Set font - void setFont(const QFont &font); - QFont font() const; - - // Label transparency adjustment - void setLabelTransparency(QDataVis::LabelTransparency transparency); - QDataVis::LabelTransparency labelTransparency() const; - - // Adjust shadow quality - QDataVis::ShadowQuality setShadowQuality(QDataVis::ShadowQuality quality); - QDataVis::ShadowQuality shadowQuality() const; - - // Sets the data proxy. Assumes ownership of the data proxy. Deletes old proxy. - void setDataProxy(QMapDataProxy *proxy); - QMapDataProxy *dataProxy(); - -protected: - void render(); - -#if defined(Q_OS_ANDROID) - void mouseDoubleClickEvent(QMouseEvent *event); - void touchEvent(QTouchEvent *event); -#endif - void mousePressEvent(QMouseEvent *event); - void mouseReleaseEvent(QMouseEvent *event); - void mouseMoveEvent(QMouseEvent *event); - void wheelEvent(QWheelEvent *event); - void resizeEvent(QResizeEvent *event); - -private: - QScopedPointer<Q3DMapsPrivate> d_ptr; - Q_DISABLE_COPY(Q3DMaps) -}; - -QT_DATAVIS3D_END_NAMESPACE - -#endif diff --git a/src/datavis3d/engine/q3dscatter.cpp b/src/datavis3d/engine/q3dscatter.cpp deleted file mode 100644 index 73332bdd..00000000 --- a/src/datavis3d/engine/q3dscatter.cpp +++ /dev/null @@ -1,463 +0,0 @@ -/**************************************************************************** -** -** 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 QtDataVis3D 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 "q3dscatter.h" -#include "q3dscatter_p.h" -#include "scatter3dcontroller_p.h" -#include "qvalueaxis.h" - -#include <QMouseEvent> - -#include <QDebug> - -QT_DATAVIS3D_BEGIN_NAMESPACE - -/*! - * \class Q3DScatter - * \inmodule QtDataVis3D - * \brief The Q3DScatter class provides methods for rendering 3D scatter graphs. - * \since 1.0.0 - * - * This class enables developers to render bar graphs in 3D and to view them by rotating the scene - * freely. Rotation is done by holding down the right mouse button and moving the mouse. Zooming - * is done by mouse wheel. Selection, if enabled, is done by left mouse button. The scene can be - * reset to default camera view by clicking mouse wheel. In touch devices rotation is done - * by tap-and-move, selection by tap-and-hold and zoom by pinch. - * - * Methods are provided for changing bar types, themes, bar selection modes and so on. See the - * methods for more detailed descriptions. - * - * \section1 How to construct a minimal Q3DScatter chart - * - * After constructing Q3DScatter, you need to set up sample space using setupSampleSpace(). Let's - * set the sample space to 5 rows and 5 columns: - * - * \snippet doc_src_q3dscatter_construction.cpp 0 - * - * Now Q3DScatter is ready to receive data to be rendered. Add one row of 5 floats into the data - * set: - * - * \snippet doc_src_q3dscatter_construction.cpp 1 - * - * \note We set the sample space to 5 x 5, but we are inserting only one row of data. This is ok, - * the rest of the rows will just be blank. - * - * Finally you will need to set it visible: - * - * \snippet doc_src_q3dscatter_construction.cpp 2 - * - * The complete code needed to create and display this chart is: - * - * \snippet doc_src_q3dscatter_construction.cpp 3 - * - * And this is what those few lines of code produce: - * - * \image q3dscatter-minimal.png - * - * The scene can be rotated and zoomed into, but no other interaction is included in this minimal - * code example. You can learn more by familiarizing yourself with the examples provided, like - * the \l{Rainfall Example} or the \l{Widget Example}. - * - * \sa Q3DMaps, {Qt Data Visualization 3D C++ Classes} - */ - -/*! - * Constructs a new 3D scatter window. - */ -Q3DScatter::Q3DScatter() - : d_ptr(new Q3DScatterPrivate(this, geometry())) -{ - d_ptr->m_shared->initializeOpenGL(); - QObject::connect(d_ptr->m_shared, &Abstract3DController::shadowQualityChanged, this, - &Q3DScatter::handleShadowQualityUpdate); -} - -/*! - * Destroys the 3D scatter window. - */ -Q3DScatter::~Q3DScatter() -{ -} - -/*! - * \internal - */ -void Q3DScatter::render() -{ - d_ptr->m_shared->synchDataToRenderer(); - d_ptr->m_shared->render(); -} - -void Q3DScatter::handleShadowQualityUpdate(QDataVis::ShadowQuality quality) -{ - emit shadowQualityChanged(quality); -} - -#if defined(Q_OS_ANDROID) -/*! - * \internal - */ -void Q3DScatter::mouseDoubleClickEvent(QMouseEvent *event) -{ - d_ptr->m_shared->mouseDoubleClickEvent(event); -} - -/*! - * \internal - */ -void Q3DScatter::touchEvent(QTouchEvent *event) -{ - d_ptr->m_shared->touchEvent(event); -} -#endif - -/*! - * \internal - */ -void Q3DScatter::mousePressEvent(QMouseEvent *event) -{ - d_ptr->m_shared->mousePressEvent(event, event->pos()); -} - -/*! - * \internal - */ -void Q3DScatter::mouseReleaseEvent(QMouseEvent *event) -{ - d_ptr->m_shared->mouseReleaseEvent(event, event->pos()); -} - -/*! - * \internal - */ -void Q3DScatter::mouseMoveEvent(QMouseEvent *event) -{ - d_ptr->m_shared->mouseMoveEvent(event, event->pos()); -} - -/*! - * \internal - */ -void Q3DScatter::wheelEvent(QWheelEvent *event) -{ - d_ptr->m_shared->wheelEvent(event); -} - -/*! - * \internal - */ -void Q3DScatter::resizeEvent(QResizeEvent *event) -{ - Q_UNUSED(event); - d_ptr->m_shared->setSize(width(), height()); -} - -// TODO: Document -// Size -void Q3DScatter::setWidth(const int width) -{ - d_ptr->m_shared->setWidth(width); - QWindow::setWidth(width); -} - -void Q3DScatter::setHeight(const int height) -{ - d_ptr->m_shared->setHeight(height); - QWindow::setHeight(height); -} - -/*! - * \a style One of the values in \c QDataVis::MeshStyle. \c Spheres by default. - * - * \a smooth A flag to set shading to smooth. \c false by default. - * - * Sets the object type to one of the supplied ones. - * - * \sa setMeshFileName() - */ -void Q3DScatter::setObjectType(QDataVis::MeshStyle style, bool smooth) -{ - d_ptr->m_shared->setObjectType(style, smooth); -} - -/*! - * \a preset Move camera to a predefined position from \c QDataVis::CameraPreset. - * - * Moves camera to a predefined position. - */ -void Q3DScatter::setCameraPreset(QDataVis::CameraPreset preset) -{ - d_ptr->m_shared->setCameraPreset(preset); -} - -/*! - * \a horizontal Horizontal angle for camera. - * - * \a vertical Vertical angle for camera. - * - * \a distance Distance from the center. \c 100 by default. - * - * Move camera to a wanted position based on horizontal and veritcal angles. Angles are limited - * to -180...180 in horizontal direction and -90...90 in vertical. - * Distance is adjustable between 10 and 500. - */ -void Q3DScatter::setCameraPosition(qreal horizontal, qreal vertical, int distance) -{ - d_ptr->m_shared->setCameraPosition(GLfloat(horizontal), GLfloat(vertical), GLint(distance)); -} - -/*! - * \a theme Apply a predefined theme from \c QDataVis::ColorTheme. - * - * Sets a predefined theme. Theme affects object colors, label colors, text color, background color, - * window color and grid color. Lighting is also adjusted by themes. - */ -void Q3DScatter::setTheme(QDataVis::ColorTheme theme) -{ - d_ptr->m_shared->setColorTheme(theme); -} - -/*! - * \a baseColor The base color of an object. If all other colors are black, this sets the final - * color of the object. - * - * \a heightColor This color is added to the object based on its y-position. The higher the object, - * the more prominent this color becomes. Setting this black keeps the color unchanged regardless - * of y-position. - * - * \a depthColor This color becomes more prominent the further back in z-position the object is. - * Setting this black keeps objects the same color regardless of "depth" in the set. - * - * \a uniform A flag to define if color needs to be uniform throughout object's length, or will the - * colors be applied by height. \c true by default. - * - * Set object color using your own colors. This overrides colors from theme. - */ -void Q3DScatter::setObjectColor(QColor baseColor, QColor heightColor, QColor depthColor, bool uniform) -{ - d_ptr->m_shared->setObjectColor(baseColor, heightColor, depthColor, uniform); -} - -/*! - * \property Q3DScatter::selectionMode - * - * \a mode Set object selection mode from \c QDataVis::SelectionMode. \c ModeItem by default. - * - * Sets object selection mode to be used. - */ -void Q3DScatter::setSelectionMode(QDataVis::SelectionMode mode) -{ - d_ptr->m_shared->setSelectionMode(mode); -} - -QDataVis::SelectionMode Q3DScatter::selectionMode() const -{ - return d_ptr->m_shared->selectionMode(); -} - -/*! - * \property Q3DScatter::windowTitle - * - * \a title QString label to be used as window title. - * - * Sets the window title. The default is application executable name. - */ -void Q3DScatter::setWindowTitle(const QString &title) -{ - setTitle(title); -} - -QString Q3DScatter::windowTitle() const -{ - return title(); -} - -/*! - * \a objFileName File name of a mesh object. Object needs to be in Wavefront obj format - * and include vertices, normals and UVs. It also needs to be in triangles. - * - * Override object type with an object mesh. \sa setObjectType() - */ -void Q3DScatter::setMeshFileName(const QString &objFileName) -{ - d_ptr->m_shared->setMeshFileName(objFileName); -} - -/*! - * \property Q3DScatter::fontSize - * - * \a fontsize Size of the font. - * - * Sets font size. - */ -void Q3DScatter::setFontSize(float fontsize) -{ - d_ptr->m_shared->setFontSize(fontsize); -} - -float Q3DScatter::fontSize() const -{ - return d_ptr->m_shared->fontSize(); -} - -/*! - * \property Q3DScatter::font - * - * \a font QFont to be used for labels. \c Arial by default. - * - * Sets the font for labels. - */ -void Q3DScatter::setFont(const QFont &font) -{ - d_ptr->m_shared->setFont(font); -} - -QFont Q3DScatter::font() const -{ - return d_ptr->m_shared->font(); -} - -/*! - * \property Q3DScatter::labelTransparency - * - * \a transparency Transparency level of labels from \c QDataVis::LabelTransparency. - * \c TransparencyFromTheme by default. - * - * Sets label transparency. - */ -void Q3DScatter::setLabelTransparency(QDataVis::LabelTransparency transparency) -{ - d_ptr->m_shared->setLabelTransparency(transparency); -} - -QDataVis::LabelTransparency Q3DScatter::labelTransparency() const -{ - return d_ptr->m_shared->labelTransparency(); -} - -/*! - * \property Q3DScatter::gridVisible - * - * \a visible Flag to enable or disable grid. \c true by default. - * - * Sets grid drawing on or off. - */ -void Q3DScatter::setGridVisible(bool visible) -{ - d_ptr->m_shared->setGridEnabled(visible); -} - -bool Q3DScatter::isGridVisible() const -{ - return d_ptr->m_shared->gridEnabled(); -} - -/*! - * \property Q3DScatter::backgroundVisible - * - * \a visible Flag to enable or disable background. \c true by default. - * - * Sets backround rendering on or off. - */ -void Q3DScatter::setBackgroundVisible(bool visible) -{ - d_ptr->m_shared->setBackgroundEnabled(visible); -} - -bool Q3DScatter::isBackgroundVisible() const -{ - return d_ptr->m_shared->backgroundEnabled(); -} - -/*! - * \property Q3DScatter::shadowQuality - * - * \a quality Shadow quality from \c QDataVis::ShadowQuality. \c ShadowLow by default. - * - * Sets shadow quality. If setting QDataVis::ShadowQuality of a certain level fails, a level is lowered - * until it is successful and shadowQualityChanged signal is emitted for each time the change is done. - */ -void Q3DScatter::setShadowQuality(QDataVis::ShadowQuality quality) -{ - return d_ptr->m_shared->setShadowQuality(quality); -} - -QDataVis::ShadowQuality Q3DScatter::shadowQuality() const -{ - return d_ptr->m_shared->shadowQuality(); -} - -void Q3DScatter::setValueAxisX(QValueAxis *axis) -{ - Q_ASSERT(axis); - - return d_ptr->m_shared->setAxisX(axis); -} - -QValueAxis *Q3DScatter::valueAxisX() -{ - return static_cast<QValueAxis *>(d_ptr->m_shared->axisX()); -} - -void Q3DScatter::setValueAxisY(QValueAxis *axis) -{ - Q_ASSERT(axis); - - return d_ptr->m_shared->setAxisY(axis); -} - -QValueAxis *Q3DScatter::valueAxisY() -{ - return static_cast<QValueAxis *>(d_ptr->m_shared->axisY()); -} - -void Q3DScatter::setValueAxisZ(QValueAxis *axis) -{ - Q_ASSERT(axis); - - return d_ptr->m_shared->setAxisZ(axis); -} - -QValueAxis *Q3DScatter::valueAxisZ() -{ - return static_cast<QValueAxis *>(d_ptr->m_shared->axisZ()); -} - -void Q3DScatter::setDataProxy(QScatterDataProxy *proxy) -{ - d_ptr->m_shared->setDataProxy(proxy); -} - -QScatterDataProxy *Q3DScatter::dataProxy() -{ - return d_ptr->m_shared->dataProxy(); -} - -Q3DScatterPrivate::Q3DScatterPrivate(Q3DScatter *q, QRect rect) - : q_ptr(q), - m_shared(new Scatter3DController(rect)) -{ -} - -Q3DScatterPrivate::~Q3DScatterPrivate() -{ - qDebug() << "Destroying Q3DScatterPrivate"; - delete m_shared; -} - -QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/engine/q3dscatter.h b/src/datavis3d/engine/q3dscatter.h deleted file mode 100644 index 73a7d214..00000000 --- a/src/datavis3d/engine/q3dscatter.h +++ /dev/null @@ -1,153 +0,0 @@ -/**************************************************************************** -** -** 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 QtDataVis3D 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 Q3DSCATTER_H -#define Q3DSCATTER_H - -#include <QtDataVis3D/qdatavis3denums.h> -#include <QtDataVis3D/q3dwindow.h> -#include <QFont> - -QT_DATAVIS3D_BEGIN_NAMESPACE - -class Q3DScatterPrivate; -class LabelItem; -class QValueAxis; -class QCategoryAxis; -class QScatterDataProxy; - -class QT_DATAVIS3D_EXPORT Q3DScatter : public Q3DWindow -{ - Q_OBJECT - Q_PROPERTY(QtDataVis3D::QDataVis::SelectionMode selectionMode READ selectionMode WRITE setSelectionMode) - Q_PROPERTY(QtDataVis3D::QDataVis::LabelTransparency labelTransparency READ labelTransparency WRITE setLabelTransparency) - Q_PROPERTY(QtDataVis3D::QDataVis::ShadowQuality shadowQuality READ shadowQuality WRITE setShadowQuality) - Q_PROPERTY(QString windowTitle READ windowTitle WRITE setWindowTitle) - Q_PROPERTY(QFont font READ font WRITE setFont) - Q_PROPERTY(float fontSize READ fontSize WRITE setFontSize) - Q_PROPERTY(bool gridVisible READ isGridVisible WRITE setGridVisible) - Q_PROPERTY(bool backgroundVisible READ isBackgroundVisible WRITE setBackgroundVisible) - Q_ENUMS(QtDataVis3D::QDataVis::SelectionMode) - Q_ENUMS(QtDataVis3D::QDataVis::ShadowQuality) - Q_ENUMS(QtDataVis3D::QDataVis::LabelTransparency) - -public: - explicit Q3DScatter(); - ~Q3DScatter(); - - // object type; spheres, dots - void setObjectType(QDataVis::MeshStyle style, bool smooth = false); - - // Select preset camera placement - void setCameraPreset(QDataVis::CameraPreset preset); - - // Set camera rotation if you don't want to use the presets (in horizontal (-180...180) and - // vertical (-90...90) angles and distance in percentage (10...500)) - void setCameraPosition(qreal horizontal, qreal vertical, int distance = 100); - - // Set theme (object colors, shaders, window color, background colors, light intensity and text - // colors are affected) - void setTheme(QDataVis::ColorTheme theme); - - // Set color if you don't want to use themes. Set uniform to false if you want the (height) - // color to change from bottom to top - void setObjectColor(QColor baseColor, QColor heightColor, QColor depthColor, - bool uniform = true); - - // override object type with own mesh - void setMeshFileName(const QString &objFileName); - - // Change selection mode - void setSelectionMode(QDataVis::SelectionMode mode); - QDataVis::SelectionMode selectionMode() const; - - // Set window title - void setWindowTitle(const QString &title); - QString windowTitle() const; - - // Font size adjustment - void setFontSize(float fontsize); - float fontSize() const; - - // Set font - void setFont(const QFont &font); - QFont font() const; - - // Label transparency adjustment - void setLabelTransparency(QDataVis::LabelTransparency transparency); - QDataVis::LabelTransparency labelTransparency() const; - - // Enable or disable background grid - void setGridVisible(bool visible); - bool isGridVisible() const; - - // Size - void setWidth(const int width); - void setHeight(const int height); - - // Enable or disable background mesh - void setBackgroundVisible(bool visible); - bool isBackgroundVisible() const; - - // Adjust shadow quality - void setShadowQuality(QDataVis::ShadowQuality quality); - QDataVis::ShadowQuality shadowQuality() const; - - // Axes - void setValueAxisX(QValueAxis *axis); - QValueAxis *valueAxisX(); - - void setValueAxisY(QValueAxis *axis); - QValueAxis *valueAxisY(); - - void setValueAxisZ(QValueAxis *axis); - QValueAxis *valueAxisZ(); - - // Sets the data proxy. Assumes ownership of the data proxy. Deletes old proxy. - void setDataProxy(QtDataVis3D::QScatterDataProxy *proxy); - QScatterDataProxy *dataProxy(); - -public slots: - // Used to detect when shadow quality changes autonomously due to e.g. resizing. - void handleShadowQualityUpdate(QDataVis::ShadowQuality quality); - -signals: - // Signals shadow quality changes. - void shadowQualityChanged(QDataVis::ShadowQuality quality); - -protected: - void render(); - -#if defined(Q_OS_ANDROID) - void mouseDoubleClickEvent(QMouseEvent *event); - void touchEvent(QTouchEvent *event); -#endif - void mousePressEvent(QMouseEvent *event); - void mouseReleaseEvent(QMouseEvent *event); - void mouseMoveEvent(QMouseEvent *event); - void wheelEvent(QWheelEvent *event); - void resizeEvent(QResizeEvent *event); - -private: - QScopedPointer<Q3DScatterPrivate> d_ptr; - Q_DISABLE_COPY(Q3DScatter) -}; - -QT_DATAVIS3D_END_NAMESPACE - -#endif diff --git a/src/datavis3d/engine/q3dsurface.cpp b/src/datavis3d/engine/q3dsurface.cpp deleted file mode 100644 index 7647ad10..00000000 --- a/src/datavis3d/engine/q3dsurface.cpp +++ /dev/null @@ -1,181 +0,0 @@ -/**************************************************************************** -** -** 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 QtDataVis3D 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 "q3dsurface.h" -#include "q3dsurface_p.h" - -#include <QMouseEvent> - -#include <QDebug> - -QT_DATAVIS3D_BEGIN_NAMESPACE - -Q3DSurface::Q3DSurface() - : d_ptr(new Q3DSurfacePrivate(this, geometry())) -{ - d_ptr->m_shared->initializeOpenGL(); -} - -Q3DSurface::~Q3DSurface() -{ -} - -void Q3DSurface::render() -{ - d_ptr->m_shared->render(); -} - -#if defined(Q_OS_ANDROID) -void Q3DSurface::mouseDoubleClickEvent(QMouseEvent *event) -{ -} -void Q3DSurface::touchEvent(QTouchEvent *event) -{ -} -#endif - -void Q3DSurface::mousePressEvent(QMouseEvent *event) -{ - d_ptr->m_shared->mousePressEvent(event, event->pos()); -} - -void Q3DSurface::mouseReleaseEvent(QMouseEvent *event) -{ - d_ptr->m_shared->mouseReleaseEvent(event, event->pos()); -} - -void Q3DSurface::mouseMoveEvent(QMouseEvent *event) -{ - d_ptr->m_shared->mouseMoveEvent(event, event->pos()); -} - -void Q3DSurface::wheelEvent(QWheelEvent *event) -{ - Q_UNUSED(event) -} - -void Q3DSurface::resizeEvent(QResizeEvent *event) -{ - Q_UNUSED(event); - d_ptr->m_shared->setWidth(width()); - d_ptr->m_shared->setHeight(height()); -} - -void Q3DSurface::setSmoothSurface(bool enable) -{ - d_ptr->m_shared->setSmoothSurface(enable); -} - -bool Q3DSurface::smoothSurface() const -{ - return d_ptr->m_shared->smoothSurface(); -} - -void Q3DSurface::setSurfaceGrid(bool enable) -{ - d_ptr->m_shared->setSurfaceGrid(enable); -} - -bool Q3DSurface::surfaceGrid() const -{ - return d_ptr->m_shared->surfaceGrid(); -} - -void Q3DSurface::setWidth(const int width) -{ - d_ptr->m_shared->setWidth(width); - QWindow::setWidth(width); -} - -void Q3DSurface::setHeight(const int height) -{ - d_ptr->m_shared->setHeight(height); - QWindow::setHeight(height); -} - -/*! - * \a segmentCount How many segments will be drawn. \c 5 by default. - * - * \a step How large a step each segment is. - * - * \a minimum Minimum value a bar in data set can have. Setting this correctly is especially - * important if values can be negative, or autoscaling won't work correctly. - * - * Sets segment count and step. Note; segmentCount * step should be the maximum possible value of data - * set. - */ -void Q3DSurface::setSegmentCount(int segmentCount, qreal step, qreal minimum) -{ - d_ptr->m_shared->setSegmentCount(GLint(segmentCount), GLfloat(step), GLfloat(minimum)); -} - -void Q3DSurface::setGradientColorAt(qreal pos, const QColor &color) -{ - d_ptr->m_shared->setGradientColorAt(pos, color); -} - -// TODO ///////////////////////////////////////// -void Q3DSurface::appendSeries(QList<qreal> series, int width, int depth ) -{ - d_ptr->appendSeries(series); - d_ptr->m_shared->setData(series, width, depth); -} - -void Q3DSurface::showData() const -{ - for (int i = 0; i < d_ptr->numOfSeries(); i++) { - QList<qreal> s = d_ptr->seriesAt(i); - qDebug() << "Series = "; - foreach (qreal val, s) { - qDebug() << val; - } - } -} - -// TODO END ////////////////////////////////////////// - -/////////////////// PRIVATE /////////////////////////////////// - -Q3DSurfacePrivate::Q3DSurfacePrivate(Q3DSurface *q, QRect rect) - : q_ptr(q), - m_shared(new Surface3dController(rect)) -{ -} - -Q3DSurfacePrivate::~Q3DSurfacePrivate() -{ - qDebug() << "Q3DSurfacePrivate::~Q3DSurfacePrivate"; - delete m_shared; -} - -void Q3DSurfacePrivate::appendSeries(QList<qreal> series) -{ - m_seriesList.append(series); -} - -QList<qreal> Q3DSurfacePrivate::seriesAt(int i) -{ - return m_seriesList.at(i); -} - -int Q3DSurfacePrivate::numOfSeries() -{ - return m_seriesList.count(); -} - -QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/engine/q3dsurface.h b/src/datavis3d/engine/q3dsurface.h deleted file mode 100644 index c2deea9a..00000000 --- a/src/datavis3d/engine/q3dsurface.h +++ /dev/null @@ -1,84 +0,0 @@ -/**************************************************************************** -** -** 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 QtDataVis3D 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 Q3DSURFACE_H -#define Q3DSURFACE_H - -#include <QtDataVis3D/qdatavis3denums.h> -#include <QtDataVis3D/q3dwindow.h> - -QT_DATAVIS3D_BEGIN_NAMESPACE - -class Q3DSurfacePrivate; - -class QT_DATAVIS3D_EXPORT Q3DSurface : public Q3DWindow -{ - Q_OBJECT - Q_PROPERTY(bool smoothSurface READ smoothSurface WRITE setSmoothSurface) - Q_PROPERTY(bool surfaceGrid READ surfaceGrid WRITE setSurfaceGrid) - -public: - explicit Q3DSurface(); - ~Q3DSurface(); - - // Enable or disable the smoothes of the surface - void setSmoothSurface(bool enable); - bool smoothSurface() const; - - // Enable or disable the grid on the surface - void setSurfaceGrid(bool enable); - bool surfaceGrid() const; - - void setGradientColorAt(qreal pos, const QColor &color); - - // Set segment count and step. Note; segmentCount * step should be the maximum possible value of data - // set. Minimum is the absolute minimum possible value a bar can have. This is especially - // important to set if values can be negative. - void setSegmentCount(int segmentCount, qreal step, qreal minimum = 0.0f); - -//TODO part - void appendSeries(QList<qreal> series, int width, int depth); - void showData() const; -//END TODO - - // TODO: Do these need to be public? Where are they called from? - // Size - void setWidth(const int width); - void setHeight(const int height); - -protected: - void render(); - -#if defined(Q_OS_ANDROID) - void mouseDoubleClickEvent(QMouseEvent *event); - void touchEvent(QTouchEvent *event); -#endif - void mousePressEvent(QMouseEvent *event); - void mouseReleaseEvent(QMouseEvent *event); - void mouseMoveEvent(QMouseEvent *event); - void wheelEvent(QWheelEvent *event); - void resizeEvent(QResizeEvent *event); - -private: - QScopedPointer<Q3DSurfacePrivate> d_ptr; - Q_DISABLE_COPY(Q3DSurface) -}; - -QT_DATAVIS3D_END_NAMESPACE - -#endif // Q3DSURFACE_H diff --git a/src/datavis3d/engine/scatter3dcontroller.cpp b/src/datavis3d/engine/scatter3dcontroller.cpp deleted file mode 100644 index ef56fc23..00000000 --- a/src/datavis3d/engine/scatter3dcontroller.cpp +++ /dev/null @@ -1,367 +0,0 @@ -/**************************************************************************** -** -** 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 QtDataVis3D 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 "scatter3dcontroller_p.h" -#include "scatter3drenderer_p.h" -#include "camerahelper_p.h" -#include "qabstractaxis_p.h" -#include "qvalueaxis_p.h" -#include "qscatterdataproxy_p.h" - -#include <QMatrix4x4> -#include <QMouseEvent> -#include <qmath.h> - -QT_DATAVIS3D_BEGIN_NAMESPACE - -Scatter3DController::Scatter3DController(QRect boundRect) - : Abstract3DController(boundRect), - m_mouseState(MouseNone), - m_mousePos(QPoint(0, 0)), - m_isSlicingActivated(false), - m_renderer(0), - m_data(0) -{ - // Default axes - setAxisX(new QValueAxis()); - setAxisY(new QValueAxis()); - setAxisZ(new QValueAxis()); - - // Default object type; specific to scatter - setObjectType(QDataVis::Spheres, false); - - setDataProxy(new QScatterDataProxy); -} - -Scatter3DController::~Scatter3DController() -{ - delete m_data; -} - -void Scatter3DController::initializeOpenGL() -{ - // Initialization is called multiple times when Qt Quick components are used - if (isInitialized()) - return; - - m_renderer = new Scatter3DRenderer(this); - setRenderer(m_renderer); - synchDataToRenderer(); -} - -void Scatter3DController::synchDataToRenderer() -{ - Abstract3DController::synchDataToRenderer(); - - if (!isInitialized()) - return; - - // Notify changes to renderer - if (m_changeTracker.slicingActiveChanged) { - // TODO: Add notification. - m_changeTracker.slicingActiveChanged = false; - } - - if (m_isDataDirty) { - m_renderer->updateDataModel(m_data); - m_isDataDirty = false; - } -} - -QMatrix4x4 Scatter3DController::calculateViewMatrix(int zoom, int viewPortWidth, - int viewPortHeight, bool showUnder) -{ - return m_cameraHelper->calculateViewMatrix(m_mousePos, - zoom, - viewPortWidth, - viewPortHeight, - showUnder); -} - -bool Scatter3DController::isSlicingActive() -{ - return m_isSlicingActivated; -} - -void Scatter3DController::setSlicingActive(bool isSlicing) -{ - m_isSlicingActivated = isSlicing; - - m_changeTracker.slicingActiveChanged = true; - emit slicingActiveChanged(m_isSlicingActivated); -} - -Scatter3DController::MouseState Scatter3DController::mouseState() -{ - return m_mouseState; -} - -#if defined(Q_OS_ANDROID) -void Scatter3DController::mouseDoubleClickEvent(QMouseEvent *event) -{ - if (!m_isSlicingActivated) { - m_mouseState = Scatter3DController::MouseOnScene; - // update mouse positions to prevent jumping when releasing or repressing a button - m_mousePos = event->pos(); - } -} - -void Scatter3DController::touchEvent(QTouchEvent *event) -{ - static int prevDistance = 0; - - QList<QTouchEvent::TouchPoint> points; - points = event->touchPoints(); - - if (points.count() == 2) { - m_mouseState = Scatter3DController::MouseOnPinch; - - QPointF distance = points.at(0).pos() - points.at(1).pos(); - int newDistance = distance.manhattanLength(); - int zoomRate = 1; - int zoomLevel = m_zoomLevel; - if (zoomLevel > 100) - zoomRate = 5; - if (newDistance > prevDistance) - zoomLevel += zoomRate; - else - zoomLevel -= zoomRate; - if (zoomLevel > 500) - zoomLevel = 500; - else if (zoomLevel < 10) - zoomLevel = 10; - setZoomLevel(zoomLevel); - prevDistance = newDistance; - //qDebug() << "distance" << distance.manhattanLength(); - } -} -#endif - -void Scatter3DController::mousePressEvent(QMouseEvent *event, const QPoint &mousePos) -{ - QRect mainViewPort = m_renderer->mainViewPort(); - if (Qt::LeftButton == event->button()) { - if (m_isSlicingActivated) { - if (mousePos.x() <= mainViewPort.width() - && mousePos.y() <= mainViewPort.height()) { - m_mouseState = Scatter3DController::MouseOnOverview; - //qDebug() << "Mouse pressed on overview"; - } else { - m_mouseState = Scatter3DController::MouseOnZoom; - //qDebug() << "Mouse pressed on zoom"; - } - } else { -#if !defined(Q_OS_ANDROID) - m_mouseState = Scatter3DController::MouseOnScene; -#else - m_mouseState = Scatter3DController::MouseRotating; -#endif - // update mouse positions to prevent jumping when releasing or repressing a button - m_mousePos = mousePos; - //qDebug() << "Mouse pressed on scene"; - } - } else if (Qt::MiddleButton == event->button()) { - // reset rotations - m_mousePos = QPoint(0, 0); - } else if (Qt::RightButton == event->button()) { -#if !defined(Q_OS_ANDROID) - m_mouseState = Scatter3DController::MouseRotating; -#else - m_mouseState = Scatter3DController::MouseOnScene; -#endif - // update mouse positions to prevent jumping when releasing or repressing a button - m_mousePos = mousePos; - } - m_cameraHelper->updateMousePos(m_mousePos); -} - -void Scatter3DController::mouseReleaseEvent(QMouseEvent *event, const QPoint &mousePos) -{ - Q_UNUSED(event); - if (Scatter3DController::MouseRotating == m_mouseState) { - // update mouse positions to prevent jumping when releasing or repressing a button - m_mousePos = mousePos; - m_cameraHelper->updateMousePos(mousePos); - } - m_mouseState = Scatter3DController::MouseNone; -} - -void Scatter3DController::mouseMoveEvent(QMouseEvent *event, const QPoint &mousePos) -{ - Q_UNUSED(event); - if (Scatter3DController::MouseRotating == m_mouseState) - m_mousePos = mousePos; -} - -void Scatter3DController::wheelEvent(QWheelEvent *event) -{ - int zoomLevel = m_zoomLevel; - if (zoomLevel > 100) - zoomLevel += event->angleDelta().y() / 12; - else if (zoomLevel > 50) - zoomLevel += event->angleDelta().y() / 60; - else - zoomLevel += event->angleDelta().y() / 120; - if (zoomLevel > 500) - zoomLevel = 500; - else if (zoomLevel < 10) - zoomLevel = 10; - - setZoomLevel(zoomLevel); -} - -void Scatter3DController::setDataProxy(QScatterDataProxy *proxy) -{ - delete m_data; - m_data = proxy; - - QObject::connect(m_data, &QScatterDataProxy::arrayReset, - this, &Scatter3DController::handleArrayReset); - QObject::connect(m_data, &QScatterDataProxy::itemsAdded, - this, &Scatter3DController::handleItemsAdded); - QObject::connect(m_data, &QScatterDataProxy::itemsChanged, - this, &Scatter3DController::handleItemsChanged); - QObject::connect(m_data, &QScatterDataProxy::itemsRemoved, - this, &Scatter3DController::handleItemsRemoved); - QObject::connect(m_data, &QScatterDataProxy::itemsInserted, - this, &Scatter3DController::handleItemsInserted); - - adjustValueAxisRange(); - m_isDataDirty = true; -} - -QScatterDataProxy *Scatter3DController::dataProxy() -{ - return m_data; -} - -void Scatter3DController::handleArrayReset() -{ - setSlicingActive(false); - adjustValueAxisRange(); - m_isDataDirty = true; -} - -void Scatter3DController::handleItemsAdded(int startIndex, int count) -{ - Q_UNUSED(startIndex) - Q_UNUSED(count) - // TODO should dirty only affected values? - adjustValueAxisRange(); - m_isDataDirty = true; -} - -void Scatter3DController::handleItemsChanged(int startIndex, int count) -{ - Q_UNUSED(startIndex) - Q_UNUSED(count) - // TODO should dirty only affected values? - adjustValueAxisRange(); - m_isDataDirty = true; -} - -void Scatter3DController::handleItemsRemoved(int startIndex, int count) -{ - Q_UNUSED(startIndex) - Q_UNUSED(count) - // TODO should dirty only affected values? - adjustValueAxisRange(); - m_isDataDirty = true; -} - -void Scatter3DController::handleItemsInserted(int startIndex, int count) -{ - Q_UNUSED(startIndex) - Q_UNUSED(count) - // TODO should dirty only affected values? - adjustValueAxisRange(); - m_isDataDirty = true; -} - -void Scatter3DController::handleAxisAutoAdjustRangeChangedInOrientation( - QAbstractAxis::AxisOrientation orientation, bool autoAdjust) -{ - Q_UNUSED(orientation) - Q_UNUSED(autoAdjust) - adjustValueAxisRange(); -} - -void Scatter3DController::setObjectType(QDataVis::MeshStyle style, bool smooth) -{ - QString objFile; - if (style == QDataVis::Spheres) { - if (smooth) - objFile = QStringLiteral(":/defaultMeshes/sphereSmooth"); - else - objFile = QStringLiteral(":/defaultMeshes/sphere"); - } else { - if (smooth) - objFile = QStringLiteral(":/defaultMeshes/dotSmooth"); - else - objFile = QStringLiteral(":/defaultMeshes/dot"); - } - Abstract3DController::setMeshFileName(objFile); -} - -void Scatter3DController::setSelectionMode(QDataVis::SelectionMode mode) -{ - if (mode > QDataVis::ModeItem) { - qWarning("Unsupported selection mode."); - return; - } - // Disable zoom if selection mode changes - setSlicingActive(false); - Abstract3DController::setSelectionMode(mode); -} - -QPoint Scatter3DController::mousePosition() -{ - return m_mousePos; -} - -void Scatter3DController::adjustValueAxisRange() -{ - if (m_data) { - QVector3D limits = m_data->dptr()->limitValues(); - QValueAxis *valueAxis = static_cast<QValueAxis *>(m_axisX); - if (valueAxis && valueAxis->isAutoAdjustRange()) { - if (limits.x() > 0) - valueAxis->dptr()->setRange(-limits.x(), limits.x()); - else - valueAxis->dptr()->setRange(-1.0, 1.0); // Only zero value values in data set, set range to default. - } - - valueAxis = static_cast<QValueAxis *>(m_axisY); - if (valueAxis && valueAxis->isAutoAdjustRange()) { - if (limits.y() > 0) - valueAxis->dptr()->setRange(-limits.y(), limits.y()); - else - valueAxis->dptr()->setRange(-1.0, 1.0); // Only zero value values in data set, set range to default. - } - - valueAxis = static_cast<QValueAxis *>(m_axisZ); - if (valueAxis && valueAxis->isAutoAdjustRange()) { - if (limits.z() > 0) - valueAxis->dptr()->setRange(-limits.z(), limits.z()); - else - valueAxis->dptr()->setRange(-1.0, 1.0); // Only zero value values in data set, set range to default. - } - } -} - -QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/engine/shaders/surfaceGrid.frag b/src/datavis3d/engine/shaders/surfaceGrid.frag deleted file mode 100644 index 20b923fb..00000000 --- a/src/datavis3d/engine/shaders/surfaceGrid.frag +++ /dev/null @@ -1,16 +0,0 @@ -varying highp vec2 UV; -varying highp vec2 coords_mdl; -varying highp vec3 position_wrld; -varying highp vec3 normal_cmr; -varying highp vec3 eyeDirection_cmr; -varying highp vec3 lightDirection_cmr; - -uniform highp vec3 lightPosition_wrld; -uniform highp vec3 color_mdl; -uniform highp float lightStrength; -uniform highp float ambientStrength; - -void main() { - gl_FragColor.rgb = color_mdl; -} - diff --git a/src/datavis3d/engine/shaders/surfaceGrid.vert b/src/datavis3d/engine/shaders/surfaceGrid.vert deleted file mode 100644 index efb40862..00000000 --- a/src/datavis3d/engine/shaders/surfaceGrid.vert +++ /dev/null @@ -1,26 +0,0 @@ -attribute highp vec3 vertexPosition_mdl; -attribute highp vec2 vertexUV; -attribute highp vec3 vertexNormal_mdl; - -uniform highp mat4 MVP; -uniform highp mat4 V; -uniform highp mat4 M; -uniform highp mat4 itM; -uniform highp vec3 lightPosition_wrld; - -varying highp vec3 position_wrld; -varying highp vec3 normal_cmr; -varying highp vec3 eyeDirection_cmr; -varying highp vec3 lightDirection_cmr; -varying highp vec2 coords_mdl; - -void main() { - gl_Position = MVP * vec4(vertexPosition_mdl, 1.0); - coords_mdl = vertexPosition_mdl.xy; - position_wrld = (M * vec4(vertexPosition_mdl, 1.0)).xyz; - vec3 vertexPosition_cmr = (V * M * vec4(vertexPosition_mdl, 1.0)).xyz; - eyeDirection_cmr = vec3(0.0, 0.0, 0.0) - vertexPosition_cmr; - vec3 lightPosition_cmr = (V * vec4(lightPosition_wrld, 1.0)).xyz; - lightDirection_cmr = lightPosition_cmr + eyeDirection_cmr; - normal_cmr = (V * itM * vec4(vertexNormal_mdl, 0.0)).xyz; -} diff --git a/src/datavis3d/engine/surface3dcontroller.cpp b/src/datavis3d/engine/surface3dcontroller.cpp deleted file mode 100644 index 2915c993..00000000 --- a/src/datavis3d/engine/surface3dcontroller.cpp +++ /dev/null @@ -1,211 +0,0 @@ -/**************************************************************************** -** -** 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 QtDataVis3D 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 "surface3dcontroller_p.h" -#include "surface3drenderer_p.h" -#include "camerahelper_p.h" - -#include <QMatrix4x4> -#include <QMouseEvent> - -#include <QDebug> - -QT_DATAVIS3D_BEGIN_NAMESPACE - -Surface3dController::Surface3dController(QRect rect) - : Abstract3DController(rect), - m_mouseState(MouseNone), - m_mousePos(QPoint(0, 0)), - m_renderer(0), - m_isInitialized(false), - m_smoothSurface(false), - m_surfaceGrid(true) -{ -} - -Surface3dController::~Surface3dController() -{ -} - -void Surface3dController::initializeOpenGL() -{ - // Initialization is called multiple times when Qt Quick components are used - if (m_isInitialized) - return; - - m_renderer = new Surface3dRenderer(this); - m_isInitialized = true; -} - -void Surface3dController::synchDataToRenderer() -{ - // TODO: Implement -} - -void Surface3dController::render(const GLuint defaultFboHandle) -{ - if (!m_isInitialized) - return; - - m_renderer->render(m_cameraHelper, defaultFboHandle); -} - -void Surface3dController::handleAxisAutoAdjustRangeChangedInOrientation(QAbstractAxis::AxisOrientation orientation, bool autoAdjust) -{ - Q_UNUSED(orientation) - Q_UNUSED(autoAdjust) - - // TODO: Implement! -} - -QMatrix4x4 Surface3dController::calculateViewMatrix(int zoom, int viewPortWidth, int viewPortHeight, bool showUnder) -{ - return m_cameraHelper->calculateViewMatrix(m_mousePos, - zoom, - viewPortWidth, - viewPortHeight, - showUnder); -} - -void Surface3dController::setWidth(const int width) -{ - qDebug() << "Surface3dController::setWidth"; - m_renderer->setWidth(width); -} - -void Surface3dController::setHeight(const int height) -{ - qDebug() << "Surface3dController::setHeight"; - m_renderer->setHeight(height); -} - -void Surface3dController::setSmoothSurface(bool enable) -{ - m_smoothSurface = enable; - emit smoothStatusChanged(m_smoothSurface); -} - -bool Surface3dController::smoothSurface() -{ - return m_smoothSurface; -} - -void Surface3dController::setSurfaceGrid(bool enable) -{ - m_surfaceGrid = enable; - emit surfaceGridChanged(m_surfaceGrid); -} - -bool Surface3dController::surfaceGrid() -{ - return m_surfaceGrid; -} - - -#if defined(Q_OS_ANDROID) -void Surface3dController::mouseDoubleClickEvent(QMouseEvent *event) -{ -} -void touchEvent(QTouchEvent *event) -{ -} -#endif - -void Surface3dController::mousePressEvent(QMouseEvent *event, const QPoint &mousePos) -{ - if (Qt::LeftButton == event->button()) { - m_mousePos = mousePos; - emit leftMousePressed(); - } else if (Qt::RightButton == event->button()) { - #if !defined(Q_OS_ANDROID) - m_mouseState = Abstract3DController::MouseRotating; - #else - m_mouseState = Abstract3DController::MouseOnScene; - #endif - // update mouse positions to prevent jumping when releasing or repressing a button - m_mousePos = mousePos; //event->pos(); - } - m_cameraHelper->updateMousePos(m_mousePos); -} - -void Surface3dController::mouseReleaseEvent(QMouseEvent *event, const QPoint &mousePos) -{ - Q_UNUSED(event) - if (Abstract3DController::MouseRotating == m_mouseState) { - // update mouse positions to prevent jumping when releasing or repressing a button - m_mousePos = mousePos; //event->pos(); - m_cameraHelper->updateMousePos(mousePos); //event->pos()); - } - m_mouseState = Abstract3DController::MouseNone; -} - -void Surface3dController::mouseMoveEvent(QMouseEvent *event, const QPoint &mousePos) -{ - Q_UNUSED(event) - if (Abstract3DController::MouseRotating == m_mouseState) - m_mousePos = mousePos; //event->pos(); -} - -void Surface3dController::wheelEvent(QWheelEvent *event) -{ - Q_UNUSED(event) -} - -QPoint Surface3dController::mousePosition() -{ - return m_mousePos; -} - - -// TODO: abstract renderer should have accessor for Drawer instead -Drawer *Surface3dController::drawer() -{ - if (m_renderer) - return m_renderer->drawer(); - else - return 0; -} - -void Surface3dController::setSegmentCount(GLint segmentCount, GLfloat step, GLfloat minimum) -{ - m_segmentCount = segmentCount; - m_segmentStep = step; - m_segmentMinimum = minimum; - - emit segmentCountChanged(m_segmentCount, m_segmentStep, m_segmentMinimum); -} - -void Surface3dController::setGradientColorAt(qreal pos, const QColor &color) -{ - Theme t = theme(); - t.m_surfaceGradient.setColorAt(pos, color); - emit themeChanged(t); -} - -// TODO: Temp -void Surface3dController::setData(QList<qreal> series, int width, int depth) -{ - m_series = series; - m_dataWidth = width; - m_dataDepth = depth; - - m_renderer->setXZStuff(width, depth); - m_renderer->setSeries(series); -} - -QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/engine/surface3dcontroller_p.h b/src/datavis3d/engine/surface3dcontroller_p.h deleted file mode 100644 index d8c36d08..00000000 --- a/src/datavis3d/engine/surface3dcontroller_p.h +++ /dev/null @@ -1,121 +0,0 @@ -/**************************************************************************** -** -** 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 QtDataVis3D 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 QtDataVis3D 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 SURFACE3DCONTROLLER_P_H -#define SURFACE3DCONTROLLER_P_H - -#include "abstract3dcontroller_p.h" -#include "datavis3dglobal_p.h" - -#include <QLinearGradient> - -QT_DATAVIS3D_BEGIN_NAMESPACE - -class Surface3dRenderer; - -class QT_DATAVIS3D_EXPORT Surface3dController : public Abstract3DController -{ - Q_OBJECT - -private: - Surface3dRenderer *m_renderer; - bool m_isInitialized; - QList<qreal> m_series; // TODO: TEMP - int m_dataWidth; - int m_dataDepth; - bool m_smoothSurface; - bool m_surfaceGrid; - - GLint m_segmentCount; - GLfloat m_segmentStep; - GLfloat m_segmentMinimum; - - // Interaction - MouseState m_mouseState; - QPoint m_mousePos; - QDataVis::SelectionMode m_selectionMode; - -public: - explicit Surface3dController(QRect rect); - ~Surface3dController(); - - void initializeOpenGL(); - void synchDataToRenderer(); - void render(const GLuint defaultFboHandle = 0); - - QPoint mousePosition(); - - QMatrix4x4 calculateViewMatrix(int zoom, int viewPortWidth, int viewPortHeight, bool showUnder = false); - - void setWidth(const int width); - void setHeight(const int height); - - // Enable or disable the smoothes of the surface - void setSmoothSurface(bool enable); - bool smoothSurface(); - - // Enable or disable the grid on the surface - void setSurfaceGrid(bool enable); - bool surfaceGrid(); - - void setGradientColorAt(qreal pos, const QColor &color); - - // Set segment count and step. Note; segmentCount * step should be the maximum possible value of data - // set. Minimum is the absolute minimum possible value a bar can have. This is especially - // important to set if values can be negative. - void setSegmentCount(GLint segmentCount, GLfloat step, GLfloat minimum = 0.0f); - - //TODO: Temp solution - void setData(QList<qreal> series, int width, int depth); - -#if defined(Q_OS_ANDROID) - void mouseDoubleClickEvent(QMouseEvent *event); - void touchEvent(QTouchEvent *event); -#endif - void mousePressEvent(QMouseEvent *event, const QPoint &mousePos); - void mouseReleaseEvent(QMouseEvent *event, const QPoint &mousePos); - void mouseMoveEvent(QMouseEvent *event, const QPoint &mousePos); - void wheelEvent(QWheelEvent *event); - - // TODO: abstract renderer should have accessor for Drawer instead - virtual Drawer *drawer(); - virtual void handleAxisAutoAdjustRangeChangedInOrientation(QAbstractAxis::AxisOrientation orientation, bool autoAdjust); - -signals: - void smoothStatusChanged(bool enable); - void surfaceGridChanged(bool enable); - void segmentCountChanged(GLint segmentCount, GLfloat step, GLfloat minimum); - void leftMousePressed(); - -private: - Q_DISABLE_COPY(Surface3dController) -}; - -QT_DATAVIS3D_END_NAMESPACE - -#endif // SURFACE3DCONTROLLER_P_H diff --git a/src/datavis3d/engine/surface3drenderer.cpp b/src/datavis3d/engine/surface3drenderer.cpp deleted file mode 100644 index c66bd291..00000000 --- a/src/datavis3d/engine/surface3drenderer.cpp +++ /dev/null @@ -1,894 +0,0 @@ -/**************************************************************************** -** -** 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 QtDataVis3D 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 "surface3dcontroller_p.h" -#include "surface3drenderer_p.h" -#include "camerahelper_p.h" -#include "shaderhelper_p.h" -#include "objecthelper_p.h" -#include "surfaceobject_p.h" -#include "texturehelper_p.h" -#include "theme_p.h" -#include "utils_p.h" -#include "drawer_p.h" - -#include <QMatrix4x4> -#include <QMouseEvent> -#include <qmath.h> - -#include <QLinearGradient> -#include <QPainter> - -#include <QDebug> - -static const int ID_TO_RGBA_MASK = 0xff; - -QT_DATAVIS3D_BEGIN_NAMESPACE - -Surface3dRenderer::Surface3dRenderer(Surface3dController *controller) - : QObject(controller), - m_controller(controller), - m_mousePressed(MouseNone), - m_mousePos(QPoint(0, 0)), - m_isGridEnabled(true), - m_isBackgroundEnabled(true), - m_shadowQuality(QDataVis::ShadowLow), - m_labelTransparency(QDataVis::TransparencyFromTheme), - m_font(QFont(QStringLiteral("Arial"))), - m_hasNegativeValues(false), - m_segmentYCount(0), - m_segmentYStep(0.0f), - m_segmentXCount(0), - m_segmentZCount(0), - m_backgroundShader(0), - m_surfaceShader(0), - m_surfaceGridShader(0), - m_selectionShader(0), - m_isInitialized(false), - m_yRange(0.0f), // m_heightNormalizer - m_yAdjustment(0.0f), - m_xLength(0.0f), - m_zLength(0.0f), - m_maxDimension(0.0f), - m_scaleFactor(0.0f), - m_scaleX(0.0f), - m_scaleZ(0.0f), - m_maxSceneSize(40.0), - m_backgroundObj(0), - m_gridLineObj(0), - m_surfaceObj(0), - m_depthTexture(0), - m_depthFrameBuffer(0), - m_selectionFrameBuffer(0), - m_selectionDepthBuffer(0), - m_gradientTexture(0), - m_selectionTexture(0), - m_selectionResultTexture(0), - m_shadowQualityToShader(33.3f), - m_querySelection(false), - m_drawer(new Drawer(m_cachedTheme, m_font, m_labelTransparency)) -{ - // Listen to changes in the controller - QObject::connect(m_controller, &Surface3dController::smoothStatusChanged, this, - &Surface3dRenderer::updateSmoothStatus); - QObject::connect(m_controller, &Surface3dController::surfaceGridChanged, this, - &Surface3dRenderer::updateSurfaceGridStatus); - QObject::connect(m_controller, &Surface3dController::segmentCountChanged, this, - &Surface3dRenderer::updateSegmentCount); - QObject::connect(m_controller, &Surface3dController::themeChanged, this, - &Surface3dRenderer::updateTheme); - QObject::connect(m_controller, &Surface3dController::leftMousePressed, this, - &Surface3dRenderer::getSelection); - - m_cachedSmoothSurface = m_controller->smoothSurface(); - updateSurfaceGridStatus(m_controller->surfaceGrid()); - updateTheme(m_controller->theme()); - - initializeOpenGL(); -} - -Surface3dRenderer::~Surface3dRenderer() -{ - qDebug() << "Surface3dRenderer::~Surface3dRenderer()"; - m_textureHelper->glDeleteFramebuffers(1, &m_depthFrameBuffer); - m_textureHelper->glDeleteRenderbuffers(1, &m_selectionDepthBuffer); - m_textureHelper->glDeleteFramebuffers(1, &m_selectionFrameBuffer); - - m_textureHelper->deleteTexture(&m_depthTexture); - m_textureHelper->deleteTexture(&m_gradientTexture); - m_textureHelper->deleteTexture(&m_selectionTexture); - m_textureHelper->deleteTexture(&m_selectionResultTexture); - - delete m_backgroundShader; - delete m_selectionShader; - delete m_surfaceShader; - delete m_surfaceGridShader; - - delete m_backgroundObj; - delete m_surfaceObj; - delete m_textureHelper; - delete m_drawer; -} - -void Surface3dRenderer::initializeOpenGL() -{ - // Initialization is called multiple times when Qt Quick components are used - if (m_isInitialized) - return; - - initializeOpenGLFunctions(); - - m_textureHelper = new TextureHelper(); - m_drawer->initializeOpenGL(); - - // Initialize shaders -#if !defined(QT_OPENGL_ES_2) - if (m_shadowQuality > QDataVis::ShadowNone) { - initBackgroundShaders(QStringLiteral(":/shaders/vertexShadow"), - QStringLiteral(":/shaders/fragmentShadowNoTex")); - } else { - initBackgroundShaders(QStringLiteral(":/shaders/vertex"), - QStringLiteral(":/shaders/fragment")); - } -#else - initBackgroundShaders(QStringLiteral(":/shaders/vertexES2"), - QStringLiteral(":/shaders/fragmentES2")); -#endif - - initSurfaceShaders(); - - // Init selection shader - initSelectionShaders(); - - // Load grid line mesh - loadGridLineMesh(); - - // Load label mesh - //loadLabelMesh(); - - // Set OpenGL features - glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_LESS); - glEnable(GL_CULL_FACE); - glCullFace(GL_BACK); - -#if !defined(QT_OPENGL_ES_2) - glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); - glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); - glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST); -#endif - - // Set view port - glViewport(m_sliceViewPort.x(), m_sliceViewPort.y(), - m_sliceViewPort.width(), m_sliceViewPort.height()); - - // Set initialized -flag - m_isInitialized = true; - - // Resize in case we've missed resize events - // Resize calls initSelectionBuffer and initDepthBuffer, so they don't need to be called here - handleResize(); - - // Load background mesh (we need to be initialized first) - loadBackgroundMesh(); - - //loadSurfaceObj(); -} - -void Surface3dRenderer::render(CameraHelper *camera, const GLuint defaultFboHandle) -{ - if (!m_isInitialized) - return; - - if (defaultFboHandle) { - glDepthMask(true); - glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_LESS); - glEnable(GL_CULL_FACE); - glCullFace(GL_BACK); - } - - QVector3D clearColor = Utils::vectorFromColor(m_cachedTheme.m_windowColor); - glClearColor(clearColor.x(), clearColor.y(), clearColor.z(), 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - // TODO: bars have m_hasHeightAdjustmentChanged, which is always true! - // Set initial camera position - // X must be 0 for rotation to work - we can use "setCameraRotation" for setting it later - camera->setDefaultCameraOrientation(QVector3D(0.0f, 0.0f, 6.0f + zComp), - QVector3D(0.0f, 0.0f, zComp), - QVector3D(0.0f, 1.0f, 0.0f)); - - drawScene(camera, defaultFboHandle); -} - -void Surface3dRenderer::drawScene(CameraHelper *camera, const GLuint defaultFboHandle) -{ - //qDebug() << "Surface3dRenderer::drawScene"; - - GLfloat backgroundRotation = 0; - - // Specify viewport - glViewport(m_mainViewPort.x(), m_mainViewPort.y(), - m_mainViewPort.width(), m_mainViewPort.height()); - - // Set up projection matrix - QMatrix4x4 projectionMatrix; - projectionMatrix.perspective(45.0f, (GLfloat)m_mainViewPort.width() - / (GLfloat)m_mainViewPort.height(), 0.1f, 100.0f); - - // Calculate view matrix - QMatrix4x4 viewMatrix = m_controller->calculateViewMatrix( - 100.0f, //TODO: m_zoomLevel * m_autoScaleAdjustment - m_mainViewPort.width(), - m_mainViewPort.height(), - m_hasNegativeValues); - - // calculate background rotation based on view matrix rotation - if (viewMatrix.row(0).x() > 0 && viewMatrix.row(0).z() <= 0) - backgroundRotation = 270.0f; - else if (viewMatrix.row(0).x() > 0 && viewMatrix.row(0).z() > 0) - backgroundRotation = 180.0f; - else if (viewMatrix.row(0).x() <= 0 && viewMatrix.row(0).z() > 0) - backgroundRotation = 90.0f; - else if (viewMatrix.row(0).x() <= 0 && viewMatrix.row(0).z() <= 0) - backgroundRotation = 0.0f; - - QVector3D lightPos = camera->calculateLightPosition(defaultLightPos); - - QMatrix4x4 depthViewMatrix; - QMatrix4x4 depthProjectionMatrix; - depthProjectionMatrix = projectionMatrix; // TODO - depthViewMatrix.lookAt(lightPos, QVector3D(0.0f, -m_yAdjustment, zComp), - QVector3D(0.0f, 1.0f, 0.0f)); // TODO: Move - - // Enable texturing - glEnable(GL_TEXTURE_2D); - - // - // Do the surface drawing - // - - if (m_querySelection && m_surfaceObj) { - m_selectionShader->bind(); - glBindFramebuffer(GL_FRAMEBUFFER, m_selectionFrameBuffer); - glEnable(GL_DEPTH_TEST); // Needed, otherwise the depth render buffer is not used - glClearColor(0, 0, 0, 0); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Needed for clearing the frame buffer - glDisable(GL_DITHER); // disable dithering, it may affect colors if enabled - - glDisable(GL_CULL_FACE); - - QMatrix4x4 modelMatrix; - QMatrix4x4 MVPMatrix; - - modelMatrix.translate(0.0f, 1.0f - m_yAdjustment, zComp); - modelMatrix.scale(QVector3D(m_xLength / m_scaleFactor, - 1.0f, - m_zLength / m_scaleFactor)); - - MVPMatrix = projectionMatrix * viewMatrix * modelMatrix; - - m_selectionShader->setUniformValue(m_selectionShader->MVP(), MVPMatrix); - - // Activate texture - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, m_selectionTexture); - m_selectionShader->setUniformValue(m_selectionShader->texture(), 0); - - // 1st attribute buffer : vertices - glEnableVertexAttribArray(m_selectionShader->posAtt()); - glBindBuffer(GL_ARRAY_BUFFER, m_surfaceObj->vertexBuf()); - glVertexAttribPointer(m_selectionShader->posAtt(), 3, GL_FLOAT, GL_FALSE, 0, (void *)0); - - // 3rd attribute buffer : UVs - glEnableVertexAttribArray(m_selectionShader->uvAtt()); - glBindBuffer(GL_ARRAY_BUFFER, m_surfaceObj->uvBuf()); - glVertexAttribPointer(m_selectionShader->uvAtt(), 2, GL_FLOAT, GL_FALSE, 0, (void *)0); - - // Index buffer - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_surfaceObj->elementBuf()); - - // Draw the triangles - glDrawElements(GL_TRIANGLES, m_surfaceObj->indexCount(), m_surfaceObj->indicesType(), (void *)0); - //m_drawer->drawObject(m_selectionShader, m_surfaceObj, m_selectionTexture, 0); - - // Free buffers - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - glBindBuffer(GL_ARRAY_BUFFER, 0); - - glDisableVertexAttribArray(m_selectionShader->uvAtt()); - glDisableVertexAttribArray(m_selectionShader->posAtt()); - - glEnable(GL_DITHER); - - m_querySelection = false; - - QPoint point = m_controller->mousePosition(); - GLubyte pixel[4] = {0}; - glReadPixels(point.x(), height() - point.y(), 1, 1, - GL_RGBA, GL_UNSIGNED_BYTE, (void *)pixel); - //uint id = pixel[0] + pixel[1] * 256 + pixel[2] * 65536 + pixel[3] * 16777216; - - qDebug() << "pixel = " << pixel[0] << ", " << pixel[1] << ", " << pixel[2] << ", " << pixel[3]; - - glBindFramebuffer(GL_FRAMEBUFFER, defaultFboHandle); - - // Release selection shader - m_selectionShader->release(); - } - - if (m_surfaceObj) { - m_surfaceShader->bind(); - // m_selectionShader->bind(); // IFDEF print selection - - // For surface we can see climpses from underneath - glDisable(GL_CULL_FACE); - - QMatrix4x4 modelMatrix; - QMatrix4x4 MVPMatrix; - QMatrix4x4 depthMVPMatrix; - QMatrix4x4 itModelMatrix; - - modelMatrix.translate(0.0f, 1.0f - m_yAdjustment, zComp); - modelMatrix.scale(QVector3D(m_xLength / m_scaleFactor, - 1.0f, - m_zLength / m_scaleFactor)); - itModelMatrix.scale(QVector3D(m_xLength / m_scaleFactor, - 1.0f, - m_zLength / m_scaleFactor)); - -#ifdef SHOW_DEPTH_TEXTURE_SCENE - MVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; -#else - MVPMatrix = projectionMatrix * viewMatrix * modelMatrix; -#endif - // TODO Check the usage? - depthMVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; - - // Set shader bindings - m_surfaceShader->setUniformValue(m_surfaceShader->lightP(), lightPos); - m_surfaceShader->setUniformValue(m_surfaceShader->view(), viewMatrix); - m_surfaceShader->setUniformValue(m_surfaceShader->model(), modelMatrix); - m_surfaceShader->setUniformValue(m_surfaceShader->nModel(), itModelMatrix.inverted().transposed()); - m_surfaceShader->setUniformValue(m_surfaceShader->MVP(), MVPMatrix); - //m_selectionShader->setUniformValue(m_selectionShader->MVP(), MVPMatrix); // IFDEF print selection - m_surfaceShader->setUniformValue(m_surfaceShader->ambientS(), m_cachedTheme.m_ambientStrength); - - //IF QT_OPENGL_ES_2 TODO - // Shadow quality etc. - //m_backgroundShader->setUniformValue(m_backgroundShader->shadowQ(), m_shadowQualityToShader); - //m_backgroundShader->setUniformValue(m_backgroundShader->depth(), depthMVPMatrix); - m_surfaceShader->setUniformValue(m_surfaceShader->lightS(), - m_cachedTheme.m_lightStrength * 2.0f); - - m_drawer->drawObject(m_surfaceShader, m_surfaceObj, m_gradientTexture, m_depthTexture); - //m_drawer->drawObject(m_selectionShader, m_surfaceObj, m_selectionTexture, 0); // IFDEF print selection - - m_surfaceShader->release(); - //m_selectionShader->release(); // IFDEF print selection - - if (m_cachedSurfaceGridOn) { - // Draw the grid over the surface - glPolygonOffset(1.0f, 1.0f); - glEnable(GL_POLYGON_OFFSET_FILL); - - m_surfaceGridShader->bind(); - - QVector3D gridColor = Utils::vectorFromColor(QColor(Qt::white)); - // Set shader bindings - m_surfaceGridShader->setUniformValue(m_surfaceGridShader->view(), viewMatrix); - m_surfaceGridShader->setUniformValue(m_surfaceGridShader->model(), modelMatrix); - m_surfaceGridShader->setUniformValue(m_surfaceGridShader->nModel(), itModelMatrix.inverted().transposed()); - m_surfaceGridShader->setUniformValue(m_surfaceGridShader->MVP(), MVPMatrix); - m_surfaceGridShader->setUniformValue(m_surfaceGridShader->color(), gridColor); - //m_surfaceGridShader->setUniformValue(m_surfaceGridShader->ambientS(), m_theme->m_ambientStrength); - m_drawer->drawSurfaceGrid(m_surfaceGridShader, m_surfaceObj); - - m_surfaceGridShader->release(); - - glPolygonOffset(0.0f, 0.0f); - glDisable(GL_POLYGON_OFFSET_FILL); - } - } - - // Bind background shader - m_backgroundShader->bind(); - - if (m_hasNegativeValues) - glDisable(GL_CULL_FACE); - else - glCullFace(GL_BACK); - - // Draw background - if (m_isBackgroundEnabled && m_backgroundObj) { - QMatrix4x4 modelMatrix; - QMatrix4x4 MVPMatrix; - QMatrix4x4 depthMVPMatrix; - QMatrix4x4 itModelMatrix; - - modelMatrix.translate(0.0f, 1.0f - m_yAdjustment, zComp); - modelMatrix.scale(QVector3D(m_xLength / m_scaleFactor, - 1.0f, - m_zLength / m_scaleFactor)); - modelMatrix.rotate(backgroundRotation, 0.0f, 1.0f, 0.0f); - itModelMatrix.scale(QVector3D(m_xLength / m_scaleFactor, - 1.0f, - m_zLength / m_scaleFactor)); - -#ifdef SHOW_DEPTH_TEXTURE_SCENE - MVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; -#else - MVPMatrix = projectionMatrix * viewMatrix * modelMatrix; -#endif - depthMVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; - - QVector3D backgroundColor = Utils::vectorFromColor(m_cachedTheme.m_backgroundColor); - - // Set shader bindings - m_backgroundShader->setUniformValue(m_backgroundShader->lightP(), lightPos); - m_backgroundShader->setUniformValue(m_backgroundShader->view(), viewMatrix); - m_backgroundShader->setUniformValue(m_backgroundShader->model(), modelMatrix); - m_backgroundShader->setUniformValue(m_backgroundShader->nModel(), - itModelMatrix.inverted().transposed()); - m_backgroundShader->setUniformValue(m_backgroundShader->MVP(), MVPMatrix); - m_backgroundShader->setUniformValue(m_backgroundShader->color(), backgroundColor); - m_backgroundShader->setUniformValue(m_backgroundShader->ambientS(), - m_cachedTheme.m_ambientStrength * 2.0f); - -#if !defined(QT_OPENGL_ES_2) - if (m_shadowQuality > QDataVis::ShadowNone) { - // Set shadow shader bindings - m_backgroundShader->setUniformValue(m_backgroundShader->shadowQ(), - m_shadowQualityToShader); - m_backgroundShader->setUniformValue(m_backgroundShader->depth(), depthMVPMatrix); - m_backgroundShader->setUniformValue(m_backgroundShader->lightS(), - m_cachedTheme.m_lightStrength / 10.0f); - - // Draw the object - m_drawer->drawObject(m_backgroundShader, m_backgroundObj, 0, m_depthTexture); - } else -#endif - { - // Set shadowless shader bindings - m_backgroundShader->setUniformValue(m_backgroundShader->lightS(), - m_cachedTheme.m_lightStrength); - - // Draw the object - m_drawer->drawObject(m_backgroundShader, m_backgroundObj); - } - } - - // Release background shader - m_backgroundShader->release(); - - // Disable textures - glDisable(GL_TEXTURE_2D); - - // Reset culling - if (m_hasNegativeValues) { - glEnable(GL_CULL_FACE); - glCullFace(GL_BACK); - } -} - -void Surface3dRenderer::updateSegmentCount(GLint segmentCount, GLfloat step, GLfloat minimum) -{ - m_segmentYCount = segmentCount; - m_segmentYStep = step; - if (segmentCount > 0 && step > 0.0) { - m_yRange = m_segmentYCount * m_segmentYStep; - m_yAdjustment = 2.0f - ((m_yRange - minimum) / m_yRange); // TODO: to function - } - - qDebug() << "m_yAdjustment = " << m_yAdjustment; -} - -void Surface3dRenderer::setXZStuff(GLint segmentXCount, GLint segmentZCount) -{ - m_segmentXCount = segmentXCount; - m_segmentZCount = segmentZCount; - - // TODO: Invent "idiotproof" max scene size formula.. - // This seems to work ok if spacing is not negative (and row/column or column/row ratio is not too high) - m_maxSceneSize = 2 * qSqrt(segmentXCount * segmentZCount); - - calculateSceneScalingFactors(); -} - -void Surface3dRenderer::updateTheme(Theme theme) -{ - m_cachedTheme.setFromTheme(theme); - - // Update things depending from the theme - updateSurfaceGradient(); -} - -void Surface3dRenderer::updateSurfaceGradient() -{ - QImage image(QSize(4, 100), QImage::Format_RGB32); - QPainter pmp(&image); - pmp.setBrush(QBrush(m_cachedTheme.m_surfaceGradient)); - pmp.setPen(Qt::NoPen); - pmp.drawRect(0, 0, 4, 100); - - // QImage image(QStringLiteral("C:\\Users\\misalmel\\Work\\gerrit\\qtdatavis3d_2\\grid.png")); - - if (m_gradientTexture) { - m_textureHelper->deleteTexture(&m_gradientTexture); - m_gradientTexture = 0; - } - - m_gradientTexture = m_textureHelper->create2DTexture(image, false, true); -} - -void Surface3dRenderer::updateSelectionTexture() -{ - // Create the selection ID image. Each grid corner gets 2x2 pixel area of - // ID color so that each vertex (data point) has 4x4 pixel area of ID color - // TODO: power of two thing for ES - int idImageWidth = (m_segmentXCount - 1) * 4; - int idImageHeight = (m_segmentZCount - 1) * 4; - int stride = idImageWidth * 4 * sizeof(uchar); // 4 = number of color components (rgba) - - uchar *bits = new uchar[idImageWidth * idImageHeight * 4 * sizeof(uchar)]; - uint id = 1; - for (int i = 0; i < idImageHeight; i += 4) { - for (int j = 0; j < idImageWidth; j += 4) { - int p = (i * idImageWidth + j) * 4; - uchar r, g, b, a; - idToRGBA(id, &r, &g, &b, &a); - fillIdCorner(&bits[p], r, g, b, a, stride); - - idToRGBA(id + 1, &r, &g, &b, &a); - fillIdCorner(&bits[p + 8], r, g, b, a, stride); - - idToRGBA(id + m_segmentXCount, &r, &g, &b, &a); - fillIdCorner(&bits[p + 2 * stride], r, g, b, a, stride); - - idToRGBA(id + m_segmentXCount + 1, &r, &g, &b, &a); - fillIdCorner(&bits[p + 2 * stride + 8], r, g, b, a, stride); - - id++; - } - id++; - } - - // Use this to save the ID image to file - //QImage image(bits, idImageWidth, idImageHeight, QImage::Format_ARGB32); - //image.save("C:\\Users\\misalmel\\Work\\gerrit\\qtdatavis3d_2\\selection.png"); - - // If old texture exists, delete it - if (m_selectionTexture) { - m_textureHelper->deleteTexture(&m_selectionTexture); - m_selectionTexture = 0; - } - - // Move the ID image (bits) to the texture - m_selectionTexture = m_textureHelper->create2DTexture(bits, idImageWidth, idImageHeight); - - // Release the temp bits allocation - delete bits; - - // Create the result selection texture and buffers - if (m_selectionResultTexture) { - m_textureHelper->deleteTexture(&m_selectionResultTexture); - m_selectionResultTexture = 0; - } - - m_selectionResultTexture = m_textureHelper->createSelectionTexture(m_mainViewPort.size(), - m_selectionFrameBuffer, - m_selectionDepthBuffer); -} - -void Surface3dRenderer::fillIdCorner(uchar *p, uchar r, uchar g, uchar b, uchar a, int stride) -{ - p[0] = r; - p[1] = g; - p[2] = b; - p[3] = a; - p[4] = r; - p[5] = g; - p[6] = b; - p[7] = a; - p[stride + 0] = r; - p[stride + 1] = g; - p[stride + 2] = b; - p[stride + 3] = a; - p[stride + 4] = r; - p[stride + 5] = g; - p[stride + 6] = b; - p[stride + 7] = a; -} - -void Surface3dRenderer::idToRGBA(uint id, uchar *r, uchar *g, uchar *b, uchar *a) -{ - *r = id & ID_TO_RGBA_MASK; - *g = (id >> 8) & ID_TO_RGBA_MASK; - *b = (id >> 16) & ID_TO_RGBA_MASK; - *a = (id >> 24) & ID_TO_RGBA_MASK; -} - -void Surface3dRenderer::getSelection() -{ - qDebug() << "Surface3dRenderer::getSelection"; - m_querySelection = true; -} - -void Surface3dRenderer::setSeries(QList<qreal> series) -{ - m_series = series; - - // TODO temp solution - if (!m_surfaceObj) - loadSurfaceObj(); - - if (m_cachedSmoothSurface) - m_surfaceObj->setUpSmoothData(series, m_segmentXCount, m_segmentZCount, m_yRange, true); - else - m_surfaceObj->setUpData(series, m_segmentXCount, m_segmentZCount, m_yRange, true); - - updateSelectionTexture(); -} - -void Surface3dRenderer::calculateSceneScalingFactors() -{ - // Calculate scene scaling and translation factors - // m_rowWidth = ((m_columnCount + 1) * m_barSpacing.width()) / 2.0f; - // m_columnDepth = ((m_rowCount + 1) * m_barSpacing.height()) / 2.0f; - // m_maxDimension = qMax(m_rowWidth, m_columnDepth); - // m_scaleFactor = qMin((m_columnCount * (m_maxDimension / m_maxSceneSize)), - // (m_rowCount * (m_maxDimension / m_maxSceneSize))); - // m_scaleX = m_barThickness.width() / m_scaleFactor; - // m_scaleZ = m_barThickness.height() / m_scaleFactor; - - m_xLength = m_segmentXCount; - m_zLength = m_segmentZCount; - m_maxDimension = qMax(m_xLength, m_zLength); - m_scaleFactor = qMin((m_segmentXCount * (m_maxDimension / m_maxSceneSize)), - (m_segmentZCount * (m_maxDimension / m_maxSceneSize))); - m_scaleX = 1.0f / m_scaleFactor; // TODO: correspondance to m_barThickness - m_scaleZ = 1.0f / m_scaleFactor; // TODO: correspondance to m_barThickness - - //qDebug() << "m_scaleX" << m_scaleX << "m_scaleFactor" << m_scaleFactor; - //qDebug() << "m_scaleZ" << m_scaleZ << "m_scaleFactor" << m_scaleFactor; - //qDebug() << "m_rowWidth:" << m_rowWidth << "m_columnDepth:" << m_columnDepth << "m_maxDimension:" << m_maxDimension; -} - -void Surface3dRenderer::updateSmoothStatus(bool enable) -{ - m_cachedSmoothSurface = enable; - - if (!m_surfaceObj) - return; - - if (m_cachedSmoothSurface) - m_surfaceObj->setUpSmoothData(m_series, m_segmentXCount, m_segmentZCount, m_yRange, true); - else - m_surfaceObj->setUpData(m_series, m_segmentXCount, m_segmentZCount, m_yRange, true); - - initSurfaceShaders(); -} - -void Surface3dRenderer::updateSurfaceGridStatus(bool enable) -{ - m_cachedSurfaceGridOn = enable; -} - -void Surface3dRenderer::loadBackgroundMesh() -{ - if (!m_isInitialized) - return; - - if (m_backgroundObj) - delete m_backgroundObj; - if (m_hasNegativeValues) - m_backgroundObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/negativeBackground")); - else - m_backgroundObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/background")); - m_backgroundObj->load(); -} - -void Surface3dRenderer::loadSurfaceObj() -{ - if (!m_isInitialized) - return; - - if (m_surfaceObj) - delete m_surfaceObj; - m_surfaceObj = new SurfaceObject(); - //m_surfaceObj->setUpData(); -} - -void Surface3dRenderer::loadGridLineMesh() -{ - if (m_gridLineObj) - delete m_gridLineObj; - m_gridLineObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/bar")); - m_gridLineObj->load(); -} - -const QSize Surface3dRenderer::size() -{ - return m_boundingRect.size(); -} - -const QRect Surface3dRenderer::boundingRect() -{ - return m_boundingRect; -} - -void Surface3dRenderer::setBoundingRect(const QRect boundingRect) -{ - m_boundingRect = boundingRect; - handleResize(); -} - -void Surface3dRenderer::setWidth(const int width) -{ - m_boundingRect.setWidth(width); - handleResize(); -} - -int Surface3dRenderer::width() -{ - return m_boundingRect.width(); -} - -void Surface3dRenderer::setHeight(const int height) -{ - m_boundingRect.setHeight(height); - handleResize(); -} - -int Surface3dRenderer::height() -{ - return m_boundingRect.height(); -} - -void Surface3dRenderer::setX(const int x) -{ - m_boundingRect.setX(x); -} - -int Surface3dRenderer::x() -{ - return m_boundingRect.x(); -} - -void Surface3dRenderer::setY(const int y) -{ - m_boundingRect.setY(y); -} - -int Surface3dRenderer::y() -{ - return m_boundingRect.y(); -} - -void Surface3dRenderer::handleResize() -{ - if (!m_isInitialized) - return; - - qDebug() << "Surface3dRenderer::handleResize " << width() << "x" << height(); - - m_mainViewPort = QRect(0, 0, width(), height()); - m_sliceViewPort = QRect(0, 0, width(), height()); - -#if !defined(QT_OPENGL_ES_2) - // Re-init depth buffer - updateDepthBuffer(); -#endif -} - -#if !defined(QT_OPENGL_ES_2) -void Surface3dRenderer::updateDepthBuffer() -{ - if (m_depthTexture) { - m_textureHelper->deleteTexture(&m_depthTexture); - m_depthTexture = 0; - } - - // TODO: bars uses some m_cachedShadowQuality - if (m_shadowQuality > QDataVis::ShadowNone && !m_mainViewPort.size().isEmpty()) { - m_depthTexture = m_textureHelper->createDepthTexture(m_mainViewPort.size(), - m_depthFrameBuffer, - m_shadowQuality); - if (!m_depthTexture) { - qDebug() << "Failed to create m_depthTexture"; - // switch (m_shadowQuality) { - // case ShadowHigh: - // qWarning("Creating high quality shadows failed. Changing to medium quality."); - // (void)setShadowQuality(ShadowMedium); - // break; - // case ShadowMedium: - // qWarning("Creating medium quality shadows failed. Changing to low quality."); - // (void)setShadowQuality(ShadowLow); - // break; - // case ShadowLow: - // qWarning("Creating low quality shadows failed. Switching shadows off."); - // (void)setShadowQuality(ShadowNone); - // break; - // default: - // // You'll never get here - // break; - // } - } - } -} -#endif - -void Surface3dRenderer::initBackgroundShaders(const QString &vertexShader, - const QString &fragmentShader) -{ - if (m_backgroundShader) - delete m_backgroundShader; - m_backgroundShader = new ShaderHelper(this, vertexShader, fragmentShader); - m_backgroundShader->initialize(); -} - -void Surface3dRenderer::initSelectionShaders() -{ - if (m_selectionShader) - delete m_selectionShader; - m_selectionShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexLabel"), - QStringLiteral(":/shaders/fragmentLabel")); - m_selectionShader->initialize(); -} - -void Surface3dRenderer::initSurfaceShaders() -{ - if (m_surfaceShader) - delete m_surfaceShader; - if (m_cachedSmoothSurface) { - m_surfaceShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexSurface"), - QStringLiteral(":/shaders/fragmentSurface")); - } else { - m_surfaceShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexSurfaceFlat"), - QStringLiteral(":/shaders/fragmentSurfaceFlat")); - } - m_surfaceShader->initialize(); - - if (m_surfaceGridShader) - delete m_surfaceGridShader; - m_surfaceGridShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexSurfaceGrid"), - QStringLiteral(":/shaders/fragmentSurfaceGrid")); - m_surfaceGridShader->initialize(); -} - -QT_DATAVIS3D_END_NAMESPACE - - -//p = 90; -//qDebug() << "rgba = " << bits[p + 0] << ", " << bits[p + 1] << ", " << -// bits[p + 2] << ", " << bits[p + 3]; -//p += 4; -//qDebug() << "rgba = " << bits[p + 0] << ", " << bits[p + 1] << ", " << -// bits[p + 2] << ", " << bits[p + 3]; -//p += 4; -//qDebug() << "rgba = " << bits[p + 0] << ", " << bits[p + 1] << ", " << -// bits[p + 2] << ", " << bits[p + 3]; -//p += 4; -//qDebug() << "rgba = " << bits[p + 0] << ", " << bits[p + 1] << ", " << -// bits[p + 2] << ", " << bits[p + 3]; -//p += 4; -//qDebug() << "rgba = " << bits[p + 0] << ", " << bits[p + 1] << ", " << -// bits[p + 2] << ", " << bits[p + 3]; -//p += 4; - diff --git a/src/datavis3d/engine/theme.cpp b/src/datavis3d/engine/theme.cpp deleted file mode 100644 index 7b2cb210..00000000 --- a/src/datavis3d/engine/theme.cpp +++ /dev/null @@ -1,307 +0,0 @@ -/**************************************************************************** -** -** 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 QtDataVis3D 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 "theme_p.h" - -#ifdef Q_OS_WIN -#include <windows.h> -#include <stdio.h> -#endif - -QT_DATAVIS3D_BEGIN_NAMESPACE - -Theme::Theme() - : m_baseColor(QColor(Qt::gray)), - m_heightColor(QColor(Qt::black)), - m_depthColor(QColor(Qt::black)), - m_backgroundColor(QColor(Qt::gray)), - m_windowColor(QColor(Qt::gray)), - m_textColor(QColor(Qt::white)), - m_textBackgroundColor(QColor(0x00, 0x00, 0x00, 0x80)), - m_gridLine(QColor(Qt::black)), - m_highlightBarColor(QColor(Qt::red)), - m_highlightRowColor(QColor(Qt::darkRed)), - m_highlightColumnColor(QColor(Qt::darkMagenta)), - m_surfaceGradient(QLinearGradient(1, 100, 0, 0)), - m_lightStrength(4.0f), - m_ambientStrength(0.3f), - m_highlightLightStrength(8.0f), - m_uniformColor(true) -{ - // Default values for surface gradient - m_surfaceGradient.setColorAt(0.0, Qt::green); - m_surfaceGradient.setColorAt(0.5, Qt::yellow); - m_surfaceGradient.setColorAt(1.0, Qt::red); -} - -Theme::~Theme() -{ -} - -QDataVis::ColorTheme Theme::colorTheme() -{ - return m_colorTheme; -} - -void Theme::useColorTheme(QDataVis::ColorTheme colorTheme) -{ - m_colorTheme = colorTheme; - switch (colorTheme) { - case QDataVis::ThemeSystem: { -#ifdef Q_OS_WIN - DWORD colorHighlight; - colorHighlight = GetSysColor(COLOR_HIGHLIGHT); - m_baseColor = QColor(GetRValue(colorHighlight), - GetGValue(colorHighlight), - GetBValue(colorHighlight)); - DWORD colorWindowFrame; - colorWindowFrame = GetSysColor(COLOR_WINDOWFRAME); - m_heightColor = QColor(GetRValue(colorWindowFrame), - GetGValue(colorWindowFrame), - GetBValue(colorWindowFrame)); - m_depthColor = QColor(Qt::black); - DWORD colorWindow; - colorWindow = GetSysColor(COLOR_WINDOW); - m_backgroundColor = QColor(GetRValue(colorWindow), - GetGValue(colorWindow), - GetBValue(colorWindow)); - m_windowColor = QColor(GetRValue(colorWindow), - GetGValue(colorWindow), - GetBValue(colorWindow)); - m_textColor = QColor(QRgb(0x404044)); - m_textBackgroundColor = QColor(0xd6, 0xd6, 0xd6, 0x80); - m_gridLine = QColor(QRgb(0xe2e2e2)); - m_highlightBarColor = QColor(QRgb(0xe2e2e2)); - m_highlightRowColor = QColor(QRgb(0xf2f2f2)); - m_highlightColumnColor = QColor(QRgb(0xf2f2f2)); - m_lightStrength = 4.0f; - m_ambientStrength = 0.3f; - m_highlightLightStrength = 6.0f; - m_uniformColor = true; -#elif defined(Q_OS_LINUX) - m_baseColor = QColor(QRgb(0x60a6e6)); - m_heightColor = QColor(QRgb(0xfc5751)); - m_depthColor = QColor(QRgb(0x92ca66)); - m_backgroundColor = QColor(QRgb(0xffffff)); - m_windowColor = QColor(QRgb(0xffffff)); - m_textColor = QColor(QRgb(0x404044)); - m_textBackgroundColor = QColor(0xd6, 0xd6, 0xd6, 0x80); - m_gridLine = QColor(QRgb(0xe2e2e2)); - m_highlightBarColor = QColor(QRgb(0xeba85f)); - m_highlightRowColor = QColor(QRgb(0xfc5751)); - m_highlightColumnColor = QColor(QRgb(0xfc5751)); - m_lightStrength = 4.0f; - m_ambientStrength = 0.3f; - m_highlightLightStrength = 6.0f; - m_uniformColor = true; -#elif defined(Q_OS_MAC) - m_baseColor = QColor(QRgb(0x60a6e6)); - m_heightColor = QColor(QRgb(0xfc5751)); - m_depthColor = QColor(QRgb(0x92ca66)); - m_backgroundColor = QColor(QRgb(0xffffff)); - m_windowColor = QColor(QRgb(0xffffff)); - m_textColor = QColor(QRgb(0x404044)); - m_textBackgroundColor = QColor(0xd6, 0xd6, 0xd6, 0x80); - m_gridLine = QColor(QRgb(0xe2e2e2)); - m_highlightBarColor = QColor(QRgb(0xeba85f)); - m_highlightRowColor = QColor(QRgb(0xfc5751)); - m_highlightColumnColor = QColor(QRgb(0xfc5751)); - m_lightStrength = 4.0f; - m_ambientStrength = 0.3f; - m_highlightLightStrength = 6.0f; - m_uniformColor = true; -#else - m_baseColor = QColor(QRgb(0x60a6e6)); - m_heightColor = QColor(QRgb(0xfc5751)); - m_depthColor = QColor(QRgb(0x92ca66)); - m_backgroundColor = QColor(QRgb(0xffffff)); - m_windowColor = QColor(QRgb(0xffffff)); - m_textColor = QColor(QRgb(0x404044)); - m_textBackgroundColor = QColor(0xd6, 0xd6, 0xd6, 0x80); - m_gridLine = QColor(QRgb(0xe2e2e2)); - m_highlightBarColor = QColor(QRgb(0xeba85f)); - m_highlightRowColor = QColor(QRgb(0xfc5751)); - m_highlightColumnColor = QColor(QRgb(0xfc5751)); - m_lightStrength = 4.0f; - m_ambientStrength = 0.3f; - m_highlightLightStrength = 6.0f; - m_uniformColor = true; -#endif - qDebug("ThemeSystem"); - break; - } - case QDataVis::ThemeBlueCerulean: { - m_baseColor = QColor(QRgb(0xc7e85b)); - m_heightColor = QColor(QRgb(0xee7392)); - m_depthColor = QColor(QRgb(0x1cb54f)); - m_backgroundColor = QColor(QRgb(0x056189)); - m_windowColor = QColor(QRgb(0x101a31)); - m_textColor = QColor(QRgb(0xffffff)); - m_textBackgroundColor = QColor(0x05, 0x61, 0x89, 0x80); - m_gridLine = QColor(QRgb(0x84a2b0)); - m_highlightBarColor = QColor(QRgb(0x5cbf9b)); - m_highlightRowColor = QColor(QRgb(0x009fbf)); - m_highlightColumnColor = QColor(QRgb(0x009fbf)); - m_lightStrength = 5.0f; - m_ambientStrength = 0.2f; - m_highlightLightStrength = 10.0f; - m_uniformColor = true; - qDebug("ThemeBlueCerulean"); - break; - } - case QDataVis::ThemeBlueIcy: { - m_baseColor = QRgb(0x3daeda); - m_heightColor = QRgb(0x2fa3b4); - m_depthColor = QColor(QRgb(0x2685bf)); - m_backgroundColor = QColor(QRgb(0xffffff)); - m_windowColor = QColor(QRgb(0xffffff)); - m_textColor = QColor(QRgb(0x404044)); - m_textBackgroundColor = QColor(0xff, 0xff, 0xff, 0x80); - m_gridLine = QColor(QRgb(0xe2e2e2)); - m_highlightBarColor = QColor(QRgb(0x0c2673)); - m_highlightRowColor = QColor(QRgb(0x5f3dba)); - m_highlightColumnColor = QColor(QRgb(0x5f3dba)); - m_lightStrength = 5.0f; - m_ambientStrength = 0.3f; - m_highlightLightStrength = 8.0f; - m_uniformColor = true; - qDebug("ThemeBlueIcy"); - break; - } - case QDataVis::ThemeBlueNcs: { - m_baseColor = QColor(QRgb(0x1db0da)); - m_heightColor = QColor(QRgb(0x398ca3)); - m_depthColor = QColor(QRgb(0x1341a6)); - m_backgroundColor = QColor(QRgb(0xffffff)); - m_windowColor = QColor(QRgb(0xffffff)); - m_textColor = QColor(QRgb(0x404044)); - m_textBackgroundColor = QColor(0xff, 0xff, 0xff, 0x80); - m_gridLine = QColor(QRgb(0xe2e2e2)); - m_highlightBarColor = QColor(QRgb(0x88d41e)); - m_highlightRowColor = QColor(QRgb(0xff8e1a)); - m_highlightColumnColor = QColor(QRgb(0xff8e1a)); - m_lightStrength = 4.0f; - m_ambientStrength = 0.2f; - m_highlightLightStrength = 6.0f; - m_uniformColor = true; - qDebug("ThemeBlueNcs"); - break; - } - case QDataVis::ThemeBrownSand: { - m_baseColor = QColor(QRgb(0xb39b72)); - m_heightColor = QColor(QRgb(0x494345)); - m_depthColor = QColor(QRgb(0xb3b376)); - m_backgroundColor = QColor(QRgb(0xf3ece0)); - m_windowColor = QColor(QRgb(0xf3ece0)); - m_textColor = QColor(QRgb(0x404044)); - m_textBackgroundColor = QColor(0xb5, 0xb0, 0xa7, 0x80); - m_gridLine = QColor(QRgb(0xd4cec3)); - m_highlightBarColor = QColor(QRgb(0xc35660)); - m_highlightRowColor = QColor(QRgb(0x536780)); - m_highlightColumnColor = QColor(QRgb(0x536780)); - m_lightStrength = 6.0f; - m_ambientStrength = 0.3f; - m_highlightLightStrength = 8.0f; - m_uniformColor = false; - qDebug("ThemeBrownSand"); - break; - } - case QDataVis::ThemeDark: { - m_baseColor = QColor(QRgb(0x38ad6b)); // charts: series color 1 - m_heightColor = QColor(QRgb(0xbf593e)); // charts: series color 5 - m_depthColor = QColor(QRgb(0x3c84a7)); // charts: series color 2 - m_backgroundColor = QColor(QRgb(0x2e303a)); // charts: background color 1 - m_windowColor = QColor(QRgb(0x121218)); // charts: background color 2 - m_textColor = QColor(QRgb(0xffffff)); // charts: label color - m_textBackgroundColor = QColor(0x86, 0x87, 0x8c, 0x80); // charts: axis line pen OR background color 2 - m_gridLine = QColor(QRgb(0x86878c)); // charts: grid line color - m_highlightBarColor = QColor(QRgb(0xeb8817)); // charts: series color 3 - m_highlightRowColor = QColor(QRgb(0x7b7f8c)); // charts: series color 4 - m_highlightColumnColor = QColor(QRgb(0x7b7f8c)); // charts: series color 4 - m_lightStrength = 6.0f; - m_ambientStrength = 0.2f; - m_highlightLightStrength = 8.0f; - m_uniformColor = false; - qDebug("ThemeDark"); - break; - } - case QDataVis::ThemeHighContrast: { - m_baseColor = QColor(QRgb(0x202020)); - m_heightColor = QColor(QRgb(0xff4a41)); - m_depthColor = QColor(QRgb(0x596a74)); - m_backgroundColor = QColor(QRgb(0xffffff)); - m_windowColor = QColor(QRgb(0x000000)); - m_textColor = QColor(QRgb(0x181818)); - m_textBackgroundColor = QColor(0xff, 0xff, 0xff, 0x80); - m_gridLine = QColor(QRgb(0x8c8c8c)); - m_highlightBarColor = QColor(QRgb(0xffab03)); - m_highlightRowColor = QColor(QRgb(0x038e9b)); - m_highlightColumnColor = QColor(QRgb(0x038e9b)); - m_lightStrength = 8.0f; - m_ambientStrength = 0.3f; - m_highlightLightStrength = 10.0f; - m_uniformColor = false; - qDebug("ThemeHighContrast"); - break; - } - case QDataVis::ThemeLight: { - m_baseColor = QColor(QRgb(0x209fdf)); - m_heightColor = QColor(QRgb(0xbf593e)); - m_depthColor = QColor(QRgb(0x99ca53)); - m_backgroundColor = QColor(QRgb(0xffffff)); - m_windowColor = QColor(QRgb(0xffffff)); - m_textColor = QColor(QRgb(0x404044)); - m_textBackgroundColor = QColor(0xd6, 0xd6, 0xd6, 0x80); - m_gridLine = QColor(QRgb(0xe2e2e2)); - m_highlightBarColor = QColor(QRgb(0xf6a625)); - m_highlightRowColor = QColor(QRgb(0x6d5fd5)); - m_highlightColumnColor = QColor(QRgb(0x6d5fd5)); - m_lightStrength = 6.0f; - m_ambientStrength = 0.3f; - m_highlightLightStrength = 7.0f; - m_uniformColor = true; - qDebug("ThemeLight"); - break; - } - default: - break; - } -} - -void Theme::setFromTheme(Theme &theme) -{ - m_colorTheme = theme.m_colorTheme; - m_baseColor = theme.m_baseColor; - m_heightColor = theme.m_heightColor; - m_depthColor = theme.m_depthColor; - m_backgroundColor = theme.m_backgroundColor; - m_windowColor = theme.m_windowColor; - m_textColor = theme.m_textColor; - m_textBackgroundColor = theme.m_textBackgroundColor; - m_gridLine = theme.m_gridLine; - m_highlightBarColor = theme.m_highlightBarColor; - m_highlightRowColor = theme.m_highlightRowColor; - m_highlightColumnColor = theme.m_highlightColumnColor; - m_surfaceGradient = theme.m_surfaceGradient; - m_lightStrength = theme.m_lightStrength; - m_ambientStrength = theme.m_ambientStrength; - m_highlightLightStrength = theme.m_highlightLightStrength; - m_uniformColor = theme.m_uniformColor; -} - -QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/global/global.pri b/src/datavis3d/global/global.pri deleted file mode 100644 index 7292bbd6..00000000 --- a/src/datavis3d/global/global.pri +++ /dev/null @@ -1,4 +0,0 @@ -HEADERS += \ - $$PWD/qdatavis3dglobal.h \ - $$PWD/qdatavis3denums.h \ - $$PWD/datavis3dglobal_p.h diff --git a/src/datavis3d/global/qdatavis3denums.h b/src/datavis3d/global/qdatavis3denums.h deleted file mode 100644 index a6384508..00000000 --- a/src/datavis3d/global/qdatavis3denums.h +++ /dev/null @@ -1,115 +0,0 @@ -/**************************************************************************** -** -** 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 QtDataVis3D 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 QDATAVIS3DENUMS_H -#define QDATAVIS3DENUMS_H - -#include <QtDataVis3D/qdatavis3dglobal.h> -#include <QObject> - -QT_DATAVIS3D_BEGIN_NAMESPACE - -class QT_DATAVIS3D_EXPORT QDataVis : public QObject -{ - Q_OBJECT - Q_ENUMS(MeshStyle) - Q_ENUMS(CameraPreset) - Q_ENUMS(ColorTheme) - Q_ENUMS(SelectionMode) - Q_ENUMS(ShadowQuality) - Q_ENUMS(LabelTransparency) - -public: - - enum MeshStyle { - Bars = 0, - Pyramids, - Cones, - Cylinders, - BevelBars, - Spheres, - Dots - }; - - enum CameraPreset { - NoPreset = -1, - PresetFrontLow = 0, - PresetFront, - PresetFrontHigh, - PresetLeftLow, - PresetLeft, - PresetLeftHigh, - PresetRightLow, - PresetRight, - PresetRightHigh, - PresetBehindLow, - PresetBehind, - PresetBehindHigh, - PresetIsometricLeft, - PresetIsometricLeftHigh, - PresetIsometricRight, - PresetIsometricRightHigh, - PresetDirectlyAbove, - PresetDirectlyAboveCW45, - PresetDirectlyAboveCCW45, - PresetFrontBelow, // These work only for graphs including negative values. - PresetLeftBelow, // They act as Preset...Low for positive-only values. - PresetRightBelow, - PresetBehindBelow, - PresetDirectlyBelow - }; - - enum ColorTheme { - ThemeDefault = -1, - ThemeSystem = 0, - ThemeBlueCerulean, - ThemeBlueIcy, - ThemeBlueNcs, - ThemeBrownSand, - ThemeDark, - ThemeHighContrast, - ThemeLight - }; - - enum SelectionMode { - ModeNone = 0, - ModeItem, - ModeItemAndRow, // From here onwards used for Q3DBars only - ModeItemAndColumn, - ModeItemRowAndColumn, - ModeZoomRow, - ModeZoomColumn - }; - - enum ShadowQuality { - ShadowNone = 0, - ShadowLow = 1, - ShadowMedium = 3, - ShadowHigh = 5 - }; - - enum LabelTransparency { - TransparencyNone = 0, // Full solid, using colors from theme - TransparencyFromTheme, // Use colors and transparencies from theme - TransparencyNoBackground // Draw just text on transparent background - }; -}; - -QT_DATAVIS3D_END_NAMESPACE - -#endif diff --git a/src/datavis3d/global/qdatavis3dglobal.h b/src/datavis3d/global/qdatavis3dglobal.h deleted file mode 100644 index 5e2e88b1..00000000 --- a/src/datavis3d/global/qdatavis3dglobal.h +++ /dev/null @@ -1,67 +0,0 @@ -/**************************************************************************** -** -** 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 QtDataVis3D 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 QDATAVIS3DGLOBAL_H -#define QDATAVIS3DGLOBAL_H - -#include <qglobal.h> - -#define QT_DATAVIS3D_VERSION_STR "0.0.1" -/* - QT_DATAVIS3D_VERSION is (major << 16) + (minor << 8) + patch. -*/ -#define QT_DATAVIS3D_VERSION 0x000001 -/* - can be used like #if (QT_DATAVIS3D_VERSION >= QT_DATAVIS3D_VERSION_CHECK(1, 1, 0)) -*/ -#define QT_DATAVIS3D_VERSION_CHECK(major, minor, patch) ((major<<16)|(minor<<8)|(patch)) - -#if defined(QT_DATAVIS3D_LIBRARY) -# define QT_DATAVIS3D_EXPORT Q_DECL_EXPORT -#else -# define QT_DATAVIS3D_EXPORT Q_DECL_IMPORT -#endif - -#if defined(BUILD_PRIVATE_UNIT_TESTS) && defined(QT_DATAVIS3D_LIBRARY) -# define QT_DATAVIS3D_AUTOTEST_EXPORT Q_DECL_EXPORT -#elif defined(BUILD_PRIVATE_UNIT_TESTS) && !defined(QT_DATAVIS3D_LIBRARY) -# define QT_DATAVIS3D_AUTOTEST_EXPORT Q_DECL_IMPORT -#else -# define QT_DATAVIS3D_AUTOTEST_EXPORT -#endif - -#ifdef QT_DATAVIS3D_STATICLIB -# undef QT_DATAVIS3D_EXPORT -# undef QT_DATAVIS3D_AUTOTEST_EXPORT -# define QT_DATAVIS3D_EXPORT -# define QT_DATAVIS3D_AUTOTEST_EXPORT -#endif - -#define QT_DATAVIS3D_NAMESPACE QtDataVis3D - -#ifdef QT_DATAVIS3D_NAMESPACE -# define QT_DATAVIS3D_BEGIN_NAMESPACE namespace QT_DATAVIS3D_NAMESPACE { -# define QT_DATAVIS3D_END_NAMESPACE } -# define QT_DATAVIS3D_USE_NAMESPACE using namespace QT_DATAVIS3D_NAMESPACE; -#else -# define QT_DATAVIS3D_BEGIN_NAMESPACE -# define QT_DATAVIS3D_END_NAMESPACE -# define QT_DATAVIS3D_USE_NAMESPACE -#endif - -#endif // QVIS3DGLOBAL_H diff --git a/src/datavis3d/global/qtdatavis3dnamespace.qdoc b/src/datavis3d/global/qtdatavis3dnamespace.qdoc deleted file mode 100644 index 2a1f6fae..00000000 --- a/src/datavis3d/global/qtdatavis3dnamespace.qdoc +++ /dev/null @@ -1,163 +0,0 @@ -/**************************************************************************** -** -** 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 QtDataVis3D 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 -** -****************************************************************************/ - -/*! - \namespace QtDataVis3D - \inmodule QtDataVis3D - \target QtDataVis3D Namespace - - \brief The QtDataVis3D namespace contains miscellaneous identifiers - used throughout the QtDataVis3D library. -*/ - -/*! - \enum QtDataVis3D::BarStyle - - Predefined bar types. - - \value Bars - Basic cubic bar. - \value Pyramids - Four -sided pyramid. - \value Cones - Basic cone. - \value Cylinders - Basic cylinder. - \value BevelBars - Slilghtly beveled (rounded) cubic bar. - \value Spheres - Sphere. Not usable in Q3DBars. -*/ - -/*! - \enum QtDataVis3D::CameraPreset - - Predefined positions for camera. - - \value PresetFrontLow - \value PresetFront - \value PresetFrontHigh - \value PresetLeftLow - \value PresetLeft - \value PresetLeftHigh - \value PresetRightLow - \value PresetRight - \value PresetRightHigh - \value PresetBehindLow - \value PresetBehind - \value PresetBehindHigh - \value PresetIsometricLeft - \value PresetIsometricLeftHigh - \value PresetIsometricRight - \value PresetIsometricRightHigh - \value PresetDirectlyAbove - \value PresetDirectlyAboveCW45 - \value PresetDirectlyAboveCCW45 - \value PresetFrontBelow - From PresetFrontBelow onward these only work for graphs including negative values. - They act as Preset...Low for positive-only values. - \value PresetLeftBelow - \value PresetRightBelow - \value PresetBehindBelow - \value PresetDirectlyBelow - Acts as PresetFrontLow for positive -only bars. -*/ - -/*! - \enum QtDataVis3D::ColorTheme - - Predefined color themes. - - \value ThemeSystem - \value ThemeBlueCerulean - \value ThemeBlueIcy - \value ThemeBlueNcs - \value ThemeBrownSand - \value ThemeDark - \value ThemeHighContrast - \value ThemeLight -*/ - -/*! - \enum QtDataVis3D::LabelPosition - - Predefined positions for labels. - - \value LabelBelow - \value LabelLow - \value LabelMid - \value LabelHigh - \value LabelOver - \value LabelBottom - \value LabelTop - \value LabelLeft - \value LabelRight -*/ - -/*! - \enum QtDataVis3D::SelectionMode - - Bar selection modes. - - \value ModeNone - Selection mode disabled. - \value ModeBar - Selection selects a single bar. - \value ModeBarAndRow - Selection selects a single bar and highlights the row it is on. - \value ModeBarAndColumn - Selection selects a single bar and highlights the column it is on. - \value ModeBarRowAndColumn - Selection selects a single bar and highlights the row and the column it is on. - \value ModeZoomRow - Selection selects a single bar and displays the row it is on in a separate view. The - original view is shrunk into upper left corner. Original view is restored by clicking - on it. - \value ModeZoomColumn - Selection selects a single bar and displays the column it is on in a separate view. The - original view is shrunk into upper left corner. Original view is restored by clicking - on it. -*/ - -/*! - \enum QtDataVis3D::ShadowQuality - - Quality of shadows. - - \value ShadowNone - Shadows are disabled. - \value ShadowLow - Shadows are rendered in low quality. - \value ShadowMedium - Shadows are rendered in medium quality. - \value ShadowHigh - Shadows are rendered in high quality. -*/ - -/*! - \enum QtDataVis3D::LabelTransparency - - Label transparencies. - - \value TransparencyNone - Full solid, using colors from theme. - \value TransparencyFromTheme - Use colors and transparencies from theme. - \value TransparencyNoBackground - Draw just text on transparent background. -*/ diff --git a/src/datavis3d/utils/surfaceobject.cpp b/src/datavis3d/utils/surfaceobject.cpp deleted file mode 100644 index 4c05c442..00000000 --- a/src/datavis3d/utils/surfaceobject.cpp +++ /dev/null @@ -1,349 +0,0 @@ -/**************************************************************************** -** -** 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 QtDataVis3D 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 "surfaceobject_p.h" -#include "abstractobjecthelper_p.h" - -#include <QVector3D> -#include <QVector2D> - -#include <QDebug> - -QT_DATAVIS3D_BEGIN_NAMESPACE - -SurfaceObject::SurfaceObject() -{ - m_indicesType = GL_UNSIGNED_INT; -} - -SurfaceObject::~SurfaceObject() -{ -} - -void SurfaceObject::setUpSmoothData(QList<qreal> series, int columns, int rows, GLfloat yRange, bool changeGeometry) -{ - GLfloat width = (GLfloat(columns) - 1.0f) / 2.0f; - GLfloat depth = (GLfloat(rows) - 1.0f) / -2.0f; - GLfloat height = yRange / 2.0f; - - // Create vertice table - QVector<QVector3D> vertices; - QVector<QVector2D> uvs; - float uvX = 1.0 / float(columns - 1); - float uvY = 1.0 / float(rows - 1); - int row = 0; - for (float i = 0.0f; i < float(rows); i += 1.0, row += columns) { - for (float j = 0; j < columns; j++) { - vertices.append(QVector3D(j / width - 1.0f, - series.at(row + int(j)) / height - 1.0f, - i / depth + 1.0f)); - uvs.append(QVector2D(j * uvX, i * uvY)); - } - } - - // Create normals - QVector<QVector3D> normals; - for (int row = 0; row < (rows - 1) * columns; row += columns) { - for (int j = 0; j < columns - 1; j++) { - normals.append(normal(vertices.at(row + j), - vertices.at(row + j + 1), - vertices.at(row + columns + j))); - } - int p = row + columns - 1; - normals.append(normal(vertices.at(p), - vertices.at(p + columns), - vertices.at(p - 1))); - } - for (int j = (rows - 1) * columns ; j < rows * columns - 1; j++) { - normals.append(normal(vertices.at(j), - vertices.at(j - columns), - vertices.at(j + 1))); - } - int p = rows * columns - 1; - normals.append(normal(vertices.at(p), - vertices.at(p - 1), - vertices.at(p - columns - 1))); - - // Create indices table - GLint *indices = 0; - if (changeGeometry) { - m_indexCount = 6 * (columns - 1) * (rows - 1); - indices = new GLint[m_indexCount]; - p = 0; - for (int row = 0; row < (rows - 1) * columns; row += columns) { - for (int j = 0; j < columns - 1; j++) { - // Left triangle - indices[p++] = row + j + 1; - indices[p++] = row + columns + j; - indices[p++] = row + j; - - // Right triangle - indices[p++] = row + columns + j + 1; - indices[p++] = row + columns + j; - indices[p++] = row + j + 1; - } - } - } - - // Create line element indices - GLint *gridIndices = 0; - if (changeGeometry) { - m_gridIndexCount = 2 * columns * (rows - 1) + 2 * rows * (columns - 1); - gridIndices = new GLint[m_gridIndexCount]; - p = 0; - for (int i = 0, row = 0; i < rows; i++, row += columns) { - for (int j = 0; j < columns - 1; j++) { - gridIndices[p++] = row + j; - gridIndices[p++] = row + j + 1; - } - } - for (int i = 0, row = 0; i < rows - 1; i++, row += columns) { - for (int j = 0; j < columns; j++) { - gridIndices[p++] = row + j; - gridIndices[p++] = row + j + columns; - } - } - } - - createBuffers(vertices, uvs, normals, indices, gridIndices, changeGeometry); - - if (indices) - delete indices; - if (gridIndices) - delete gridIndices; -} - - -void SurfaceObject::setUpData(QList<qreal> series, int columns, int rows, GLfloat yRange, bool changeGeometry) -{ - GLfloat width = (GLfloat(columns) - 1.0f) / 2.0f; - GLfloat depth = (GLfloat(rows) - 1.0f) / -2.0f; - GLfloat height = yRange / 2.0f; - float uvX = 1.0 / float(columns - 1); - float uvY = 1.0 / float(rows - 1); - - // Create vertice table - QVector<QVector3D> vertices; - QVector<QVector2D> uvs; - int row = 0; - for (float i = 0.0f; i < float(rows); i += 1.0f, row += columns) { - for (float j = 0.0f; j < float(columns); j += 1.0f) { - vertices.append(QVector3D(j / width - 1.0f, - series.at(row + int(j)) / height - 1.0f, - i / depth + 1.0f)); - uvs.append(QVector2D(j * uvX, i * uvY)); - if (j > 0 && j < columns - 1) { - vertices.append(vertices.last()); - uvs.append(uvs.last()); - } - } - } - - // Create normals & indices table - QVector<QVector3D> normals; - int doubleColumns = columns * 2 - 2; - - GLint *indices = 0; - int p = 0; - if (changeGeometry) { - m_indexCount = 6 * (columns - 1) * (rows - 1); - indices = new GLint[m_indexCount]; - } - - for (int row = 0, upperRow = doubleColumns; - row < (rows - 1) * doubleColumns; - row += doubleColumns, upperRow += doubleColumns) { - for (int j = 0; j < doubleColumns; j += 2) { - // Normal for the left triangle - normals.append(normal(vertices.at(row + j), - vertices.at(row + j + 1), - vertices.at(upperRow + j))); - - // Normal for the right triangle - normals.append(normal(vertices.at(row + j + 1), - vertices.at(upperRow + j + 1), - vertices.at(upperRow + j))); - - if (changeGeometry) { - // Left triangle - indices[p++] = row + j + 1; - indices[p++] = upperRow + j; - indices[p++] = row + j; - - // Right triangle - indices[p++] = upperRow + j + 1; - indices[p++] = upperRow + j; - indices[p++] = row + j + 1; - } - } - } - - // Create grid line element indices - m_gridIndexCount = 2 * columns * (rows - 1) + 2 * rows * (columns - 1); - GLint *gridIndices = new GLint[m_gridIndexCount]; - p = 0; - int rowLimit = (rows - 1) * doubleColumns; - for (int row = 0; row < rows * doubleColumns; row += doubleColumns) { - for (int j = 0; j < doubleColumns; j += 2) { - gridIndices[p++] = row + j; - gridIndices[p++] = row + j + 1; - - if (row < rowLimit) { - gridIndices[p++] = row + j; - gridIndices[p++] = row + j + doubleColumns; - } - } - } - for (int i = doubleColumns - 1; i < rowLimit; i += doubleColumns) { - gridIndices[p++] = i; - gridIndices[p++] = i + doubleColumns; - } - - createBuffers(vertices, uvs, normals, indices, gridIndices, changeGeometry); - - if (indices) - delete indices; - if (gridIndices) - delete gridIndices; -} - - -void SurfaceObject::createBuffers(const QVector<QVector3D> &vertices, const QVector<QVector2D> &uvs, - const QVector<QVector3D> &normals, const GLint *indices, - const GLint *gridIndices, bool changeGeometry) -{ - initializeOpenGLFunctions(); - if (m_meshDataLoaded) { - // Delete old data - glDeleteBuffers(1, &m_vertexbuffer); - glDeleteBuffers(1, &m_normalbuffer); - if (changeGeometry) { - glDeleteBuffers(1, &m_uvbuffer); - glDeleteBuffers(1, &m_elementbuffer); - glDeleteBuffers(1, &m_gridElementbuffer); - } - } - - // Move to buffers - glGenBuffers(1, &m_vertexbuffer); - glBindBuffer(GL_ARRAY_BUFFER, m_vertexbuffer); - glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(QVector3D), - &vertices.at(0), GL_STATIC_DRAW); - - glGenBuffers(1, &m_normalbuffer); - glBindBuffer(GL_ARRAY_BUFFER, m_normalbuffer); - glBufferData(GL_ARRAY_BUFFER, normals.size() * sizeof(QVector3D), - &normals.at(0), GL_STATIC_DRAW); - - if (changeGeometry) { - glGenBuffers(1, &m_uvbuffer); - glBindBuffer(GL_ARRAY_BUFFER, m_uvbuffer); - glBufferData(GL_ARRAY_BUFFER, uvs.size() * sizeof(QVector2D), - &uvs.at(0), GL_STATIC_DRAW); - - glGenBuffers(1, &m_elementbuffer); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_elementbuffer); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_indexCount * sizeof(GLint), - indices, GL_STATIC_DRAW); - - glGenBuffers(1, &m_gridElementbuffer); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_gridElementbuffer); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_gridIndexCount * sizeof(GLint), - gridIndices, GL_STATIC_DRAW); - } - - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - - // We're done. Set the flag ON - m_meshDataLoaded = true; -} - -GLuint SurfaceObject::gridElementBuf() -{ - if (!m_meshDataLoaded) - qFatal("No loaded object"); - return m_gridElementbuffer; -} - -GLuint SurfaceObject::gridIndexCount() -{ - return m_gridIndexCount; -} - -QVector3D SurfaceObject::normal(const QVector3D &a, const QVector3D &b, const QVector3D &c) -{ - QVector3D v1 = b - a; - QVector3D v2 = c - a; - return QVector3D::crossProduct(v1, v2); -} - -QT_DATAVIS3D_END_NAMESPACE - - - -// For rainy days - -// QVector3D vertices[] = { -// QVector3D(-0.5f, 0.0f, 0.1f), -// QVector3D(0.5f, 0.0f, 0.1f), -// QVector3D(0.0f, 1.0f, -0.5f) -// }; - -// QVector3D normals[] = { -// QVector3D(0.5, 0.0, 1.0), -// QVector3D(0.5, 0.0, 1.0), -// QVector3D(0.5, 0.0, 1.0) -// }; - -// vertices.append(QVector3D(-1.0f, 0.0f, 0.1f)); -// vertices.append(QVector3D(0.0f, 0.0f, 0.1f)); -// vertices.append(QVector3D(0.0f, 0.5f, -0.5f)); - -// normals.append(QVector3D(0.5, 0.0, 1.0)); -// normals.append(QVector3D(0.5, 0.0, 1.0)); -// normals.append(QVector3D(0.5, 0.0, 1.0)); - -//GLushort indices[] = {0, 1, 2, 1, 3, 2}; -//GLushort indices[] = {1, 3, 2}; - -//qDebug() << indices[p + 0] << ", " << indices[p + 1] << ", " << indices[p + 2]; -//qDebug() << indices[p + 3] << ", " << indices[p + 4] << ", " << indices[p + 5]; - -//qDebug() << "(" << float(j) / width << ", 0.0, " << float(i) / depth * -1.0f << ")"; - -//normals.append(QVector3D(1,0,0)); -//normals.append(QVector3D(0,1,0)); -//normals.append(QVector3D(0,0,1)); -//normals.append(QVector3D(1,0,1)); - -//normals.append(QVector3D(1,0,0)); -//normals.append(QVector3D(0,1,0)); -//normals.append(QVector3D(0,0,1)); -//normals.append(QVector3D(1,0,1)); - -//normals.append(QVector3D(1,0,0)); -//normals.append(QVector3D(0,1,0)); -//normals.append(QVector3D(0,0,1)); -//normals.append(QVector3D(1,0,1)); - - -//qDebug() << "Left normal from (" << row + j << ", " << row + j + 1 << ", " << row + doubleColumns + j << ")"; - -//qDebug() << "right normal from (" << row + j +1 << ", " << row + doubleColumns + j + 1 << ", " << row + doubleColumns + j << ")"; - diff --git a/src/datavis3d/utils/utils.cpp b/src/datavis3d/utils/utils.cpp deleted file mode 100644 index cf6b91f8..00000000 --- a/src/datavis3d/utils/utils.cpp +++ /dev/null @@ -1,234 +0,0 @@ -/**************************************************************************** -** -** 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 QtDataVis3D 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 "utils_p.h" - -#include <QVector3D> -#include <QColor> -#include <QPainter> -#include <QPoint> -#include <QImage> - -#include <qmath.h> - -#include <QDebug> - -QT_DATAVIS3D_BEGIN_NAMESPACE - -#define NUM_IN_POWER(y, x) for (;y<x;y<<=1) -#define MIN_POWER 32 - -GLuint Utils::getNearestPowerOfTwo(GLuint value, GLuint &padding) -{ - GLuint powOfTwoValue = MIN_POWER; - NUM_IN_POWER(powOfTwoValue, value); - padding = powOfTwoValue - value; - return powOfTwoValue; -} - -QVector3D Utils::vectorFromColor(const QColor &color) -{ - return QVector3D(color.redF(), color.greenF(), color.blueF()); -} - -void Utils::printText(QPainter *painter, const QString &text, const QSize &position, - bool absoluteCoords, qreal rotation, qreal scale) -{ - painter->save(); - painter->setCompositionMode(QPainter::CompositionMode_Source); - painter->setPen(Qt::black); // TODO: Use black, as nothing works - QFont bgrFont = QFont(QStringLiteral("Arial"), 17); - QFont valueFont = QFont(QStringLiteral("Arial"), 11); - valueFont.setBold(true); - painter->setFont(bgrFont); - QFontMetrics valueFM(valueFont); - QFontMetrics bgrFM(bgrFont); - int valueStrLen = valueFM.width(text); - int bgrStrLen = 0; - int bgrHeight = valueFM.height() + 8; - QString bgrStr = QString(); - do { - bgrStr.append(QStringLiteral("I")); - bgrStrLen = bgrFM.width(bgrStr); - } while (bgrStrLen <= (valueStrLen + 8)); -#if 0 - // Hack solution, as drawRect doesn't work - painter->drawText(position.width() - (bgrStrLen / 2), - position.height() - bgrHeight, - bgrStrLen, bgrHeight, - Qt::AlignCenter | Qt::AlignVCenter, - bgrStr); - //painter->setPen(d_ptr->m_textColor); - painter->setPen(Qt::lightGray); // TODO: Use lightGray, as nothing works - painter->setFont(valueFont); - painter->drawText(position.width() - (valueStrLen / 2), - position.height() - bgrHeight, - valueStrLen, bgrHeight, - Qt::AlignCenter | Qt::AlignVCenter, - text); -#else - //qDebug() << painter->window() << painter->viewport(); - painter->scale(scale, scale); - if (absoluteCoords) { - // This assumes absolute screen coordinates - painter->translate(position.width() - (((float)bgrStrLen / 2.0f) - * qCos(qDegreesToRadians(rotation))) - + (((float)bgrHeight / 2.0f) * qSin(qDegreesToRadians(rotation))), - position.height() - - ((((float)bgrHeight / 2.0f) * qCos(qDegreesToRadians(rotation))) - + (((float)bgrStrLen / 2.0f) * qSin(qDegreesToRadians(rotation))))); - } else { - // This calculates y as a distance from screen bottom - painter->translate(position.width() - (((float)bgrStrLen / 2.0f) - * qCos(qDegreesToRadians(rotation))) - + (((float)bgrHeight / 2.0f) * qSin(qDegreesToRadians(rotation))), - painter->window().height() - position.height() - - ((((float)bgrHeight / 2.0f) * qCos(qDegreesToRadians(rotation))) - + (((float)bgrStrLen / 2.0f) * qSin(qDegreesToRadians(rotation))))); - } - //qDebug() << painter->window().height() - position.height() - // - ((((float)bgrHeight / 2.0f) * qCos(qDegreesToRadians(rotation))) - // + (((float)bgrStrLen / 2.0f) * qSin(qDegreesToRadians(rotation)))); - painter->rotate(rotation); - painter->drawText(0, 0, - bgrStrLen, bgrHeight, - Qt::AlignCenter | Qt::AlignVCenter, - bgrStr); - painter->setPen(Qt::lightGray); // TODO: Use lightGray, as nothing works - painter->setFont(valueFont); - painter->drawText(6, 0, - valueStrLen, bgrHeight, - Qt::AlignCenter | Qt::AlignVCenter, - text); - painter->resetTransform(); -#endif - painter->restore(); -} - -QImage Utils::printTextToImage(const QFont &font, const QString &text, const QColor &bgrColor, - const QColor &txtColor, QDataVis::LabelTransparency transparency) -{ - GLuint paddingWidth = 15; - GLuint paddingHeight = 15; - // Calculate text dimensions - QFont valueFont = font; - valueFont.setPointSize(30); - QFontMetrics valueFM(valueFont); - int valueStrWidth = valueFM.width(text); - int valueStrHeight = valueFM.height(); - QSize labelSize; - -#if defined(Q_OS_ANDROID) - // Android can't handle textures with dimensions not in power of 2. Resize labels accordingly. - // Add some padding before converting to power of two to avoid too tight fit - GLuint prePadding = 10; - labelSize = QSize(valueStrWidth + prePadding, valueStrHeight + prePadding); - //qDebug() << "label size before padding" << labelSize; - labelSize.setWidth(getNearestPowerOfTwo(labelSize.width(), paddingWidth)); - labelSize.setHeight(getNearestPowerOfTwo(labelSize.height(), paddingHeight)); - paddingWidth += prePadding; - paddingHeight += prePadding; - paddingWidth /= 2; - paddingHeight /= 2; - //qDebug() << "label size after padding" << labelSize << paddingWidth << paddingHeight; -#else - if (QDataVis::TransparencyNoBackground == transparency) - labelSize = QSize(valueStrWidth, valueStrHeight); - else - labelSize = QSize(valueStrWidth + paddingWidth * 2, valueStrHeight + paddingHeight * 2); -#endif - - // Create image - QImage image = QImage(labelSize, QImage::Format_ARGB32); - image.fill(Qt::transparent); - - // Init painter - QPainter painter(&image); - // Paint text - painter.setRenderHint(QPainter::Antialiasing, true); - painter.setCompositionMode(QPainter::CompositionMode_Source); - switch (transparency) { - // TODO: Texture size padding fix for Android f**ks this up for axis labels. Fix or disable for android. - case QDataVis::TransparencyNoBackground: { - painter.setFont(valueFont); - painter.setPen(txtColor); - painter.drawText(0, 0, - valueStrWidth, valueStrHeight, - Qt::AlignCenter | Qt::AlignVCenter, - text); - break; - } - case QDataVis::TransparencyFromTheme: { - painter.setBrush(QBrush(bgrColor)); - painter.setPen(bgrColor); - painter.drawRoundedRect(0, 0, labelSize.width(), labelSize.height(), 10.0, 10.0f); - painter.setFont(valueFont); - painter.setPen(txtColor); - painter.drawText(paddingWidth, paddingHeight, - valueStrWidth, valueStrHeight, - Qt::AlignCenter | Qt::AlignVCenter, - text); - break; - } - case QDataVis::TransparencyNone: { - painter.setBrush(QBrush(bgrColor)); - painter.setPen(bgrColor); - painter.drawRect(0, 0, labelSize.width(), labelSize.height()); - painter.setFont(valueFont); - painter.setPen(txtColor); - painter.drawText(paddingWidth, paddingHeight, - valueStrWidth, valueStrHeight, - Qt::AlignCenter | Qt::AlignVCenter, - text); - break; - } - } - return image; -} - -QVector3D Utils::getSelection(QPoint mousepos, int height) -{ - QVector3D selectedColor; - - //#if defined(QT_OPENGL_ES_2) - // This is the only one that works with ANGLE (ES 2.0) - // Item count will be limited to 256*256*256 - GLubyte pixel[4]; - glReadPixels(mousepos.x(), height - mousepos.y(), 1, 1, - GL_RGBA, GL_UNSIGNED_BYTE, (void *)pixel); - //qDebug() << "rgba" << pixel[0] << pixel[1] << pixel[2];// << pixel[3]; - //#else - //// These work with desktop OpenGL - //// They offer a lot higher possible object count and a possibility to use object ids - //GLuint pixel[3]; - //glReadPixels(mousepos.x(), height - mousepos.y(), 1, 1, - // GL_RGB, GL_UNSIGNED_INT, (void *)pixel); - //qDebug() << "rgba" << pixel[0] << pixel[1] << pixel[2];// << pixel[3]; - - //GLfloat pixel3[3]; - //glReadPixels(mousepos.x(), height - mousepos.y(), 1, 1, - // GL_RGB, GL_FLOAT, (void *)pixel3); - //qDebug() << "rgba" << pixel3[0] << pixel3[1] << pixel3[2];// << pixel[3]; - //#endif - selectedColor = QVector3D(pixel[0], pixel[1], pixel[2]); - //qDebug() << selectedColor; - - return selectedColor; -} - -QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3dqml2/datavis3dqml2_plugin.cpp b/src/datavis3dqml2/datavis3dqml2_plugin.cpp deleted file mode 100644 index d1e534f8..00000000 --- a/src/datavis3dqml2/datavis3dqml2_plugin.cpp +++ /dev/null @@ -1,48 +0,0 @@ -/**************************************************************************** -** -** 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 QtDataVis3D 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 "datavis3dqml2_plugin.h" - -#include <qqml.h> - -QT_DATAVIS3D_BEGIN_NAMESPACE - -void Datavis3dqml2Plugin::registerTypes(const char *uri) -{ - // @uri com.digia.QtDataVis3D - qmlRegisterUncreatableType<QAbstractItemModel>(uri, 1, 0, "AbstractItemModel", - QLatin1String("Trying to create uncreatable: AbstractItemModel.")); - qmlRegisterUncreatableType<QDataVis>(uri, 1, 0, "DataVis", - QLatin1String("Trying to create uncreatable: DataVis.")); - qmlRegisterUncreatableType<QAbstractAxis>(uri, 1, 0, "AbstractAxis", - QLatin1String("Trying to create uncreatable: AbstractAxis.")); - - qmlRegisterType<QItemModelBarDataMapping>(uri, 1, 0, "BarDataMapping"); - qmlRegisterType<QItemModelMapDataMapping>(uri, 1, 0, "MapDataMapping"); - qmlRegisterType<QItemModelScatterDataMapping>(uri, 1, 0, "ScatterDataMapping"); - - qmlRegisterType<DeclarativeBars>(uri, 1, 0, "Bars3D"); - qmlRegisterType<DeclarativeMaps>(uri, 1, 0, "Maps3D"); - qmlRegisterType<DeclarativeScatter>(uri, 1, 0, "Scatter3D"); - - qmlRegisterType<QValueAxis>(uri, 1, 0, "ValueAxis"); - qmlRegisterType<QCategoryAxis>(uri, 1, 0, "CategoryAxis"); -} - -QT_DATAVIS3D_END_NAMESPACE - diff --git a/src/datavis3dqml2/datavis3dqml2_plugin.h b/src/datavis3dqml2/datavis3dqml2_plugin.h deleted file mode 100644 index ac88e1b5..00000000 --- a/src/datavis3dqml2/datavis3dqml2_plugin.h +++ /dev/null @@ -1,64 +0,0 @@ -/**************************************************************************** -** -** 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 QtDataVis3D 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 DATAVIS3DQML2_PLUGIN_H -#define DATAVIS3DQML2_PLUGIN_H - -#include "datavis3dglobal_p.h" -#include "declarativebars_p.h" -#include "declarativemaps_p.h" -#include "declarativescatter_p.h" -#include "qitemmodelbardatamapping.h" -#include "qitemmodelmapdatamapping.h" -#include "qitemmodelscatterdatamapping.h" -#include "qvalueaxis.h" -#include "qcategoryaxis.h" - -#include <QQmlExtensionPlugin> - -QT_DATAVIS3D_USE_NAMESPACE - -Q_DECLARE_METATYPE(DeclarativeBars *) -Q_DECLARE_METATYPE(DeclarativeMaps *) -Q_DECLARE_METATYPE(DeclarativeScatter *) - -Q_DECLARE_METATYPE(QItemModelBarDataMapping *) -Q_DECLARE_METATYPE(QItemModelMapDataMapping *) -Q_DECLARE_METATYPE(QItemModelScatterDataMapping *) -Q_DECLARE_METATYPE(QAbstractItemModel *) -Q_DECLARE_METATYPE(QDataVis *) - -Q_DECLARE_METATYPE(QAbstractAxis *) -Q_DECLARE_METATYPE(QCategoryAxis *) -Q_DECLARE_METATYPE(QValueAxis *) - -QT_DATAVIS3D_BEGIN_NAMESPACE - -class Datavis3dqml2Plugin : public QQmlExtensionPlugin -{ - Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") - -public: - void registerTypes(const char *uri); -}; - -QT_DATAVIS3D_END_NAMESPACE - -#endif // DATAVIS3DQML2_PLUGIN_H - diff --git a/src/datavis3dqml2/declarativebars.cpp b/src/datavis3dqml2/declarativebars.cpp deleted file mode 100644 index 2e4dbf04..00000000 --- a/src/datavis3dqml2/declarativebars.cpp +++ /dev/null @@ -1,380 +0,0 @@ -/**************************************************************************** -** -** 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 QtDataVis3D 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 "declarativebars_p.h" -#include "declarativebarsrenderer_p.h" -#include "qitemmodelbardataproxy.h" -#include "qvalueaxis.h" - -QT_DATAVIS3D_BEGIN_NAMESPACE - -const QString smoothString(QStringLiteral("Smooth")); - -DeclarativeBars::DeclarativeBars(QQuickItem *parent) - : QQuickItem(parent), - m_shared(0), - m_initialisedSize(0, 0), - m_cameraPreset(QDataVis::NoPreset), - m_theme(QDataVis::ThemeDefault) -{ - setFlags(QQuickItem::ItemHasContents); - setAcceptedMouseButtons(Qt::AllButtons); - - // TODO: These seem to have no effect; find a way to activate anti-aliasing - setAntialiasing(true); - setSmooth(true); - - // Create the shared component on the main GUI thread. - m_shared = new Bars3dController(boundingRect().toRect()); - QObject::connect(m_shared, &Abstract3DController::shadowQualityChanged, this, - &DeclarativeBars::handleShadowQualityUpdate); - - m_shared->setDataProxy(new QItemModelBarDataProxy); -} - -DeclarativeBars::~DeclarativeBars() -{ - delete m_shared; -} - -void DeclarativeBars::handleShadowQualityUpdate(QDataVis::ShadowQuality quality) -{ - emit shadowQualityChanged(quality); -} - -void DeclarativeBars::classBegin() -{ - qDebug() << "classBegin"; -} - -void DeclarativeBars::componentComplete() -{ - qDebug() << "componentComplete"; -} - -QSGNode *DeclarativeBars::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) -{ - // If old node exists and has right size, reuse it. - if (oldNode && m_initialisedSize == boundingRect().size().toSize()) { - // Update bounding rectangle (that has same size as before). - static_cast<DeclarativeBarsRenderer *>( oldNode )->setRect(boundingRect()); - return oldNode; - } - - // Create a new render node when size changes or if there is no node yet - m_initialisedSize = boundingRect().size().toSize(); - - // Delete old node - if (oldNode) - delete oldNode; - - // Create a new one and set it's bounding rectangle - DeclarativeBarsRenderer *node = new DeclarativeBarsRenderer(window(), m_shared); - node->setRect(boundingRect()); - m_shared->setBoundingRect(boundingRect().toRect()); - return node; -} - -void DeclarativeBars::setupSampleSpace(int rowCount, int columnCount) -{ - m_shared->setupSampleSpace(rowCount, columnCount); -} - -void DeclarativeBars::setBarColor(QColor baseColor, QColor heightColor, QColor depthColor, - bool uniform) -{ - m_shared->setObjectColor(baseColor, heightColor, depthColor, uniform); -} - -void DeclarativeBars::setCameraPosition(qreal horizontal, qreal vertical, int distance) -{ - m_shared->setCameraPosition(GLfloat(horizontal), GLfloat(vertical), GLint(distance)); -} - -void DeclarativeBars::setData(QAbstractItemModel *data) -{ - static_cast<QItemModelBarDataProxy *>(m_shared->dataProxy())->setItemModel(data); -} - -QAbstractItemModel *DeclarativeBars::data() -{ - return static_cast<QItemModelBarDataProxy *>(m_shared->dataProxy())->itemModel(); -} - -void DeclarativeBars::setMapping(QItemModelBarDataMapping *mapping) -{ - static_cast<QItemModelBarDataProxy *>(m_shared->dataProxy())->setMapping(mapping); -} - -QCategoryAxis *DeclarativeBars::axisX() const -{ - return static_cast<QCategoryAxis *>(m_shared->axisX()); -} - -void DeclarativeBars::setAxisX(QCategoryAxis *axis) -{ - m_shared->setAxisX(axis); -} - -QValueAxis *DeclarativeBars::axisY() const -{ - return static_cast<QValueAxis *>(m_shared->axisY()); -} - -void DeclarativeBars::setAxisY(QValueAxis *axis) -{ - m_shared->setAxisY(axis); -} - -QCategoryAxis *DeclarativeBars::axisZ() const -{ - return static_cast<QCategoryAxis *>(m_shared->axisZ()); -} - -void DeclarativeBars::setAxisZ(QCategoryAxis *axis) -{ - m_shared->setAxisZ(axis); -} - -QItemModelBarDataMapping *DeclarativeBars::mapping() const -{ - return static_cast<QItemModelBarDataProxy *>(m_shared->dataProxy())->mapping(); -} - -void DeclarativeBars::setBarThickness(QSizeF thickness) -{ - m_shared->setBarSpecs(thickness, barSpacing(), isBarSpacingRelative()); -} - -QSizeF DeclarativeBars::barThickness() -{ - return m_shared->barThickness(); -} - -void DeclarativeBars::setBarSpacing(QSizeF spacing) -{ - m_shared->setBarSpecs(barThickness(), spacing, isBarSpacingRelative()); -} - -QSizeF DeclarativeBars::barSpacing() -{ - return m_shared->barSpacing(); -} - -void DeclarativeBars::setBarSpacingRelative(bool relative) -{ - m_shared->setBarSpecs(barThickness(), barSpacing(), relative); -} - -bool DeclarativeBars::isBarSpacingRelative() -{ - return m_shared->isBarSpecRelative(); -} - -void DeclarativeBars::setBarType(QDataVis::MeshStyle style) -{ - QString objFile = m_shared->meshFileName(); - bool smooth = objFile.endsWith(smoothString); - m_shared->setBarType(style, smooth); -} - -QDataVis::MeshStyle DeclarativeBars::barType() -{ - QString objFile = m_shared->meshFileName(); - if (objFile.contains("/sphere")) - return QDataVis::Spheres; - else - return QDataVis::Dots; -} - -void DeclarativeBars::setBarSmooth(bool smooth) -{ - QString objFile = m_shared->meshFileName(); - if (objFile.endsWith(smoothString)) { - if (smooth) - return; // Already smooth; do nothing - else // Rip Smooth off the end - objFile.resize(objFile.indexOf(smoothString)); - } else { - if (!smooth) // Already flat; do nothing - return; - else // Append Smooth to the end - objFile.append(smoothString); - } - m_shared->setMeshFileName(objFile); -} - -bool DeclarativeBars::barSmooth() -{ - QString objFile = m_shared->meshFileName(); - return objFile.endsWith(smoothString); -} - -void DeclarativeBars::setMeshFileName(const QString &objFileName) -{ - m_shared->setMeshFileName(objFileName); -} - -QString DeclarativeBars::meshFileName() -{ - return m_shared->meshFileName(); -} - -void DeclarativeBars::setCameraPreset(QDataVis::CameraPreset preset) -{ - // TODO: Implement correctly once "improved camera api" (QTRD-2122) is implemented - // We need to save this locally, as there are no getters for it in controller - m_cameraPreset = preset; - m_shared->setCameraPreset(preset); -} - -QDataVis::CameraPreset DeclarativeBars::cameraPreset() -{ - return m_cameraPreset; -} - -void DeclarativeBars::setTheme(QDataVis::ColorTheme theme) -{ - // TODO: Implement correctly once "user-modifiable themes" (QTRD-2120) is implemented - // We need to save this locally, as there are no getters for it in controller - m_theme = theme; - m_shared->setColorTheme(theme); -} - -QDataVis::ColorTheme DeclarativeBars::theme() -{ - return m_theme; -} - -void DeclarativeBars::setFontSize(float fontsize) -{ - m_shared->setFontSize(fontsize); -} - -float DeclarativeBars::fontSize() -{ - return m_shared->fontSize(); -} - -void DeclarativeBars::setFont(const QFont &font) -{ - m_shared->setFont(font); -} - -QFont DeclarativeBars::font() -{ - return m_shared->font(); -} - -void DeclarativeBars::setLabelTransparency(QDataVis::LabelTransparency transparency) -{ - m_shared->setLabelTransparency(transparency); -} - -QDataVis::LabelTransparency DeclarativeBars::labelTransparency() -{ - return m_shared->labelTransparency(); -} - -void DeclarativeBars::setGridVisible(bool visible) -{ - m_shared->setGridEnabled(visible); -} - -bool DeclarativeBars::isGridVisible() -{ - return m_shared->gridEnabled(); -} - -void DeclarativeBars::setBackgroundVisible(bool visible) -{ - m_shared->setBackgroundEnabled(visible); -} - -bool DeclarativeBars::isBackgroundVisible() -{ - return m_shared->backgroundEnabled(); -} - -void DeclarativeBars::setSelectionMode(QDataVis::SelectionMode mode) -{ - m_shared->setSelectionMode(mode); -} - -QDataVis::SelectionMode DeclarativeBars::selectionMode() -{ - return m_shared->selectionMode(); -} - -void DeclarativeBars::setShadowQuality(QDataVis::ShadowQuality quality) -{ - m_shared->setShadowQuality(quality); -} - -QDataVis::ShadowQuality DeclarativeBars::shadowQuality() -{ - return m_shared->shadowQuality(); -} - -int DeclarativeBars::rows() const -{ - return m_shared->rowCount(); -} - -void DeclarativeBars::setRows(int rows) -{ - setupSampleSpace(rows, columns()); -} - -int DeclarativeBars::columns() const -{ - return m_shared->columnCount(); -} - -void DeclarativeBars::setColumns(int columns) -{ - setupSampleSpace(rows(), columns); -} - -void DeclarativeBars::mousePressEvent(QMouseEvent *event) -{ - QPoint mousePos = event->pos(); - //mousePos.setY(height() - mousePos.y()); - m_shared->mousePressEvent(event, mousePos); -} - -void DeclarativeBars::mouseReleaseEvent(QMouseEvent *event) -{ - QPoint mousePos = event->pos(); - //mousePos.setY(height() - mousePos.y()); - m_shared->mouseReleaseEvent(event, mousePos); -} - -void DeclarativeBars::mouseMoveEvent(QMouseEvent *event) -{ - QPoint mousePos = event->pos(); - //mousePos.setY(height() - mousePos.y()); - m_shared->mouseMoveEvent(event, mousePos); -} - -void DeclarativeBars::wheelEvent(QWheelEvent *event) -{ - m_shared->wheelEvent(event); -} - -QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3dqml2/declarativebars_p.h b/src/datavis3dqml2/declarativebars_p.h deleted file mode 100644 index 07dc21d4..00000000 --- a/src/datavis3dqml2/declarativebars_p.h +++ /dev/null @@ -1,206 +0,0 @@ -/**************************************************************************** -** -** 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 QtDataVis3D 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 QtDataVis3D 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 DECLARATIVEBARS_P_H -#define DECLARATIVEBARS_P_H - -#include "datavis3dglobal_p.h" -#include "bars3dcontroller_p.h" -#include "declarativebars_p.h" -#include "qitemmodelbardatamapping.h" -#include "qvalueaxis.h" -#include "qcategoryaxis.h" - -#include <QAbstractItemModel> -#include <QQuickItem> -#include <QObject> -#include <QQuickWindow> - -QT_DATAVIS3D_BEGIN_NAMESPACE - -class DeclarativeBars : public QQuickItem -{ - Q_OBJECT - Q_PROPERTY(QAbstractItemModel *data READ data WRITE setData) - Q_PROPERTY(QItemModelBarDataMapping *mapping READ mapping WRITE setMapping) - Q_PROPERTY(QCategoryAxis *axisX READ axisX WRITE setAxisX) - Q_PROPERTY(QValueAxis *axisY READ axisY WRITE setAxisY) - Q_PROPERTY(QCategoryAxis *axisZ READ axisZ WRITE setAxisZ) - Q_PROPERTY(QtDataVis3D::QDataVis::SelectionMode selectionMode READ selectionMode WRITE setSelectionMode) - Q_PROPERTY(QtDataVis3D::QDataVis::LabelTransparency labelTransparency READ labelTransparency WRITE setLabelTransparency) - Q_PROPERTY(QtDataVis3D::QDataVis::ShadowQuality shadowQuality READ shadowQuality WRITE setShadowQuality) - Q_PROPERTY(QtDataVis3D::QDataVis::MeshStyle barType READ barType WRITE setBarType) - Q_PROPERTY(QtDataVis3D::QDataVis::CameraPreset cameraPreset READ cameraPreset WRITE setCameraPreset) - Q_PROPERTY(QtDataVis3D::QDataVis::ColorTheme theme READ theme WRITE setTheme) - Q_PROPERTY(QSizeF barThickness READ barThickness WRITE setBarThickness) - Q_PROPERTY(QSizeF barSpacing READ barSpacing WRITE setBarSpacing) - Q_PROPERTY(bool barSpacingRelative READ isBarSpacingRelative WRITE setBarSpacingRelative) - Q_PROPERTY(bool barSmooth READ barSmooth WRITE setBarSmooth) - Q_PROPERTY(QString meshFileName READ meshFileName WRITE setMeshFileName) - Q_PROPERTY(QFont font READ font WRITE setFont) - Q_PROPERTY(float fontSize READ fontSize WRITE setFontSize) - Q_PROPERTY(bool gridVisible READ isGridVisible WRITE setGridVisible) - Q_PROPERTY(bool backgroundVisible READ isBackgroundVisible WRITE setBackgroundVisible) - Q_PROPERTY(int rows READ rows WRITE setRows) - Q_PROPERTY(int columns READ columns WRITE setColumns) - Q_ENUMS(QtDataVis3D::QDataVis::SelectionMode) - Q_ENUMS(QtDataVis3D::QDataVis::ShadowQuality) - Q_ENUMS(QtDataVis3D::QDataVis::LabelTransparency) - Q_ENUMS(QtDataVis3D::QDataVis::MeshStyle) - Q_ENUMS(QtDataVis3D::QDataVis::CameraPreset) - Q_ENUMS(QtDataVis3D::QDataVis::ColorTheme) - -public: - explicit DeclarativeBars(QQuickItem *parent = 0); - ~DeclarativeBars(); - - void classBegin(); - void componentComplete(); - - // how many samples per row and column - Q_INVOKABLE void setupSampleSpace(int rowCount, int columnCount); - - // Set color if you don't want to use themes. Set uniform to false if you want the (height) - // color to change from bottom to top - Q_INVOKABLE void setBarColor(QColor baseColor, QColor heightColor, QColor depthColor, - bool uniform = true); - - // Set camera rotation if you don't want to use the presets (in horizontal (-180...180) and - // vertical (0...90) (or (-90...90) if there are negative values) angles and distance in - // percentage (10...500)) - Q_INVOKABLE void setCameraPosition(qreal horizontal, qreal vertical, int distance); - - // Add whole data set. - void setData(QAbstractItemModel *data); - QAbstractItemModel *data(); - - QItemModelBarDataMapping *mapping() const; - void setMapping(QItemModelBarDataMapping *mapping); - - QCategoryAxis *axisX() const; - void setAxisX(QCategoryAxis *axis); - QValueAxis *axisY() const; - void setAxisY(QValueAxis *axis); - QCategoryAxis *axisZ() const; - void setAxisZ(QCategoryAxis *axis); - - // Set bar thickness. Y -component sets the thickness of z -direction. - void setBarThickness(QSizeF thickness); - QSizeF barThickness(); - - // Set spacing between bars. Y -component sets the spacing of z -direction. - // If spacing is relative, 0.0f means side-to-side and 1.0f = one thickness in between. - void setBarSpacing(QSizeF spacing); - QSizeF barSpacing(); - - // Set bar spacing relative to thickness or absolute - void setBarSpacingRelative(bool relative); - bool isBarSpacingRelative(); - - // Bar type - void setBarType(QDataVis::MeshStyle style); - QDataVis::MeshStyle barType(); - - // Bar smoothing - void setBarSmooth(bool smooth); - bool barSmooth(); - - // override object type with own mesh - void setMeshFileName(const QString &objFileName); - QString meshFileName(); - - // Select preset camera placement - void setCameraPreset(QDataVis::CameraPreset preset); - QDataVis::CameraPreset cameraPreset(); - - // Set theme (object colors, shaders, window color, background colors, light intensity and text - // colors are affected) - void setTheme(QDataVis::ColorTheme theme); - QDataVis::ColorTheme theme(); - - // Change selection mode; single bar, bar and row, bar and column, or all - void setSelectionMode(QDataVis::SelectionMode mode); - QDataVis::SelectionMode selectionMode(); - - // Font size adjustment - void setFontSize(float fontsize); - float fontSize(); - - // Set font - void setFont(const QFont &font); - QFont font(); - - // Label transparency adjustment - void setLabelTransparency(QDataVis::LabelTransparency transparency); - QDataVis::LabelTransparency labelTransparency(); - - // Enable or disable background grid - void setGridVisible(bool visible); - bool isGridVisible(); - - // Enable or disable background mesh - void setBackgroundVisible(bool visible); - bool isBackgroundVisible(); - - // Adjust shadow quality - void setShadowQuality(QDataVis::ShadowQuality quality); - QDataVis::ShadowQuality shadowQuality(); - - int rows() const; - void setRows(int rows); - - int columns() const; - void setColumns(int columns); - -public slots: - // Used to detect when shadow quality changes autonomously due to e.g. resizing. - void handleShadowQualityUpdate(QDataVis::ShadowQuality quality); - -signals: - // Signals shadow quality changes. - void shadowQualityChanged(QDataVis::ShadowQuality quality); - -protected: - Bars3dController *m_shared; - - QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *); - - void mousePressEvent(QMouseEvent *event); - void mouseReleaseEvent(QMouseEvent *event); - void mouseMoveEvent(QMouseEvent *event); - void wheelEvent(QWheelEvent *event); - -private: - QSize m_initialisedSize; - QDataVis::CameraPreset m_cameraPreset; - QDataVis::ColorTheme m_theme; -}; - -QT_DATAVIS3D_END_NAMESPACE - -#endif diff --git a/src/datavis3dqml2/declarativemaps.cpp b/src/datavis3dqml2/declarativemaps.cpp deleted file mode 100644 index 7be239f2..00000000 --- a/src/datavis3dqml2/declarativemaps.cpp +++ /dev/null @@ -1,229 +0,0 @@ -/**************************************************************************** -** -** 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 QtDataVis3D 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 "declarativemaps_p.h" -#include "declarativemapsrenderer_p.h" -#include "qitemmodelmapdataproxy.h" - -QT_DATAVIS3D_BEGIN_NAMESPACE - -DeclarativeMaps::DeclarativeMaps(QQuickItem *parent) - : QQuickItem(parent), - m_shared(0), - m_initializedSize(0, 0) -{ - setFlags(QQuickItem::ItemHasContents); - setAcceptedMouseButtons(Qt::AllButtons); - - // TODO: These seem to have no effect; find a way to activate anti-aliasing - setAntialiasing(true); - setSmooth(true); -} - -DeclarativeMaps::~DeclarativeMaps() -{ - delete m_shared; -} - -void DeclarativeMaps::classBegin() -{ - qDebug() << "classBegin"; -} - -void DeclarativeMaps::componentComplete() -{ - qDebug() << "componentComplete"; -} - -QSGNode *DeclarativeMaps::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) -{ - if (!m_shared) { - m_shared = new Maps3DController(boundingRect().toRect()); - m_shared->setDataProxy(new QItemModelMapDataProxy); - m_shared->initializeOpenGL(); - } - - // If old node exists and has right size, reuse it. - if (oldNode && m_initializedSize == boundingRect().size().toSize()) { - // Update bounding rectangle (that has same size as before). - static_cast<DeclarativeMapsRenderer *>( oldNode )->setRect(boundingRect()); - return oldNode; - } - - // Create a new render node when size changes or if there is no node yet - m_initializedSize = boundingRect().size().toSize(); - - // Delete old node - if (oldNode) - delete oldNode; - - // Create a new one and set it's bounding rectangle - DeclarativeMapsRenderer *node = new DeclarativeMapsRenderer(window(), m_shared); - node->setRect(boundingRect()); - m_shared->setBoundingRect(boundingRect().toRect()); - return node; -} - -void DeclarativeMaps::setData(QAbstractItemModel *data) -{ - static_cast<QItemModelMapDataProxy *>(m_shared->dataProxy())->setItemModel(data); -} - -QAbstractItemModel *DeclarativeMaps::data() -{ - return static_cast<QItemModelMapDataProxy *>(m_shared->dataProxy())->itemModel(); -} - -void DeclarativeMaps::setBarSpecs(const QVector3D &thickness, - Q3DMaps::AdjustmentDirection direction) -{ - m_shared->setBarSpecs(thickness, direction); -} - -void DeclarativeMaps::setBarType(QDataVis::MeshStyle style, bool smooth) -{ - m_shared->setBarType(style, smooth); -} - -void DeclarativeMaps::setMeshFileName(const QString &objFileName) -{ - m_shared->setMeshFileName(objFileName); -} - -void DeclarativeMaps::setCameraPreset(QDataVis::CameraPreset preset) -{ - m_shared->setCameraPreset(preset); -} - -void DeclarativeMaps::setCameraPosition(GLfloat horizontal, GLfloat vertical, GLint distance) -{ - m_shared->setCameraPosition(horizontal, vertical, distance); -} - -void DeclarativeMaps::setTheme(QDataVis::ColorTheme theme) -{ - m_shared->setTheme(theme); -} - -void DeclarativeMaps::setBarColor(QColor baseColor, QColor heightColor, bool uniform) -{ - m_shared->setBarColor(baseColor, heightColor, uniform); -} - -void DeclarativeMaps::setAreaSpecs(const QRect &areaRect, const QImage &image) -{ - m_shared->setAreaSpecs(areaRect, image); -} - -void DeclarativeMaps::setImage(const QImage &image) -{ - m_shared->setImage(image); -} - -void DeclarativeMaps::setImage(const QString &imageUrl) -{ - m_shared->setImage(QImage(imageUrl)); -} - -void DeclarativeMaps::setSelectionMode(QDataVis::SelectionMode mode) -{ - m_shared->setSelectionMode(mode); -} - -QDataVis::SelectionMode DeclarativeMaps::selectionMode() -{ - return m_shared->selectionMode(); -} - -void DeclarativeMaps::setFontSize(float fontsize) -{ - m_shared->setFontSize(fontsize); -} - -float DeclarativeMaps::fontSize() -{ - return m_shared->fontSize(); -} - -void DeclarativeMaps::setFont(const QFont &font) -{ - m_shared->setFont(font); -} - -QFont DeclarativeMaps::font() -{ - return m_shared->font(); -} - -void DeclarativeMaps::setLabelTransparency(QDataVis::LabelTransparency transparency) -{ - m_shared->setLabelTransparency(transparency); -} - -QDataVis::LabelTransparency DeclarativeMaps::labelTransparency() -{ - return m_shared->labelTransparency(); -} - -void DeclarativeMaps::setShadowQuality(QDataVis::ShadowQuality quality) -{ - m_shared->setShadowQuality(quality); -} - -QDataVis::ShadowQuality DeclarativeMaps::shadowQuality() -{ - return m_shared->shadowQuality(); -} - -QItemModelMapDataMapping *DeclarativeMaps::mapping() const -{ - return static_cast<QItemModelMapDataProxy *>(m_shared->dataProxy())->mapping(); -} - -void DeclarativeMaps::setMapping(QItemModelMapDataMapping *mapping) -{ - static_cast<QItemModelMapDataProxy *>(m_shared->dataProxy())->setMapping(mapping); -} - -void DeclarativeMaps::mousePressEvent(QMouseEvent *event) -{ - QPoint mousePos = event->pos(); - //mousePos.setY(height() - mousePos.y()); - m_shared->mousePressEvent(event, mousePos); -} - -void DeclarativeMaps::mouseReleaseEvent(QMouseEvent *event) -{ - QPoint mousePos = event->pos(); - //mousePos.setY(height() - mousePos.y()); - m_shared->mouseReleaseEvent(event, mousePos); -} - -void DeclarativeMaps::mouseMoveEvent(QMouseEvent *event) -{ - QPoint mousePos = event->pos(); - //mousePos.setY(height() - mousePos.y()); - m_shared->mouseMoveEvent(event, mousePos); -} - -void DeclarativeMaps::wheelEvent(QWheelEvent *event) -{ - m_shared->wheelEvent(event); -} - -QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3dqml2/declarativemaps_p.h b/src/datavis3dqml2/declarativemaps_p.h deleted file mode 100644 index ba2da0b3..00000000 --- a/src/datavis3dqml2/declarativemaps_p.h +++ /dev/null @@ -1,139 +0,0 @@ -/**************************************************************************** -** -** 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 QtDataVis3D 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 QtDataVis3D 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 DECLARATIVEMAPS_P_H -#define DECLARATIVEMAPS_P_H - -#include "datavis3dglobal_p.h" -#include "maps3dcontroller_p.h" -#include "declarativemaps_p.h" -#include "qitemmodelmapdatamapping.h" - -#include <QAbstractItemModel> -#include <QQuickItem> -#include <QObject> - -QT_DATAVIS3D_BEGIN_NAMESPACE - -class DeclarativeMaps : public QQuickItem -{ - Q_OBJECT - Q_PROPERTY(QAbstractItemModel *data READ data WRITE setData) - Q_PROPERTY(QtDataVis3D::QDataVis::SelectionMode selectionMode READ selectionMode WRITE setSelectionMode) - Q_PROPERTY(QtDataVis3D::QDataVis::LabelTransparency labelTransparency READ labelTransparency WRITE setLabelTransparency) - Q_PROPERTY(QtDataVis3D::QDataVis::ShadowQuality shadowQuality READ shadowQuality WRITE setShadowQuality) - Q_PROPERTY(QFont font READ font WRITE setFont) - Q_PROPERTY(float fontSize READ fontSize WRITE setFontSize) - Q_PROPERTY(QItemModelMapDataMapping *mapping READ mapping WRITE setMapping) - Q_ENUMS(QtDataVis3D::QDataVis::SelectionMode) - Q_ENUMS(QtDataVis3D::QDataVis::ShadowQuality) - Q_ENUMS(QtDataVis3D::QDataVis::LabelTransparency) - -public: - explicit DeclarativeMaps(QQuickItem *parent = 0); - ~DeclarativeMaps(); - - void classBegin(); - void componentComplete(); - - void setData(QAbstractItemModel *data); - QAbstractItemModel *data(); - - // bar specifications; base thickness in x, y and z, enum to indicate which direction is increased with value - // TODO: Start using thickness also in adjustment direction; use it as a relative value. - // For example, in AdjustAll mode setting thickness to (0.1f, 1.0f, 0.5f) would apply value to - // x at 10%, y at 100% and z at 50%. If a dimension is not included, given thickness states its absolute value. - Q_INVOKABLE void setBarSpecs(const QVector3D &thickness = QVector3D(1.0f, 1.0f, 1.0f), - Q3DMaps::AdjustmentDirection direction = Q3DMaps::AdjustHeight); - - // bar type; bars (=cubes), pyramids, cones, cylinders, balls, etc. - Q_INVOKABLE void setBarType(QDataVis::MeshStyle style, bool smooth = false); - - // override bar type with own mesh - Q_INVOKABLE void setMeshFileName(const QString &objFileName); - - // Select preset camera placement - Q_INVOKABLE void setCameraPreset(QDataVis::CameraPreset preset); - - // Set camera rotation if you don't want to use the presets (in horizontal (180...180) and - // vertical (0...90) angles and distance in percentage (10...500)) - Q_INVOKABLE void setCameraPosition(GLfloat horizontal, GLfloat vertical, GLint distance = 100); - - // Set theme (bar colors, shaders, window color, background colors, light intensity and text colors are affected) - Q_INVOKABLE void setTheme(QDataVis::ColorTheme theme); - - // Set color if you don't want to use themes. Set uniform to false if you want the (height) color to change from bottom to top - Q_INVOKABLE void setBarColor(QColor baseColor, QColor heightColor, bool uniform = true); - - // Set area specs - Q_INVOKABLE void setAreaSpecs(const QRect &areaRect, const QImage &image); - - // Set area image - Q_INVOKABLE void setImage(const QImage &image); - Q_INVOKABLE void setImage(const QString &imageUrl); - - // Change selection mode; single bar, bar and row, bar and column, or all - void setSelectionMode(QDataVis::SelectionMode mode); - QDataVis::SelectionMode selectionMode(); - - // Font size adjustment - void setFontSize(float fontsize); - float fontSize(); - - // Set font - void setFont(const QFont &font); - QFont font(); - - // Label transparency adjustment - void setLabelTransparency(QDataVis::LabelTransparency transparency); - QDataVis::LabelTransparency labelTransparency(); - - // Adjust shadow quality - void setShadowQuality(QDataVis::ShadowQuality quality); - QDataVis::ShadowQuality shadowQuality(); - - QItemModelMapDataMapping *mapping() const; - void setMapping(QItemModelMapDataMapping *mapping); - -protected: - Maps3DController *m_shared; - - QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *); - - void mousePressEvent(QMouseEvent *event); - void mouseReleaseEvent(QMouseEvent *event); - void mouseMoveEvent(QMouseEvent *event); - void wheelEvent(QWheelEvent *event); - -private: - QSize m_initializedSize; -}; - -QT_DATAVIS3D_END_NAMESPACE - -#endif diff --git a/src/datavis3dqml2/declarativescatter.cpp b/src/datavis3dqml2/declarativescatter.cpp deleted file mode 100644 index 6731035e..00000000 --- a/src/datavis3dqml2/declarativescatter.cpp +++ /dev/null @@ -1,328 +0,0 @@ -/**************************************************************************** -** -** 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 QtDataVis3D 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 "declarativescatter_p.h" -#include "declarativescatterrenderer_p.h" -#include "qitemmodelscatterdataproxy.h" - -QT_DATAVIS3D_BEGIN_NAMESPACE - -const QString smoothString(QStringLiteral("Smooth")); - -DeclarativeScatter::DeclarativeScatter(QQuickItem *parent) - : QQuickItem(parent), - m_shared(0), - m_initialisedSize(0, 0), - m_cameraPreset(QDataVis::NoPreset), - m_theme(QDataVis::ThemeDefault) -{ - setFlags(QQuickItem::ItemHasContents); - setAcceptedMouseButtons(Qt::AllButtons); - - // TODO: These seem to have no effect; find a way to activate anti-aliasing - setAntialiasing(true); - setSmooth(true); - - // Create the shared component on the main GUI thread. - m_shared = new Scatter3DController(boundingRect().toRect()); - QObject::connect(m_shared, &Abstract3DController::shadowQualityChanged, this, - &DeclarativeScatter::handleShadowQualityUpdate); - - m_shared->setDataProxy(new QItemModelScatterDataProxy); -} - -DeclarativeScatter::~DeclarativeScatter() -{ - delete m_shared; -} - -void DeclarativeScatter::handleShadowQualityUpdate(QDataVis::ShadowQuality quality) -{ - emit shadowQualityChanged(quality); -} - -void DeclarativeScatter::classBegin() -{ - qDebug() << "classBegin"; -} - -void DeclarativeScatter::componentComplete() -{ - qDebug() << "componentComplete"; -} - -QSGNode *DeclarativeScatter::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) -{ - // If old node exists and has right size, reuse it. - if (oldNode && m_initialisedSize == boundingRect().size().toSize()) { - // Update bounding rectangle (that has same size as before). - static_cast<DeclarativeScatterRenderer *>( oldNode )->setRect(boundingRect()); - return oldNode; - } - - // Create a new render node when size changes or if there is no node yet - m_initialisedSize = boundingRect().size().toSize(); - - // Delete old node - if (oldNode) - delete oldNode; - - // Create a new one and set it's bounding rectangle - DeclarativeScatterRenderer *node = new DeclarativeScatterRenderer(window(), m_shared); - node->setRect(boundingRect()); - m_shared->setBoundingRect(boundingRect().toRect()); - return node; -} - -void DeclarativeScatter::setCameraPosition(qreal horizontal, qreal vertical, int distance) -{ - m_shared->setCameraPosition(GLfloat(horizontal), GLfloat(vertical), GLint(distance)); -} - -void DeclarativeScatter::setObjectColor(QColor baseColor, QColor heightColor, QColor depthColor, - bool uniform) -{ - m_shared->setObjectColor(baseColor, heightColor, depthColor, uniform); -} - -void DeclarativeScatter::setData(QAbstractItemModel *data) -{ - static_cast<QItemModelScatterDataProxy *>(m_shared->dataProxy())->setItemModel(data); -} - -QAbstractItemModel *DeclarativeScatter::data() -{ - return static_cast<QItemModelScatterDataProxy *>(m_shared->dataProxy())->itemModel(); -} - -void DeclarativeScatter::setMapping(QItemModelScatterDataMapping *mapping) -{ - static_cast<QItemModelScatterDataProxy *>(m_shared->dataProxy())->setMapping(mapping); -} - -QItemModelScatterDataMapping *DeclarativeScatter::mapping() const -{ - return static_cast<QItemModelScatterDataProxy *>(m_shared->dataProxy())->mapping(); -} - -QValueAxis *DeclarativeScatter::axisX() const -{ - return static_cast<QValueAxis *>(m_shared->axisX()); -} - -void DeclarativeScatter::setAxisX(QValueAxis *axis) -{ - m_shared->setAxisX(axis); -} - -QValueAxis *DeclarativeScatter::axisY() const -{ - return static_cast<QValueAxis *>(m_shared->axisY()); -} - -void DeclarativeScatter::setAxisY(QValueAxis *axis) -{ - m_shared->setAxisY(axis); -} - -QValueAxis *DeclarativeScatter::axisZ() const -{ - return static_cast<QValueAxis *>(m_shared->axisZ()); -} - -void DeclarativeScatter::setAxisZ(QValueAxis *axis) -{ - m_shared->setAxisZ(axis); -} - -void DeclarativeScatter::setObjectType(QDataVis::MeshStyle style) -{ - QString objFile = m_shared->meshFileName(); - bool smooth = objFile.endsWith(smoothString); - m_shared->setObjectType(style, smooth); -} - -QDataVis::MeshStyle DeclarativeScatter::objectType() -{ - QString objFile = m_shared->meshFileName(); - if (objFile.contains("/sphere")) - return QDataVis::Spheres; - else - return QDataVis::Dots; -} - -void DeclarativeScatter::setObjectSmooth(bool smooth) -{ - QString objFile = m_shared->meshFileName(); - if (objFile.endsWith(smoothString)) { - if (smooth) - return; // Already smooth; do nothing - else // Rip Smooth off the end - objFile.resize(objFile.indexOf(smoothString)); - } else { - if (!smooth) // Already flat; do nothing - return; - else // Append Smooth to the end - objFile.append(smoothString); - } - m_shared->setMeshFileName(objFile); -} - -bool DeclarativeScatter::objectSmooth() -{ - QString objFile = m_shared->meshFileName(); - return objFile.endsWith(smoothString); -} - -void DeclarativeScatter::setMeshFileName(const QString &objFileName) -{ - m_shared->setMeshFileName(objFileName); -} - -QString DeclarativeScatter::meshFileName() -{ - return m_shared->meshFileName(); -} - -void DeclarativeScatter::setCameraPreset(QDataVis::CameraPreset preset) -{ - // TODO: Implement correctly once "improved camera api" (QTRD-2122) is implemented - // We need to save this locally, as there are no getters for it in controller - m_cameraPreset = preset; - m_shared->setCameraPreset(preset); -} - -QDataVis::CameraPreset DeclarativeScatter::cameraPreset() -{ - return m_cameraPreset; -} - -void DeclarativeScatter::setTheme(QDataVis::ColorTheme theme) -{ - // TODO: Implement correctly once "user-modifiable themes" (QTRD-2120) is implemented - // We need to save this locally, as there are no getters for it in controller - m_theme = theme; - m_shared->setColorTheme(theme); - - // TODO: Investigate why the beforeSynchronizing() signal requires update and is not sent automatically when this value changes, - // but is sent wen e.g. enable/disable background changes. - update(); -} - -QDataVis::ColorTheme DeclarativeScatter::theme() -{ - return m_theme; -} - -void DeclarativeScatter::setFontSize(float fontsize) -{ - m_shared->setFontSize(fontsize); -} - -float DeclarativeScatter::fontSize() -{ - return m_shared->fontSize(); -} - -void DeclarativeScatter::setFont(const QFont &font) -{ - m_shared->setFont(font); -} - -QFont DeclarativeScatter::font() -{ - return m_shared->font(); -} - -void DeclarativeScatter::setLabelTransparency(QDataVis::LabelTransparency transparency) -{ - m_shared->setLabelTransparency(transparency); -} - -QDataVis::LabelTransparency DeclarativeScatter::labelTransparency() -{ - return m_shared->labelTransparency(); -} - -void DeclarativeScatter::setGridVisible(bool visible) -{ - m_shared->setGridEnabled(visible); -} - -bool DeclarativeScatter::isGridVisible() -{ - return m_shared->gridEnabled(); -} - -void DeclarativeScatter::setBackgroundVisible(bool visible) -{ - m_shared->setBackgroundEnabled(visible); -} - -bool DeclarativeScatter::isBackgroundVisible() -{ - return m_shared->backgroundEnabled(); -} - -void DeclarativeScatter::setSelectionMode(QDataVis::SelectionMode mode) -{ - m_shared->setSelectionMode(mode); -} - -QDataVis::SelectionMode DeclarativeScatter::selectionMode() -{ - return m_shared->selectionMode(); -} - -void DeclarativeScatter::setShadowQuality(QDataVis::ShadowQuality quality) -{ - m_shared->setShadowQuality(quality); -} - -QDataVis::ShadowQuality DeclarativeScatter::shadowQuality() -{ - return m_shared->shadowQuality(); -} - -void DeclarativeScatter::mousePressEvent(QMouseEvent *event) -{ - QPoint mousePos = event->pos(); - //mousePos.setY(height() - mousePos.y()); - m_shared->mousePressEvent(event, mousePos); -} - -void DeclarativeScatter::mouseReleaseEvent(QMouseEvent *event) -{ - QPoint mousePos = event->pos(); - //mousePos.setY(height() - mousePos.y()); - m_shared->mouseReleaseEvent(event, mousePos); -} - -void DeclarativeScatter::mouseMoveEvent(QMouseEvent *event) -{ - QPoint mousePos = event->pos(); - //mousePos.setY(height() - mousePos.y()); - m_shared->mouseMoveEvent(event, mousePos); -} - -void DeclarativeScatter::wheelEvent(QWheelEvent *event) -{ - m_shared->wheelEvent(event); -} - -QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3dqml2/declarativescatter_p.h b/src/datavis3dqml2/declarativescatter_p.h deleted file mode 100644 index dce5c021..00000000 --- a/src/datavis3dqml2/declarativescatter_p.h +++ /dev/null @@ -1,175 +0,0 @@ -/**************************************************************************** -** -** 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 QtDataVis3D 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 QtDataVis3D 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 DECLARATIVESCATTER_P_H -#define DECLARATIVESCATTER_P_H - -#include "datavis3dglobal_p.h" -#include "scatter3dcontroller_p.h" -#include "declarativescatter_p.h" -#include "qitemmodelscatterdatamapping.h" -#include "qvalueaxis.h" - -#include <QAbstractItemModel> -#include <QQuickItem> -#include <QObject> - -QT_DATAVIS3D_BEGIN_NAMESPACE - -class DeclarativeScatter : public QQuickItem -{ - Q_OBJECT - Q_PROPERTY(QAbstractItemModel *data READ data WRITE setData) - Q_PROPERTY(QItemModelScatterDataMapping *mapping READ mapping WRITE setMapping) - Q_PROPERTY(QValueAxis *axisX READ axisX WRITE setAxisX) - Q_PROPERTY(QValueAxis *axisY READ axisY WRITE setAxisY) - Q_PROPERTY(QValueAxis *axisZ READ axisZ WRITE setAxisZ) - Q_PROPERTY(QtDataVis3D::QDataVis::SelectionMode selectionMode READ selectionMode WRITE setSelectionMode) - Q_PROPERTY(QtDataVis3D::QDataVis::LabelTransparency labelTransparency READ labelTransparency WRITE setLabelTransparency) - Q_PROPERTY(QtDataVis3D::QDataVis::ShadowQuality shadowQuality READ shadowQuality WRITE setShadowQuality) - Q_PROPERTY(QtDataVis3D::QDataVis::MeshStyle objectType READ objectType WRITE setObjectType) - Q_PROPERTY(QtDataVis3D::QDataVis::CameraPreset cameraPreset READ cameraPreset WRITE setCameraPreset) - Q_PROPERTY(QtDataVis3D::QDataVis::ColorTheme theme READ theme WRITE setTheme) - Q_PROPERTY(bool objectSmooth READ objectSmooth WRITE setObjectSmooth) - Q_PROPERTY(QString meshFileName READ meshFileName WRITE setMeshFileName) - Q_PROPERTY(QFont font READ font WRITE setFont) - Q_PROPERTY(float fontSize READ fontSize WRITE setFontSize) - Q_PROPERTY(bool gridVisible READ isGridVisible WRITE setGridVisible) - Q_PROPERTY(bool backgroundVisible READ isBackgroundVisible WRITE setBackgroundVisible) - Q_ENUMS(QtDataVis3D::QDataVis::SelectionMode) - Q_ENUMS(QtDataVis3D::QDataVis::ShadowQuality) - Q_ENUMS(QtDataVis3D::QDataVis::LabelTransparency) - Q_ENUMS(QtDataVis3D::QDataVis::MeshStyle) - Q_ENUMS(QtDataVis3D::QDataVis::CameraPreset) - Q_ENUMS(QtDataVis3D::QDataVis::ColorTheme) - -public: - explicit DeclarativeScatter(QQuickItem *parent = 0); - ~DeclarativeScatter(); - - void classBegin(); - void componentComplete(); - - // Set camera rotation if you don't want to use the presets (in horizontal (-180...180) and - // vertical (-90...90) angles and distance in percentage (10...500)) - Q_INVOKABLE void setCameraPosition(qreal horizontal, qreal vertical, int distance); - - // Set color if you don't want to use themes. Set uniform to false if you want the (height) - // color to change from bottom to top - Q_INVOKABLE void setObjectColor(QColor baseColor, QColor heightColor, QColor depthColor, - bool uniform = true); - - // Add whole data set. - void setData(QAbstractItemModel *data); - QAbstractItemModel *data(); - - QItemModelScatterDataMapping *mapping() const; - void setMapping(QItemModelScatterDataMapping *mapping); - - QValueAxis *axisX() const; - void setAxisX(QValueAxis *axis); - QValueAxis *axisY() const; - void setAxisY(QValueAxis *axis); - QValueAxis *axisZ() const; - void setAxisZ(QValueAxis *axis); - - // Object type - void setObjectType(QDataVis::MeshStyle style); - QDataVis::MeshStyle objectType(); - - // Object smoothing - void setObjectSmooth(bool smooth); - bool objectSmooth(); - - // override object type with own mesh - void setMeshFileName(const QString &objFileName); - QString meshFileName(); - - // Select preset camera placement - void setCameraPreset(QDataVis::CameraPreset preset); - QDataVis::CameraPreset cameraPreset(); - - // Set theme (object colors, shaders, window color, background colors, light intensity and text - // colors are affected) - void setTheme(QDataVis::ColorTheme theme); - QDataVis::ColorTheme theme(); - - // Change selection mode - void setSelectionMode(QDataVis::SelectionMode mode); - QDataVis::SelectionMode selectionMode(); - - // Font size adjustment - void setFontSize(float fontsize); - float fontSize(); - - // Set font - void setFont(const QFont &font); - QFont font(); - - // Label transparency adjustment - void setLabelTransparency(QDataVis::LabelTransparency transparency); - QDataVis::LabelTransparency labelTransparency(); - - // Enable or disable background grid - void setGridVisible(bool visible); - bool isGridVisible(); - - // Enable or disable background mesh - void setBackgroundVisible(bool visible); - bool isBackgroundVisible(); - - // Adjust shadow quality - void setShadowQuality(QDataVis::ShadowQuality quality); - QDataVis::ShadowQuality shadowQuality(); - -public slots: - // Used to detect when shadow quality changes autonomously due to e.g. resizing. - void handleShadowQualityUpdate(QDataVis::ShadowQuality quality); - -signals: - // Signals shadow quality changes. - void shadowQualityChanged(QDataVis::ShadowQuality quality); - -protected: - Scatter3DController *m_shared; - QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *); - - void mousePressEvent(QMouseEvent *event); - void mouseReleaseEvent(QMouseEvent *event); - void mouseMoveEvent(QMouseEvent *event); - void wheelEvent(QWheelEvent *event); - -private: - QSize m_initialisedSize; - QDataVis::CameraPreset m_cameraPreset; - QDataVis::ColorTheme m_theme; -}; - -QT_DATAVIS3D_END_NAMESPACE - -#endif diff --git a/src/datavis3dqml2/qmldir b/src/datavis3dqml2/qmldir deleted file mode 100644 index 876138db..00000000 --- a/src/datavis3dqml2/qmldir +++ /dev/null @@ -1,3 +0,0 @@ -module com.digia.QtDataVis3D -plugin datavis3dqml2 - diff --git a/src/datavisualization/axis/axis.pri b/src/datavisualization/axis/axis.pri new file mode 100644 index 00000000..4e96618b --- /dev/null +++ b/src/datavisualization/axis/axis.pri @@ -0,0 +1,12 @@ +HEADERS += \ + $$PWD/q3dabstractaxis.h \ + $$PWD/q3dabstractaxis_p.h \ + $$PWD/q3dvalueaxis.h \ + $$PWD/q3dvalueaxis_p.h \ + $$PWD/q3dcategoryaxis.h \ + $$PWD/q3dcategoryaxis_p.h + +SOURCES += \ + $$PWD/q3dabstractaxis.cpp \ + $$PWD/q3dvalueaxis.cpp \ + $$PWD/q3dcategoryaxis.cpp diff --git a/src/datavisualization/axis/q3dabstractaxis.cpp b/src/datavisualization/axis/q3dabstractaxis.cpp new file mode 100644 index 00000000..07761d0c --- /dev/null +++ b/src/datavisualization/axis/q3dabstractaxis.cpp @@ -0,0 +1,373 @@ +/**************************************************************************** +** +** 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 "q3dabstractaxis.h" +#include "q3dabstractaxis_p.h" + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +/*! + * \class Q3DAbstractAxis + * \inmodule QtDataVisualization + * \brief Q3DAbstractAxis is base class for axes of a graph. + * \since 1.0.0 + * + * You should not need to use this class directly, but one of its subclasses instead. + * + * \sa Q3DCategoryAxis, Q3DValueAxis + */ + +/*! + * \qmltype AbstractAxis3D + * \inqmlmodule com.digia.QtDataVisualization 1.0 + * \since com.digia.QtDataVisualization 1.0 + * \ingroup datavisualization_qml + * \instantiates Q3DAbstractAxis + * \brief AbstractAxis3D is base type for axes of a graph. + * + * This type is uncreatable, but contains properties that are exposed via subtypes. + */ + +/*! + * \qmlproperty string AbstractAxis3D::title + * Defines the title for the axis. + */ + +/*! + * \qmlproperty list AbstractAxis3D::labels + * Defines the labels for the axis. + */ + +/*! + * \qmlproperty AbstractAxis3D.AxisOrientation AbstractAxis3D::orientation + * Defines the orientation of the axis. + */ + +/*! + * \qmlproperty AbstractAxis3D.AxisType AbstractAxis3D::type + * Defines the type of the axis. + */ + +/*! + * \qmlproperty real AbstractAxis3D::min + * + * Defines the minimum value on the axis. + * When setting this property the max is adjusted if necessary, to ensure that the range remains + * valid. + */ + +/*! + * \qmlproperty real AbstractAxis3D::max + * + * Defines the maximum value on the axis. + * When setting this property the min is adjusted if necessary, to ensure that the range remains + * valid. + */ + +/*! + * \qmlproperty bool AbstractAxis3D::autoAdjustRange + * + * If set, the axis will automatically adjust the range so that all data fits in it. + */ + + +/*! + * \enum Q3DAbstractAxis::AxisOrientation + * + * The orientation of the axis object. + * + * \value AxisOrientationNone + * \value AxisOrientationX + * \value AxisOrientationY + * \value AxisOrientationZ + */ + +/*! + * \enum Q3DAbstractAxis::AxisType + * + * The type of the axis object. + * + * \value AxisTypeNone + * \value AxisTypeCategory + * \value AxisTypeValue + */ + +/*! + * \internal + */ +Q3DAbstractAxis::Q3DAbstractAxis(Q3DAbstractAxisPrivate *d, QObject *parent) : + QObject(parent), + d_ptr(d) +{ +} + +/*! + * Destroys Q3DAbstractAxis. + */ +Q3DAbstractAxis::~Q3DAbstractAxis() +{ +} + +/*! + * \property Q3DAbstractAxis::title + * + * Defines the title for the axis. + */ +QString Q3DAbstractAxis::title() const +{ + return d_ptr->m_title; +} + +/*! + * \property Q3DAbstractAxis::labels + * + * Defines the labels for the axis. + */ +QStringList Q3DAbstractAxis::labels() const +{ + d_ptr->updateLabels(); + return d_ptr->m_labels; +} + +/*! + * \property Q3DAbstractAxis::orientation + * + * Defines the orientation of the axis, one of \c Q3DAbstractAxis::AxisOrientation. + */ +Q3DAbstractAxis::AxisOrientation Q3DAbstractAxis::orientation() const +{ + return d_ptr->m_orientation; +} + +/*! + * \property Q3DAbstractAxis::type + * + * Defines the type of the axis, one of \c Q3DAbstractAxis::AxisType. + */ +Q3DAbstractAxis::AxisType Q3DAbstractAxis::type() const +{ + return d_ptr->m_type; +} + +void Q3DAbstractAxis::setTitle(QString title) +{ + if (d_ptr->m_title != title) { + d_ptr->m_title = title; + emit titleChanged(title); + } +} + +/*! + * Sets value range of the axis from \a min to \a max. + * When setting the range, the max is adjusted if necessary, to ensure that the range remains valid. + * \note For Q3DCategoryAxis this specifies the index range of rows or columns to show. + */ +void Q3DAbstractAxis::setRange(qreal min, qreal max) +{ + d_ptr->setRange(min, max); + setAutoAdjustRange(false); +} + +/*! + * \property Q3DAbstractAxis::min + * + * Defines the minimum value on the axis. + * When setting this property the max is adjusted if necessary, to ensure that the range remains + * valid. + * \note For Q3DCategoryAxis this specifies the index of the first row or column to show. + */ +void Q3DAbstractAxis::setMin(qreal min) +{ + d_ptr->setMin(min); + setAutoAdjustRange(false); +} + +/*! + * \property Q3DAbstractAxis::max + * + * Defines the maximum value on the axis. + * When setting this property the min is adjusted if necessary, to ensure that the range remains + * valid. + * \note For Q3DCategoryAxis this specifies the index of the last row or column to show. + */ +void Q3DAbstractAxis::setMax(qreal max) +{ + d_ptr->setMax(max); + setAutoAdjustRange(false); +} + +qreal Q3DAbstractAxis::min() const +{ + return d_ptr->m_min; +} + +qreal Q3DAbstractAxis::max() const +{ + return d_ptr->m_max; +} + +/*! + * \property Q3DAbstractAxis::autoAdjustRange + * + * If set, the axis will automatically adjust the range so that all data fits in it. + * + * \sa setRange(), setMin(), setMax() + */ +void Q3DAbstractAxis::setAutoAdjustRange(bool autoAdjust) +{ + if (d_ptr->m_autoAdjust != autoAdjust) { + d_ptr->m_autoAdjust = autoAdjust; + emit autoAdjustRangeChanged(autoAdjust); + } +} + +bool Q3DAbstractAxis::isAutoAdjustRange() const +{ + return d_ptr->m_autoAdjust; +} + +// Q3DAbstractAxisPrivate + +Q3DAbstractAxisPrivate::Q3DAbstractAxisPrivate(Q3DAbstractAxis *q, Q3DAbstractAxis::AxisType type) + : QObject(0), + q_ptr(q), + m_orientation(Q3DAbstractAxis::AxisOrientationNone), + m_type(type), + m_isDefaultAxis(false), + m_min(0.0), + m_max(10.0), + m_autoAdjust(true), + m_onlyPositiveValues(false), + m_allowMinMaxSame(false) +{ +} + +Q3DAbstractAxisPrivate::~Q3DAbstractAxisPrivate() +{ +} + +void Q3DAbstractAxisPrivate::setOrientation(Q3DAbstractAxis::AxisOrientation orientation) +{ + if (m_orientation == Q3DAbstractAxis::AxisOrientationNone) + m_orientation = orientation; + else + Q_ASSERT("Attempted to reset axis orientation."); +} + +void Q3DAbstractAxisPrivate::updateLabels() +{ + // Default implementation does nothing +} + +void Q3DAbstractAxisPrivate::setRange(qreal min, qreal max) +{ + bool adjusted = false; + if (m_onlyPositiveValues) { + if (min < 0.0) { + min = 0.0; + adjusted = true; + } + if (max < 0.0) { + max = 0.0; + adjusted = true; + } + } + // If min >= max, we adjust ranges so that + // m_max becomes (min + 1.0) + // as axes need some kind of valid range. + bool dirty = false; + if (m_min != min) { + m_min = min; + dirty = true; + } + if (m_max != max || min > max || (!m_allowMinMaxSame && min == max)) { + if (min > max || (!m_allowMinMaxSame && min == max)) { + m_max = min + 1.0; + adjusted = true; + } else { + m_max = max; + } + dirty = true; + } + + if (dirty) { + if (adjusted) { + qWarning() << "Warning: Tried to set invalid range for axis." + " Range automatically adjusted to a valid one:" + << min << "-" << max << "-->" << m_min << "-" << m_max; + } + emit q_ptr->rangeChanged(m_min, m_max); + } +} + +void Q3DAbstractAxisPrivate::setMin(qreal min) +{ + if (m_onlyPositiveValues) { + if (min < 0.0) { + min = 0.0; + qWarning() << "Warning: Tried to set negative minimum for an axis that only supports" + " positive values:" << min; + } + } + + if (m_min != min) { + if (min > m_max || (!m_allowMinMaxSame && min == m_max)) { + qreal oldMax = m_max; + m_max = min + 1.0; + qWarning() << "Warning: Tried to set minimum to equal or larger than maximum for" + " value axis. Maximum automatically adjusted to a valid one:" + << oldMax << "-->" << m_max; + } + m_min = min; + + emit q_ptr->rangeChanged(m_min, m_max); + } +} + +void Q3DAbstractAxisPrivate::setMax(qreal max) +{ + if (m_onlyPositiveValues) { + if (max < 0.0) { + max = 0.0; + qWarning() << "Warning: Tried to set negative maximum for an axis that only supports" + " positive values:" << max; + } + } + + if (m_max != max) { + if (m_min > max || (!m_allowMinMaxSame && m_min == max)) { + qreal oldMin = m_min; + m_min = max - 1.0; + if (m_onlyPositiveValues && m_min < 0.0) { + m_min = 0.0; + if (!m_allowMinMaxSame && max == 0.0) { + m_min = oldMin; + qWarning() << "Unable to set maximum value to zero."; + return; + } + } + qWarning() << "Warning: Tried to set maximum to equal or smaller than minimum for" + " value axis. Minimum automatically adjusted to a valid one:" + << oldMin << "-->" << m_min; + } + m_max = max; + emit q_ptr->rangeChanged(m_min, m_max); + } +} + +QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavis3d/axis/qabstractaxis.h b/src/datavisualization/axis/q3dabstractaxis.h index 4bc0ac16..9e5c426a 100644 --- a/src/datavis3d/axis/qabstractaxis.h +++ b/src/datavisualization/axis/q3dabstractaxis.h @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -16,20 +16,20 @@ ** ****************************************************************************/ -#ifndef QABSTRACTAXIS_H -#define QABSTRACTAXIS_H +#ifndef Q3DABSTRACTAXIS_H +#define Q3DABSTRACTAXIS_H -#include <QtDataVis3D/qdatavis3denums.h> +#include <QtDataVisualization/qdatavisualizationenums.h> #include <QObject> #include <QScopedPointer> #include <QVector> #include <QStringList> -QT_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVISUALIZATION_BEGIN_NAMESPACE -class QAbstractAxisPrivate; +class Q3DAbstractAxisPrivate; -class QT_DATAVIS3D_EXPORT QAbstractAxis : public QObject +class QT_DATAVISUALIZATION_EXPORT Q3DAbstractAxis : public QObject { Q_OBJECT Q_ENUMS(AxisOrientation) @@ -38,6 +38,9 @@ class QT_DATAVIS3D_EXPORT QAbstractAxis : public QObject Q_PROPERTY(QStringList labels READ labels NOTIFY labelsChanged) Q_PROPERTY(AxisOrientation orientation READ orientation) Q_PROPERTY(AxisType type READ type) + Q_PROPERTY(qreal min READ min WRITE setMin NOTIFY rangeChanged) + Q_PROPERTY(qreal max READ max WRITE setMax NOTIFY rangeChanged) + Q_PROPERTY(bool autoAdjustRange READ isAutoAdjustRange WRITE setAutoAdjustRange NOTIFY autoAdjustRangeChanged) public: enum AxisOrientation { @@ -55,9 +58,10 @@ public: }; protected: - explicit QAbstractAxis(QAbstractAxisPrivate *d); + explicit Q3DAbstractAxis(Q3DAbstractAxisPrivate *d, QObject *parent = 0); + public: - virtual ~QAbstractAxis(); + virtual ~Q3DAbstractAxis(); QString title() const; QStringList labels() const; @@ -65,22 +69,32 @@ public: AxisOrientation orientation() const; AxisType type() const; -public slots: + qreal min() const; + qreal max() const; + bool isAutoAdjustRange() const; + void setTitle(QString title); + void setRange(qreal min, qreal max); + void setMin(qreal min); + void setMax(qreal max); + void setAutoAdjustRange(bool autoAdjust); signals: void titleChanged(QString newTitle); void labelsChanged(); + void rangeChanged(qreal min, qreal max); + void autoAdjustRangeChanged(bool autoAdjust); protected: - QScopedPointer<QAbstractAxisPrivate> d_ptr; + QScopedPointer<Q3DAbstractAxisPrivate> d_ptr; private: - Q_DISABLE_COPY(QAbstractAxis) + Q_DISABLE_COPY(Q3DAbstractAxis) friend class Abstract3DController; + friend class Bars3DController; }; -QT_DATAVIS3D_END_NAMESPACE +QT_DATAVISUALIZATION_END_NAMESPACE #endif // QABSTRACTAXIS_H diff --git a/src/datavisualization/axis/q3dabstractaxis_p.h b/src/datavisualization/axis/q3dabstractaxis_p.h new file mode 100644 index 00000000..902f65be --- /dev/null +++ b/src/datavisualization/axis/q3dabstractaxis_p.h @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** 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 "q3dabstractaxis.h" +#include "abstract3dcontroller_p.h" + +#ifndef Q3DABSTRACTAXIS_P_H +#define Q3DABSTRACTAXIS_P_H + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +class Q3DAbstractAxisPrivate : public QObject +{ + Q_OBJECT +public: + Q3DAbstractAxisPrivate(Q3DAbstractAxis *q, Q3DAbstractAxis::AxisType type); + virtual ~Q3DAbstractAxisPrivate(); + + void setOrientation(Q3DAbstractAxis::AxisOrientation orientation); + + inline bool isDefaultAxis() { return m_isDefaultAxis; } + inline void setDefaultAxis(bool isDefault) { m_isDefaultAxis = isDefault; } + + virtual void setRange(qreal min, qreal max); + virtual void setMin(qreal min); + virtual void setMax (qreal max); + +protected: + virtual void updateLabels(); + + Q3DAbstractAxis *q_ptr; + + QString m_title; + QStringList m_labels; + Q3DAbstractAxis::AxisOrientation m_orientation; + Q3DAbstractAxis::AxisType m_type; + bool m_isDefaultAxis; + qreal m_min; + qreal m_max; + bool m_autoAdjust; + bool m_onlyPositiveValues; + bool m_allowMinMaxSame; + + friend class Q3DAbstractAxis; + friend class Q3DValueAxis; + friend class Q3DCategoryAxis; +}; + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif // QABSTRACTAXIS_P_H diff --git a/src/datavisualization/axis/q3dcategoryaxis.cpp b/src/datavisualization/axis/q3dcategoryaxis.cpp new file mode 100644 index 00000000..05f52cdc --- /dev/null +++ b/src/datavisualization/axis/q3dcategoryaxis.cpp @@ -0,0 +1,152 @@ +/**************************************************************************** +** +** 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 "q3dcategoryaxis.h" +#include "q3dcategoryaxis_p.h" +#include "bars3dcontroller_p.h" +#include "qbardataproxy.h" + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +/*! + * \class Q3DCategoryAxis + * \inmodule QtDataVisualization + * \brief The Q3DCategoryAxis class is used for manipulating an axis of a graph. + * \since 1.0.0 + * + * Q3DCategoryAxis provides an axis that can be given labels. The axis is divided into equal-sized + * categories based on the data window size defined by setting the axis range. + * + * Grid lines are drawn between categories, if visible. Labels are drawn to positions of categories + * if provided. + */ + +/*! + * \qmltype CategoryAxis3D + * \inqmlmodule com.digia.QtDataVisualization 1.0 + * \since com.digia.QtDataVisualization 1.0 + * \ingroup datavisualization_qml + * \instantiates Q3DCategoryAxis + * \inherits AbstractAxis3D + * \brief The CategoryAxis3D type is used for manipulating an axis of a graph. + * + * This type provides an axis that can be given labels. + */ + +/*! + * \qmlproperty list CategoryAxis3D::categoryLabels + * Defines labels for axis applied to categories. If there are fewer labels than categories, the + * remaining ones do not have a label. If category labels are not explicitly defined, labels are + * generated from the data row and column labels. + */ + +/*! + * Constructs Q3DCategoryAxis with \a parent. + */ +Q3DCategoryAxis::Q3DCategoryAxis(QObject *parent) : + Q3DAbstractAxis(new Q3DCategoryAxisPrivate(this), parent) +{ +} + +/*! + * Destroys Q3DCategoryAxis. + */ +Q3DCategoryAxis::~Q3DCategoryAxis() +{ +} + +/*! + * \property Q3DCategoryAxis::categoryLabels + * + * Defines labels for axis applied to categories. If there are fewer labels than categories, the + * remaining ones do not have a label. If category labels are not explicitly defined, labels are + * generated from the data row and column labels. + * + * \note CategoryLabels actually reads/writes the Q3DAbstractAxis::labels property, + * which is read only there. Since subclass cannot have property with same name, + * this partially duplicate property is necessary. + */ +QStringList Q3DCategoryAxis::categoryLabels() const +{ + return labels(); +} + +void Q3DCategoryAxis::setCategoryLabels(const QStringList &labels) +{ + dptr()->m_labelsExplicitlySet = !labels.isEmpty(); + bool labelsFromData = false; + + // Get labels from data proxy if axis is attached to a bar controller and an active axis there + if (labels.isEmpty()) { + Bars3DController *controller = qobject_cast<Bars3DController *>(parent()); + if (controller) { + if (controller->axisX() == this) { + controller->handleDataRowLabelsChanged(); + labelsFromData = true; + } else if (controller->axisZ() == this) { + controller->handleDataColumnLabelsChanged(); + labelsFromData = true; + } + } + } + + if (!labelsFromData && d_ptr->m_labels != labels) { + d_ptr->m_labels = labels; + emit labelsChanged(); + } +} + +/*! + * \internal + */ +Q3DCategoryAxisPrivate *Q3DCategoryAxis::dptr() +{ + return static_cast<Q3DCategoryAxisPrivate *>(d_ptr.data()); +} + +Q3DCategoryAxisPrivate::Q3DCategoryAxisPrivate(Q3DCategoryAxis *q) + : Q3DAbstractAxisPrivate(q, Q3DAbstractAxis::AxisTypeCategory), + m_labelsExplicitlySet(false) +{ + m_onlyPositiveValues = true; + m_allowMinMaxSame = true; +} + +Q3DCategoryAxisPrivate::~Q3DCategoryAxisPrivate() +{ +} + +/*! + * \internal + * Controller uses this function to set labels from data proxy as category labels. + * If the labels have been explicitly set by user, data proxy labels are not used. + */ +void Q3DCategoryAxisPrivate::setDataLabels(const QStringList &labels) +{ + if (!m_labelsExplicitlySet && m_labels != labels) { + m_labels = labels; + emit qptr()->labelsChanged(); + } +} + +Q3DCategoryAxis *Q3DCategoryAxisPrivate::qptr() +{ + return static_cast<Q3DCategoryAxis *>(q_ptr); +} + +QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavis3d/axis/qcategoryaxis.h b/src/datavisualization/axis/q3dcategoryaxis.h index 8d1e3f57..ef545950 100644 --- a/src/datavis3d/axis/qcategoryaxis.h +++ b/src/datavisualization/axis/q3dcategoryaxis.h @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -16,39 +16,35 @@ ** ****************************************************************************/ -#ifndef QCATEGORYAXIS_H -#define QCATEGORYAXIS_H +#ifndef Q3DCATEGORYAXIS_H +#define Q3DCATEGORYAXIS_H -#include <QtDataVis3D/qabstractaxis.h> +#include <QtDataVisualization/q3dabstractaxis.h> -QT_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVISUALIZATION_BEGIN_NAMESPACE -class QCategoryAxisPrivate; +class Q3DCategoryAxisPrivate; -class QT_DATAVIS3D_EXPORT QCategoryAxis : public QAbstractAxis +class QT_DATAVISUALIZATION_EXPORT Q3DCategoryAxis : public Q3DAbstractAxis { Q_OBJECT - // Note: categoryLabels actually reads/writes the labels property in abstract axis, - // which is read only there. Since subclass cannot have property with same name, - // this partially duplicate property is necessary. Q_PROPERTY(QStringList categoryLabels READ categoryLabels WRITE setCategoryLabels) + public: - explicit QCategoryAxis(); - ~QCategoryAxis(); + explicit Q3DCategoryAxis(QObject *parent = 0); + virtual ~Q3DCategoryAxis(); QStringList categoryLabels() const; - -public slots: void setCategoryLabels(const QStringList &labels); protected: - QCategoryAxisPrivate *dptr(); + Q3DCategoryAxisPrivate *dptr(); private: - - Q_DISABLE_COPY(QCategoryAxis) + Q_DISABLE_COPY(Q3DCategoryAxis) + friend class Bars3DController; }; -QT_DATAVIS3D_END_NAMESPACE +QT_DATAVISUALIZATION_END_NAMESPACE #endif // QCATEGORYAXIS_H diff --git a/src/datavis3d/axis/qcategoryaxis_p.h b/src/datavisualization/axis/q3dcategoryaxis_p.h index 3ca79c64..9b66e48a 100644 --- a/src/datavis3d/axis/qcategoryaxis_p.h +++ b/src/datavisualization/axis/q3dcategoryaxis_p.h @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -20,30 +20,38 @@ // W A R N I N G // ------------- // -// This file is not part of the QtDataVis3D API. It exists purely as an +// 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 "qcategoryaxis.h" -#include "qabstractaxis_p.h" +#include "q3dcategoryaxis.h" +#include "q3dabstractaxis_p.h" #include "qbardataitem.h" #ifndef QCATEGORYAXIS_P_H #define QCATEGORYAXIS_P_H -QT_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVISUALIZATION_BEGIN_NAMESPACE -class QCategoryAxisPrivate : public QAbstractAxisPrivate +class Q3DCategoryAxisPrivate : public Q3DAbstractAxisPrivate { Q_OBJECT public: - QCategoryAxisPrivate(QCategoryAxis *q); - virtual ~QCategoryAxisPrivate(); + Q3DCategoryAxisPrivate(Q3DCategoryAxis *q); + virtual ~Q3DCategoryAxisPrivate(); + + void setDataLabels(const QStringList &labels); + +private: + Q3DCategoryAxis *qptr(); + + bool m_labelsExplicitlySet; + friend class Q3DCategoryAxis; }; -QT_DATAVIS3D_END_NAMESPACE +QT_DATAVISUALIZATION_END_NAMESPACE #endif // QCATEGORYAXIS_P_H diff --git a/src/datavisualization/axis/q3dvalueaxis.cpp b/src/datavisualization/axis/q3dvalueaxis.cpp new file mode 100644 index 00000000..5e38e4ca --- /dev/null +++ b/src/datavisualization/axis/q3dvalueaxis.cpp @@ -0,0 +1,270 @@ +/**************************************************************************** +** +** 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 "q3dvalueaxis.h" +#include "q3dvalueaxis_p.h" +#include "utils_p.h" + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +/*! + * \class Q3DValueAxis + * \inmodule QtDataVisualization + * \brief The Q3DValueAxis class is used for manipulating an axis of a graph. + * \since 1.0.0 + * + * Q3DValueAxis provides an axis that can be given a range of values and segment and subsegment + * counts to divide the range into. + * + * Labels are drawn between each segment. Grid lines are drawn between each segment and each + * subsegment. \note If visible, there will always be at least two grid lines and labels indicating + * the minimum and the maximum values of the range, as there is always at least one segment. + */ + +/*! + * \qmltype ValueAxis3D + * \inqmlmodule com.digia.QtDataVisualization 1.0 + * \since com.digia.QtDataVisualization 1.0 + * \ingroup datavisualization_qml + * \instantiates Q3DValueAxis + * \inherits AbstractAxis3D + * \brief The ValueAxis3D type is used for manipulating an axis of a graph. + * + * This type provides an axis that can be given a range of values and segment and subsegment + * counts to divide the range into. + */ + + +/*! + * \qmlproperty int ValueAxis3D::segmentCount + * + * Defines the number of segments on the axis. This indicates how many labels are drawn. The number + * of grid lines to be drawn is calculated with formula: \c {segments * subsegments + 1}. + * The preset default is \c 5, and it can not be below \c 1. + */ + +/*! + * \qmlproperty int ValueAxis3D::subSegmentCount + * + * Defines the number of subsegments inside each segment on the axis. Grid lines are drawn between + * each subsegment, in addition to each segment. + * The preset default is \c 1, and it can not be below \c 1. + */ + +/*! + * \qmlproperty string ValueAxis3D::labelFormat + * + * Defines the label format to be used for the labels on this axis. Supported specifiers are: + * \c {d, i, o, x, X, f, F, e, E, g, G, c}. See QString::sprintf() for additional details. + */ + +/*! + * Constructs Q3DValueAxis with the given \a parent. + */ +Q3DValueAxis::Q3DValueAxis(QObject *parent) : + Q3DAbstractAxis(new Q3DValueAxisPrivate(this), parent) +{ +} + +/*! + * Destroys Q3DValueAxis. + */ +Q3DValueAxis::~Q3DValueAxis() +{ +} + + +/*! + * \property Q3DValueAxis::segmentCount + * + * Defines the number of segments on the axis. This indicates how many labels are drawn. The number + * of grid lines to be drawn is calculated with formula: \c {segments * subsegments + 1}. + * The preset default is \c 5, and it can not be below \c 1. + * + * \sa setSubSegmentCount() + */ +void Q3DValueAxis::setSegmentCount(int count) +{ + if (count <= 0) { + qWarning() << "Warning: Illegal segment count automatically adjusted to a legal one:" + << count << "-> 1"; + count = 1; + } + if (dptr()->m_segmentCount != count){ + dptr()->m_segmentCount = count; + dptr()->emitLabelsChanged(); + emit segmentCountChanged(count); + } +} + +int Q3DValueAxis::segmentCount() const +{ + return dptrc()->m_segmentCount; +} + +/*! + * \property Q3DValueAxis::subSegmentCount + * + * Defines the number of subsegments inside each segment on the axis. Grid lines are drawn between + * each subsegment, in addition to each segment. + * The preset default is \c 1, and it can not be below \c 1. + * + * \sa setSegmentCount() + */ +void Q3DValueAxis::setSubSegmentCount(int count) +{ + if (count <= 0) { + qWarning() << "Warning: Illegal subsegment count automatically adjusted to a legal one:" + << count << "-> 1"; + count = 1; + } + if (dptr()->m_subSegmentCount != count) { + dptr()->m_subSegmentCount = count; + emit subSegmentCountChanged(count); + } +} + +int Q3DValueAxis::subSegmentCount() const +{ + return dptrc()->m_subSegmentCount; +} + +/*! + * \property Q3DValueAxis::labelFormat + * + * Defines the label format to be used for the labels on this axis. Supported specifiers are: + * \c {d, i, o, x, X, f, F, e, E, g, G, c}. See QString::sprintf() for additional details. + * + * Usage example: + * + * \c {axis->setLabelFormat("%.2f mm");} + */ +void Q3DValueAxis::setLabelFormat(const QString &format) +{ + if (dptr()->m_labelFormat != format) { + dptr()->m_labelFormat = format; + dptr()->emitLabelsChanged(); + emit labelFormatChanged(format); + } +} + +QString Q3DValueAxis::labelFormat() const +{ + return dptrc()->m_labelFormat; +} + +/*! + * \internal + */ +Q3DValueAxisPrivate *Q3DValueAxis::dptr() +{ + return static_cast<Q3DValueAxisPrivate *>(d_ptr.data()); +} + +/*! + * \internal + */ +const Q3DValueAxisPrivate *Q3DValueAxis::dptrc() const +{ + return static_cast<const Q3DValueAxisPrivate *>(d_ptr.data()); +} + +Q3DValueAxisPrivate::Q3DValueAxisPrivate(Q3DValueAxis *q) + : Q3DAbstractAxisPrivate(q, Q3DAbstractAxis::AxisTypeValue), + m_segmentCount(5), + m_subSegmentCount(1), + m_labelFormat(Utils::defaultLabelFormat()), + m_labelsDirty(true) +{ +} + +Q3DValueAxisPrivate::~Q3DValueAxisPrivate() +{ +} + +void Q3DValueAxisPrivate::setRange(qreal min, qreal max) +{ + bool dirty = (min != m_min || max != m_max); + + Q3DAbstractAxisPrivate::setRange(min, max); + + if (dirty) + emitLabelsChanged(); +} + +void Q3DValueAxisPrivate::setMin(qreal min) +{ + bool dirty = (min != m_min); + + Q3DAbstractAxisPrivate::setMin(min); + + if (dirty) + emitLabelsChanged(); +} + +void Q3DValueAxisPrivate::setMax(qreal max) +{ + bool dirty = (max != m_max); + + Q3DAbstractAxisPrivate::setMax(max); + + if (dirty) + emitLabelsChanged(); +} + +void Q3DValueAxisPrivate::emitLabelsChanged() +{ + m_labelsDirty = true; + emit q_ptr->labelsChanged(); +} + +void Q3DValueAxisPrivate::updateLabels() +{ + if (!m_labelsDirty) + return; + + m_labelsDirty = false; + + QStringList newLabels; + newLabels.reserve(m_segmentCount + 1); + + // First label is at axis min, which is an extra segment + qreal segmentStep = (m_max - m_min) / m_segmentCount; + + QString formatString(m_labelFormat); + Utils::ParamType paramType = Utils::findFormatParamType(formatString); + QByteArray formatArray = formatString.toUtf8(); + + for (int i = 0; i < m_segmentCount; i++) { + qreal value = m_min + (segmentStep * i); + newLabels.append(Utils::formatLabel(formatArray, paramType, value)); + } + + // Ensure max label doesn't suffer from any rounding errors + newLabels.append(Utils::formatLabel(formatArray, paramType, m_max)); + + if (m_labels != newLabels) + m_labels = newLabels; +} + +Q3DValueAxis *Q3DValueAxisPrivate::qptr() +{ + return static_cast<Q3DValueAxis *>(q_ptr); +} + +QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavis3d/axis/qvalueaxis.h b/src/datavisualization/axis/q3dvalueaxis.h index c9658f37..f1280e25 100644 --- a/src/datavis3d/axis/qvalueaxis.h +++ b/src/datavisualization/axis/q3dvalueaxis.h @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -19,59 +19,47 @@ #ifndef QVALUEAXIS_H #define QVALUEAXIS_H -#include <QtDataVis3D/qabstractaxis.h> +#include <QtDataVisualization/q3dabstractaxis.h> -QT_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVISUALIZATION_BEGIN_NAMESPACE -class QValueAxisPrivate; +class Q3DValueAxisPrivate; -class QT_DATAVIS3D_EXPORT QValueAxis : public QAbstractAxis +class QT_DATAVISUALIZATION_EXPORT Q3DValueAxis : public Q3DAbstractAxis { Q_OBJECT - Q_PROPERTY(qreal min READ min WRITE setMin NOTIFY rangeChanged) - Q_PROPERTY(qreal max READ max WRITE setMax NOTIFY rangeChanged) Q_PROPERTY(int segmentCount READ segmentCount WRITE setSegmentCount NOTIFY segmentCountChanged) Q_PROPERTY(int subSegmentCount READ subSegmentCount WRITE setSubSegmentCount NOTIFY subSegmentCountChanged) - Q_PROPERTY(bool autoAdjustRange READ isAutoAdjustRange WRITE setAutoAdjustRange NOTIFY autoAdjustRangeChanged) Q_PROPERTY(QString labelFormat READ labelFormat WRITE setLabelFormat NOTIFY labelFormatChanged) public: - explicit QValueAxis(); - ~QValueAxis(); + explicit Q3DValueAxis(QObject *parent = 0); + virtual ~Q3DValueAxis(); - qreal min() const; - qreal max() const; int segmentCount() const; int subSegmentCount() const; - bool isAutoAdjustRange() const; QString labelFormat() const; -public slots: - void setRange(qreal min, qreal max); - void setMin(qreal min); - void setMax(qreal max); void setSegmentCount(int count); void setSubSegmentCount(int count); - void setAutoAdjustRange(bool autoAdjust); void setLabelFormat(const QString &format); signals: - void rangeChanged(qreal min, qreal max); void segmentCountChanged(int count); void subSegmentCountChanged(int count); - void autoAdjustRangeChanged(bool autoAdjust); void labelFormatChanged(QString format); protected: - QValueAxisPrivate *dptr(); - const QValueAxisPrivate *dptrc() const; + Q3DValueAxisPrivate *dptr(); + const Q3DValueAxisPrivate *dptrc() const; private: - Q_DISABLE_COPY(QValueAxis) - friend class Bars3dController; + Q_DISABLE_COPY(Q3DValueAxis) + friend class Bars3DController; friend class Scatter3DController; + friend class Surface3DController; }; -QT_DATAVIS3D_END_NAMESPACE +QT_DATAVISUALIZATION_END_NAMESPACE #endif // QVALUEAXIS_H diff --git a/src/datavis3d/axis/qvalueaxis_p.h b/src/datavisualization/axis/q3dvalueaxis_p.h index f730d0c0..5d0084e6 100644 --- a/src/datavis3d/axis/qvalueaxis_p.h +++ b/src/datavisualization/axis/q3dvalueaxis_p.h @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -20,48 +20,47 @@ // W A R N I N G // ------------- // -// This file is not part of the QtDataVis3D API. It exists purely as an +// 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 "qvalueaxis.h" -#include "qabstractaxis_p.h" +#include "q3dvalueaxis.h" +#include "q3dabstractaxis_p.h" #ifndef QVALUEAXIS_P_H #define QVALUEAXIS_P_H -QT_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVISUALIZATION_BEGIN_NAMESPACE -class QValueAxisPrivate : public QAbstractAxisPrivate +class Q3DValueAxisPrivate : public Q3DAbstractAxisPrivate { Q_OBJECT public: - QValueAxisPrivate(QValueAxis *q); - virtual ~QValueAxisPrivate(); + Q3DValueAxisPrivate(Q3DValueAxis *q); + virtual ~Q3DValueAxisPrivate(); - void setRange(qreal min, qreal max); - void setMin(qreal min); - void setMax (qreal max); + virtual void setRange(qreal min, qreal max); + virtual void setMin(qreal min); + virtual void setMax (qreal max); protected: - void recreateLabels(); + void emitLabelsChanged(); + virtual void updateLabels(); - qreal m_min; - qreal m_max; int m_segmentCount; int m_subSegmentCount; - bool m_autoAdjust; QString m_labelFormat; + bool m_labelsDirty; private: - QValueAxis *qptr(); + Q3DValueAxis *qptr(); - friend class QValueAxis; + friend class Q3DValueAxis; }; -QT_DATAVIS3D_END_NAMESPACE +QT_DATAVISUALIZATION_END_NAMESPACE #endif // QVALUEAXIS_P_H diff --git a/src/datavis3d/common.pri b/src/datavisualization/common.pri index 57948697..5b03ab98 100644 --- a/src/datavis3d/common.pri +++ b/src/datavisualization/common.pri @@ -5,4 +5,5 @@ INCLUDEPATH += $$PWD/engine \ $$PWD/global \ $$PWD/utils \ $$PWD/axis \ - $$PWD/data + $$PWD/data \ + $$PWD/input 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/datavis3d/data/abstractrenderitem.cpp b/src/datavisualization/data/abstractrenderitem.cpp index 004fb598..22a1c6de 100644 --- a/src/datavis3d/data/abstractrenderitem.cpp +++ b/src/datavisualization/data/abstractrenderitem.cpp @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -18,48 +18,43 @@ #include "abstractrenderitem_p.h" -QT_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVISUALIZATION_BEGIN_NAMESPACE AbstractRenderItem::AbstractRenderItem() - : m_labelItem(0), - m_selectionLabel(0) + : m_selectionLabelItem(0) { } -AbstractRenderItem::~AbstractRenderItem() +AbstractRenderItem::AbstractRenderItem(const AbstractRenderItem &other) { - delete m_labelItem; - delete m_selectionLabel; + m_selectionLabel = other.m_selectionLabel; + m_translation = other.m_translation; + m_selectionLabelItem = 0; } -LabelItem &AbstractRenderItem::labelItem() +AbstractRenderItem::~AbstractRenderItem() { - if (!m_labelItem) - m_labelItem = new LabelItem; - return *m_labelItem; + delete m_selectionLabelItem; } -LabelItem &AbstractRenderItem::selectionLabel() +LabelItem &AbstractRenderItem::selectionLabelItem() { - if (!m_selectionLabel) - m_selectionLabel = new LabelItem; - return *m_selectionLabel; + if (!m_selectionLabelItem) + m_selectionLabelItem = new LabelItem; + return *m_selectionLabelItem; } -QString &AbstractRenderItem::label() +void AbstractRenderItem::setSelectionLabel(const QString &label) { - if (m_label.isNull()) - formatLabel(); - return m_label; + if (m_selectionLabelItem) + m_selectionLabelItem->clear(); + m_selectionLabel = label; } -void AbstractRenderItem::setLabel(const QString &label) +QString &AbstractRenderItem::selectionLabel() { - if (m_labelItem) - m_labelItem->clear(); - if (m_selectionLabel) - m_selectionLabel->clear(); - m_label = label; + return m_selectionLabel; } -QT_DATAVIS3D_END_NAMESPACE + +QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavis3d/data/abstractrenderitem_p.h b/src/datavisualization/data/abstractrenderitem_p.h index 4bf4df71..5f623c41 100644 --- a/src/datavis3d/data/abstractrenderitem_p.h +++ b/src/datavisualization/data/abstractrenderitem_p.h @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -20,7 +20,7 @@ // W A R N I N G // ------------- // -// This file is not part of the QtDataVis3D API. It exists purely as an +// 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. // @@ -29,46 +29,41 @@ #ifndef ABSTRACTRENDERITEM_P_H #define ABSTRACTRENDERITEM_P_H -#include "datavis3dglobal_p.h" +#include "datavisualizationglobal_p.h" #include "labelitem_p.h" #include <QOpenGLFunctions> #include <QString> #include <QVector3D> -QT_DATAVIS3D_BEGIN_NAMESPACE +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; } - // Label item for formatted label - LabelItem &labelItem(); - // Selection label item (containing special selection texture, if mode is activated) - LabelItem &selectionLabel(); + LabelItem &selectionLabelItem(); - // Formatted label for item. - void setLabel(const QString &label); - QString &label(); // Formats label if not previously formatted + // Formatted selection label for item. + void setSelectionLabel(const QString &label); + QString &selectionLabel(); // Formats selection label if not previously formatted protected: - virtual void formatLabel() = 0; - - QString m_label; + QString m_selectionLabel; QVector3D m_translation; - LabelItem *m_labelItem; - LabelItem *m_selectionLabel; + LabelItem *m_selectionLabelItem; friend class QAbstractDataItem; }; -QT_DATAVIS3D_END_NAMESPACE +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/datavis3d/data/qitemmodelmapdatamapping_p.h b/src/datavisualization/data/baritemmodelhandler_p.h index 99618942..54b45f2e 100644 --- a/src/datavis3d/data/qitemmodelmapdatamapping_p.h +++ b/src/datavisualization/data/baritemmodelhandler_p.h @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -20,37 +20,35 @@ // W A R N I N G // ------------- // -// This file is not part of the QtDataVis3D API. It exists purely as an +// 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 "qitemmodelmapdatamapping.h" +#ifndef BARITEMMODELHANDLER_P_H +#define BARITEMMODELHANDLER_P_H -#ifndef QITEMMODELMAPDATAMAPPING_P_H -#define QITEMMODELMAPDATAMAPPING_P_H +#include "abstractitemmodelhandler_p.h" +#include "qitemmodelbardataproxy.h" -QT_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVISUALIZATION_BEGIN_NAMESPACE -class QItemModelMapDataMappingPrivate : public QObject +class BarItemModelHandler : public AbstractItemModelHandler { Q_OBJECT public: - QItemModelMapDataMappingPrivate(QItemModelMapDataMapping *q); - virtual ~QItemModelMapDataMappingPrivate(); + BarItemModelHandler(QItemModelBarDataProxy *proxy, QObject *parent = 0); + virtual ~BarItemModelHandler(); -private: - QString m_labelRole; - QString m_xPosRole; - QString m_yPosRole; - QString m_valueRole; +protected: + void virtual resolveModel(); - QItemModelMapDataMapping *q_ptr; - - friend class QItemModelMapDataMapping; + QItemModelBarDataProxy *m_proxy; // Not owned + QBarDataArray *m_proxyArray; // Not owned + int m_columnCount; }; -QT_DATAVIS3D_END_NAMESPACE +QT_DATAVISUALIZATION_END_NAMESPACE #endif diff --git a/src/datavis3d/data/barrenderitem.cpp b/src/datavisualization/data/barrenderitem.cpp index db377aa3..558e2f96 100644 --- a/src/datavis3d/data/barrenderitem.cpp +++ b/src/datavisualization/data/barrenderitem.cpp @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -19,28 +19,49 @@ #include "barrenderitem_p.h" #include "bars3drenderer_p.h" -QT_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVISUALIZATION_BEGIN_NAMESPACE BarRenderItem::BarRenderItem() : AbstractRenderItem(), - m_renderer(0), - m_value(0) + 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::formatLabel() +void BarRenderItem::setSliceLabel(const QString &label) { - // Format the string on first access - QString numStr; - numStr.setNum(m_value); - // TODO actually format instead of just prepending the value - m_label.clear(); // Just in case - m_label.append(numStr); - m_label.append(m_renderer->itemLabelFormat()); // TODO format needs to be cached + if (m_sliceLabelItem) + m_sliceLabelItem->clear(); + m_sliceLabel = label; } -QT_DATAVIS3D_END_NAMESPACE +QString &BarRenderItem::sliceLabel() +{ + return m_sliceLabel; +} + + +QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavis3d/data/barrenderitem_p.h b/src/datavisualization/data/barrenderitem_p.h index babab795..6cd2b0fa 100644 --- a/src/datavis3d/data/barrenderitem_p.h +++ b/src/datavisualization/data/barrenderitem_p.h @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -20,7 +20,7 @@ // W A R N I N G // ------------- // -// This file is not part of the QtDataVis3D API. It exists purely as an +// 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. // @@ -31,14 +31,15 @@ #include "abstractrenderitem_p.h" -QT_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVISUALIZATION_BEGIN_NAMESPACE -class Bars3dRenderer; +class Bars3DRenderer; class BarRenderItem : public AbstractRenderItem { public: BarRenderItem(); + BarRenderItem(const BarRenderItem &other); virtual ~BarRenderItem(); // Position relative to data window (for bar label generation) @@ -53,32 +54,36 @@ public: inline void setHeight(GLfloat height) { m_height = height; } inline GLfloat height() const { return m_height; } - // TODO should be in abstract, but currently there is no abstract renderer - inline void setRenderer(Bars3dRenderer *renderer) { m_renderer = renderer; } + // Label item for formatted label + LabelItem &sliceLabelItem(); -protected: - virtual void formatLabel(); + // Formatted label for item. + void setSliceLabel(const QString &label); + QString &sliceLabel(); // Formats label if not previously formatted - Bars3dRenderer *m_renderer; +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) { - if (m_value != value) { - m_value = value; - if (!m_label.isNull()) - setLabel(QString()); // Forces reformatting on next access - } + 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_DATAVIS3D_END_NAMESPACE +QT_DATAVISUALIZATION_END_NAMESPACE #endif diff --git a/src/datavis3d/data/data.pri b/src/datavisualization/data/data.pri index a3b28e6e..770d2bd1 100644 --- a/src/datavis3d/data/data.pri +++ b/src/datavisualization/data/data.pri @@ -12,24 +12,31 @@ HEADERS += \ $$PWD/qitemmodelbardatamapping_p.h \ $$PWD/qitemmodelbardataproxy_p.h \ $$PWD/qitemmodelbardataproxy.h \ - $$PWD/maprenderitem_p.h \ - $$PWD/qmapdataitem.h \ - $$PWD/qmapdataitem_p.h \ - $$PWD/qmapdataproxy.h \ - $$PWD/qmapdataproxy_p.h \ $$PWD/scatterrenderitem_p.h \ $$PWD/qscatterdataitem.h \ $$PWD/qscatterdataitem_p.h \ $$PWD/qscatterdataproxy.h \ $$PWD/qscatterdataproxy_p.h \ - $$PWD/qitemmodelmapdatamapping.h \ - $$PWD/qitemmodelmapdatamapping_p.h \ - $$PWD/qitemmodelmapdataproxy.h \ - $$PWD/qitemmodelmapdataproxy_p.h \ $$PWD/qitemmodelscatterdatamapping.h \ $$PWD/qitemmodelscatterdatamapping_p.h \ $$PWD/qitemmodelscatterdataproxy.h \ - $$PWD/qitemmodelscatterdataproxy_p.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 \ @@ -40,13 +47,18 @@ SOURCES += \ $$PWD/qbardataitem.cpp \ $$PWD/qitemmodelbardatamapping.cpp \ $$PWD/qitemmodelbardataproxy.cpp \ - $$PWD/maprenderitem.cpp \ - $$PWD/qmapdataitem.cpp \ - $$PWD/qmapdataproxy.cpp \ $$PWD/scatterrenderitem.cpp \ $$PWD/qscatterdataitem.cpp \ $$PWD/qscatterdataproxy.cpp \ - $$PWD/qitemmodelmapdatamapping.cpp \ - $$PWD/qitemmodelmapdataproxy.cpp \ $$PWD/qitemmodelscatterdatamapping.cpp \ - $$PWD/qitemmodelscatterdataproxy.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/datavis3d/data/labelitem.cpp b/src/datavisualization/data/labelitem.cpp index 1d1bf6f7..5e27a50e 100644 --- a/src/datavis3d/data/labelitem.cpp +++ b/src/datavisualization/data/labelitem.cpp @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -18,7 +18,7 @@ #include "labelitem_p.h" -QT_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVISUALIZATION_BEGIN_NAMESPACE LabelItem::LabelItem() : m_size(QSize(0, 0)), @@ -61,4 +61,4 @@ void LabelItem::clear() m_size = QSize(0, 0); } -QT_DATAVIS3D_END_NAMESPACE +QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavis3d/data/labelitem_p.h b/src/datavisualization/data/labelitem_p.h index 84625002..c10c1f12 100644 --- a/src/datavis3d/data/labelitem_p.h +++ b/src/datavisualization/data/labelitem_p.h @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -20,7 +20,7 @@ // W A R N I N G // ------------- // -// This file is not part of the QtDataVis3D API. It exists purely as an +// 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. // @@ -29,11 +29,11 @@ #ifndef LABELITEM_P_H #define LABELITEM_P_H -#include "datavis3dglobal_p.h" +#include "datavisualizationglobal_p.h" #include <QOpenGLFunctions> #include <QSize> -QT_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVISUALIZATION_BEGIN_NAMESPACE class LabelItem { @@ -54,6 +54,6 @@ private: GLuint m_textureId; }; -QT_DATAVIS3D_END_NAMESPACE +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/datavis3d/data/qabstractdataproxy.h b/src/datavisualization/data/qabstractdataproxy.h index 0e717dbb..db0e0863 100644 --- a/src/datavis3d/data/qabstractdataproxy.h +++ b/src/datavisualization/data/qabstractdataproxy.h @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -19,38 +19,37 @@ #ifndef QABSTRACTDATAPROXY_H #define QABSTRACTDATAPROXY_H -#include <QtDataVis3D/qdatavis3denums.h> +#include <QtDataVisualization/qdatavisualizationenums.h> #include <QObject> #include <QScopedPointer> -QT_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVISUALIZATION_BEGIN_NAMESPACE class QAbstractDataProxyPrivate; -class QT_DATAVIS3D_EXPORT QAbstractDataProxy : public QObject +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, - DataTypeMap = 2, - DataTypeScatter = 4, - DataTypeSurface = 8 + DataTypeScatter = 2, + DataTypeSurface = 4 }; protected: - explicit QAbstractDataProxy(QAbstractDataProxyPrivate *d); + explicit QAbstractDataProxy(QAbstractDataProxyPrivate *d, QObject *parent = 0); + public: virtual ~QAbstractDataProxy(); DataType type() const; - // Items use this string to format single item labels, unless custom proxy initializes - // item labels with something else. void setItemLabelFormat(const QString &format); QString itemLabelFormat() const; @@ -62,8 +61,13 @@ protected: private: Q_DISABLE_COPY(QAbstractDataProxy) + + friend class Abstract3DController; + friend class Bars3DController; + friend class Scatter3DController; + friend class Surface3DController; }; -QT_DATAVIS3D_END_NAMESPACE +QT_DATAVISUALIZATION_END_NAMESPACE #endif // QABSTRACTDATAPROXY_H diff --git a/src/datavis3d/data/qabstractdataproxy_p.h b/src/datavisualization/data/qabstractdataproxy_p.h index eda13b86..4aa1b678 100644 --- a/src/datavis3d/data/qabstractdataproxy_p.h +++ b/src/datavisualization/data/qabstractdataproxy_p.h @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -20,20 +20,20 @@ // W A R N I N G // ------------- // -// This file is not part of the QtDataVis3D API. It exists purely as an +// 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 "datavis3dglobal_p.h" +#include "datavisualizationglobal_p.h" #include "qabstractdataproxy.h" #include <QString> #ifndef QABSTRACTDATAPROXY_P_H #define QABSTRACTDATAPROXY_P_H -QT_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVISUALIZATION_BEGIN_NAMESPACE class QAbstractDataProxyPrivate : public QObject { @@ -44,15 +44,19 @@ public: 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_DATAVIS3D_END_NAMESPACE +QT_DATAVISUALIZATION_END_NAMESPACE #endif // QABSTRACTDATAPROXY_P_H diff --git a/src/datavis3d/data/qbardataitem.cpp b/src/datavisualization/data/qbardataitem.cpp index 1e8f3d95..2803c01a 100644 --- a/src/datavis3d/data/qbardataitem.cpp +++ b/src/datavisualization/data/qbardataitem.cpp @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -18,18 +18,18 @@ #include "qbardataitem_p.h" -QT_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVISUALIZATION_BEGIN_NAMESPACE /*! * \class QBarDataItem - * \inmodule QtDataVis3D + * \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 3D C++ Classes} + * \sa QBarDataProxy, {Qt Data Visualization C++ Classes} */ /*! @@ -41,12 +41,18 @@ QBarDataItem::QBarDataItem() { } +/*! + * 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); @@ -60,6 +66,9 @@ 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; @@ -71,23 +80,25 @@ QBarDataItem &QBarDataItem::operator=(const QBarDataItem &other) return *this; } -void QBarDataItem::setValue(qreal value) -{ - m_value = value; -} +/*! + * \fn void QBarDataItem::setValue(qreal value) + * Sets \a value to this data item. + */ -qreal QBarDataItem::value() const -{ - return m_value; -} +/*! + * \fn qreal QBarDataItem::value() const + * \return value of this data item. + */ +/*! + * \internal + */ void QBarDataItem::createExtraData() { if (!d_ptr) d_ptr = new QBarDataItemPrivate; } - QBarDataItemPrivate::QBarDataItemPrivate() { } @@ -96,4 +107,4 @@ QBarDataItemPrivate::~QBarDataItemPrivate() { } -QT_DATAVIS3D_END_NAMESPACE +QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavis3d/data/qbardataitem.h b/src/datavisualization/data/qbardataitem.h index d7062b66..68bbcedf 100644 --- a/src/datavis3d/data/qbardataitem.h +++ b/src/datavisualization/data/qbardataitem.h @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -19,13 +19,13 @@ #ifndef QBARDATAITEM_H #define QBARDATAITEM_H -#include <QtDataVis3D/qdatavis3denums.h> +#include <QtDataVisualization/qdatavisualizationenums.h> -QT_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVISUALIZATION_BEGIN_NAMESPACE class QBarDataItemPrivate; -class QT_DATAVIS3D_EXPORT QBarDataItem +class QT_DATAVISUALIZATION_EXPORT QBarDataItem { public: QBarDataItem(); @@ -35,8 +35,8 @@ public: QBarDataItem &operator=(const QBarDataItem &other); - void setValue(qreal value); - qreal value() const; + void setValue(qreal value) { m_value = value; } + qreal value() const { return m_value; } // TODO Set color, label format, ...? @@ -49,6 +49,6 @@ private: qreal m_value; }; -QT_DATAVIS3D_END_NAMESPACE +QT_DATAVISUALIZATION_END_NAMESPACE #endif diff --git a/src/datavis3d/data/qbardataitem_p.h b/src/datavisualization/data/qbardataitem_p.h index e63ce787..20b7ea69 100644 --- a/src/datavis3d/data/qbardataitem_p.h +++ b/src/datavisualization/data/qbardataitem_p.h @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -20,7 +20,7 @@ // W A R N I N G // ------------- // -// This file is not part of the QtDataVis3D API. It exists purely as an +// 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. // @@ -29,10 +29,10 @@ #ifndef QBARDATAITEM_P_H #define QBARDATAITEM_P_H -#include "datavis3dglobal_p.h" +#include "datavisualizationglobal_p.h" #include "qbardataitem.h" -QT_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVISUALIZATION_BEGIN_NAMESPACE class QBarDataItemPrivate { @@ -46,6 +46,6 @@ protected: friend class QBarDataItem; }; -QT_DATAVIS3D_END_NAMESPACE +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/datavis3d/data/qbardataproxy.h b/src/datavisualization/data/qbardataproxy.h index e28f8ff0..758700df 100644 --- a/src/datavis3d/data/qbardataproxy.h +++ b/src/datavisualization/data/qbardataproxy.h @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -19,85 +19,89 @@ #ifndef QBARDATAPROXY_H #define QBARDATAPROXY_H -#include <QtDataVis3D/qabstractdataproxy.h> -#include <QtDataVis3D/qbardataitem.h> +#include <QtDataVisualization/qabstractdataproxy.h> +#include <QtDataVisualization/qbardataitem.h> #include <QVector> +#include <QStringList> -QT_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVISUALIZATION_BEGIN_NAMESPACE typedef QVector<QBarDataItem> QBarDataRow; typedef QList<QBarDataRow *> QBarDataArray; class QBarDataProxyPrivate; -class QT_DATAVIS3D_EXPORT QBarDataProxy : public QAbstractDataProxy +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(); - explicit QBarDataProxy(QBarDataProxyPrivate *d); + explicit QBarDataProxy(QObject *parent = 0); virtual ~QBarDataProxy(); - // BarDataProxy 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. + // 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. + */ - // Row and item pointers are guaranteed to be valid only until next call that modifies data. - // Array pointer is guaranteed to be valid for lifetime of proxy. 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; - // 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. - // QBarDataRow pointers should not be used to modify data further after they have been passed to - // the proxy, as such modifications will not trigger proper signals. - - // Clears the existing array and takes ownership of the new array. - // Passing null array clears all data. + void resetArray(); void resetArray(QBarDataArray *newArray); + void resetArray(QBarDataArray *newArray, const QStringList &rowLabels, + const QStringList &columnLabels); - // Change existing rows 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); - // Change single item 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); // returns the index of added row - int addRows(const QBarDataArray &rows); // returns the index of first added row + 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 - // If rowIndex is equal to array size, rows are added to end of the array. 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); - // Attempting to remove rows past the end of the array does nothing. - void removeRows(int rowIndex, int removeCount); + 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); - // Index is the current array size if rows were removed from the end of the array void rowsRemoved(int startIndex, int count); void rowsInserted(int startIndex, int count); // TODO void columnsChanged(int startIndex, int count); @@ -107,16 +111,20 @@ signals: 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; + friend class Bars3DController; }; -QT_DATAVIS3D_END_NAMESPACE +QT_DATAVISUALIZATION_END_NAMESPACE #endif // QBARDATAPROXY_H diff --git a/src/datavis3d/data/qbardataproxy_p.h b/src/datavisualization/data/qbardataproxy_p.h index fa6ccd0d..4d51bd5b 100644 --- a/src/datavis3d/data/qbardataproxy_p.h +++ b/src/datavisualization/data/qbardataproxy_p.h @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -20,7 +20,7 @@ // W A R N I N G // ------------- // -// This file is not part of the QtDataVis3D API. It exists purely as an +// 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. // @@ -33,7 +33,7 @@ #include "qabstractdataproxy_p.h" #include "qbardataitem.h" -QT_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVISUALIZATION_BEGIN_NAMESPACE class QBarDataProxyPrivate : public QAbstractDataProxyPrivate { @@ -42,28 +42,34 @@ public: QBarDataProxyPrivate(QBarDataProxy *q); virtual ~QBarDataProxyPrivate(); - bool resetArray(QBarDataArray *newArray); - void setRow(int rowIndex, QBarDataRow *row); - void setRows(int rowIndex, const QBarDataArray &rows); + 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); - int addRows(const QBarDataArray &rows); - void insertRow(int rowIndex, QBarDataRow *row); - void insertRows(int rowIndex, const QBarDataArray &rows); - void removeRows(int rowIndex, int removeCount); + 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); + 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_DATAVIS3D_END_NAMESPACE +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/datavis3d/data/qitemmodelbardatamapping.h b/src/datavisualization/data/qitemmodelbardatamapping.h index d9f74152..a5ef33b8 100644 --- a/src/datavis3d/data/qitemmodelbardatamapping.h +++ b/src/datavisualization/data/qitemmodelbardatamapping.h @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -19,14 +19,15 @@ #ifndef QITEMMODELBARDATAMAPPING_H #define QITEMMODELBARDATAMAPPING_H -#include <QtDataVis3D/qdatavis3denums.h> +#include <QtDataVisualization/qdatavisualizationenums.h> +#include <QtDataVisualization/qabstractdatamapping.h> #include <QStringList> -QT_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVISUALIZATION_BEGIN_NAMESPACE class QItemModelBarDataMappingPrivate; -class QT_DATAVIS3D_EXPORT QItemModelBarDataMapping : public QObject +class QT_DATAVISUALIZATION_EXPORT QItemModelBarDataMapping : public QAbstractDataMapping { Q_OBJECT Q_PROPERTY(QString rowRole READ rowRole WRITE setRowRole) @@ -34,21 +35,20 @@ class QT_DATAVIS3D_EXPORT QItemModelBarDataMapping : public QObject 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(); - QItemModelBarDataMapping(const QItemModelBarDataMapping &other); - QItemModelBarDataMapping(const QString &valueRole); + 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); + const QStringList &columnCategories, QObject *parent = 0); virtual ~QItemModelBarDataMapping(); - QItemModelBarDataMapping &operator=(const QItemModelBarDataMapping &other); - - // If row categories or column categories is an empty list, use item models's rows and columns for rows and columns. - // If the categories are both defined, ignore item model's rows and columns and figure out the rows and columns from - // the values of the set roles for each item. - void setRowRole(const QString &role); QString rowRole() const; void setColumnRole(const QString &role); @@ -57,21 +57,34 @@ public: QString valueRole() const; void setRowCategories(const QStringList &categories); - const QStringList &rowCategories() const; + QStringList rowCategories() const; void setColumnCategories(const QStringList &categories); - const QStringList &columnCategories() const; + 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); -signals: - void mappingChanged(); + + Q_INVOKABLE int rowCategoryIndex(const QString& category); + Q_INVOKABLE int columnCategoryIndex(const QString& category); + +protected: + QItemModelBarDataMappingPrivate *dptr(); + const QItemModelBarDataMappingPrivate *dptrc() const; private: - QScopedPointer<QItemModelBarDataMappingPrivate> d_ptr; -}; + Q_DISABLE_COPY(QItemModelBarDataMapping) + friend class BarItemModelHandler; +}; -QT_DATAVIS3D_END_NAMESPACE +QT_DATAVISUALIZATION_END_NAMESPACE #endif diff --git a/src/datavis3d/data/qitemmodelbardatamapping_p.h b/src/datavisualization/data/qitemmodelbardatamapping_p.h index fa1728e0..90a17fdb 100644 --- a/src/datavis3d/data/qitemmodelbardatamapping_p.h +++ b/src/datavisualization/data/qitemmodelbardatamapping_p.h @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -20,20 +20,21 @@ // W A R N I N G // ------------- // -// This file is not part of the QtDataVis3D API. It exists purely as an +// 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_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVISUALIZATION_BEGIN_NAMESPACE -class QItemModelBarDataMappingPrivate : public QObject +class QItemModelBarDataMappingPrivate : public QAbstractDataMappingPrivate { Q_OBJECT public: @@ -49,11 +50,14 @@ private: QStringList m_rowCategories; QStringList m_columnCategories; - QItemModelBarDataMapping *q_ptr; + bool m_useModelCategories; + bool m_autoRowCategories; + bool m_autoColumnCategories; friend class QItemModelBarDataMapping; + friend class BarItemModelHandler; }; -QT_DATAVIS3D_END_NAMESPACE +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/datavis3d/data/qmapdataproxy_p.h b/src/datavisualization/data/qitemmodelbardataproxy_p.h index bf3d1d2c..fc646f0d 100644 --- a/src/datavis3d/data/qmapdataproxy_p.h +++ b/src/datavisualization/data/qitemmodelbardataproxy_p.h @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -20,39 +20,39 @@ // W A R N I N G // ------------- // -// This file is not part of the QtDataVis3D API. It exists purely as an +// 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 QMAPDATAPROXY_P_H -#define QMAPDATAPROXY_P_H +#ifndef QITEMMODELBARDATAPROXY_P_H +#define QITEMMODELBARDATAPROXY_P_H -#include "qmapdataproxy.h" -#include "qabstractdataproxy_p.h" -#include "qmapdataitem.h" +#include "qitemmodelbardataproxy.h" +#include "qbardataproxy_p.h" +#include <QPointer> +#include <QTimer> -QT_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVISUALIZATION_BEGIN_NAMESPACE -class QMapDataProxyPrivate : public QAbstractDataProxyPrivate +class BarItemModelHandler; + +class QItemModelBarDataProxyPrivate : public QBarDataProxyPrivate { Q_OBJECT public: - QMapDataProxyPrivate(QMapDataProxy *q); - virtual ~QMapDataProxyPrivate(); - - bool resetArray(QMapDataArray *newArray); - - QPair<GLfloat, GLfloat> limitValues(); + QItemModelBarDataProxyPrivate(QItemModelBarDataProxy *q); + virtual ~QItemModelBarDataProxyPrivate(); private: - QMapDataArray m_dataArray; + QItemModelBarDataProxy *qptr(); -private: - friend class QMapDataProxy; + BarItemModelHandler *m_itemModelHandler; + + friend class QItemModelBarDataProxy; }; -QT_DATAVIS3D_END_NAMESPACE +QT_DATAVISUALIZATION_END_NAMESPACE -#endif // QBARDATAPROXY_P_H +#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/datavis3d/data/qitemmodelscatterdatamapping.h b/src/datavisualization/data/qitemmodelscatterdatamapping.h index f4a2cfe6..62f2fefc 100644 --- a/src/datavis3d/data/qitemmodelscatterdatamapping.h +++ b/src/datavisualization/data/qitemmodelscatterdatamapping.h @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -19,52 +19,44 @@ #ifndef QITEMMODELSCATTERDATAMAPPING_H #define QITEMMODELSCATTERDATAMAPPING_H -#include <QtDataVis3D/qdatavis3denums.h> +#include <QtDataVisualization/qdatavisualizationenums.h> +#include <QtDataVisualization/qabstractdatamapping.h> #include <QObject> -QT_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVISUALIZATION_BEGIN_NAMESPACE class QItemModelScatterDataMappingPrivate; -class QT_DATAVIS3D_EXPORT QItemModelScatterDataMapping : public QObject +class QT_DATAVISUALIZATION_EXPORT QItemModelScatterDataMapping : public QAbstractDataMapping { Q_OBJECT - //Q_PROPERTY(QString labelRole READ labelRole WRITE setLabelRole) Q_PROPERTY(QString xPosRole READ xPosRole WRITE setXPosRole) Q_PROPERTY(QString yPosRole READ yPosRole WRITE setYPosRole) Q_PROPERTY(QString zPosRole READ zPosRole WRITE setZPosRole) - //Q_PROPERTY(QString valueRole READ valueRole WRITE setValueRole) + public: - explicit QItemModelScatterDataMapping(); - QItemModelScatterDataMapping(const QItemModelScatterDataMapping &other); - QItemModelScatterDataMapping(const QString &labelRole, const QString &xPosRole, - const QString &yPosRole, const QString &zPosRole, - const QString &valueRole); + explicit QItemModelScatterDataMapping(QObject *parent = 0); + QItemModelScatterDataMapping(const QString &xPosRole, const QString &yPosRole, + const QString &zPosRole, QObject *parent = 0); virtual ~QItemModelScatterDataMapping(); - QItemModelScatterDataMapping &operator=(const QItemModelScatterDataMapping &other); - - //void setLabelRole(const QString &role); - //QString labelRole() const; 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 setValueRole(const QString &role); - //QString valueRole() const; - void remap(const QString &labelRole, const QString &xPosRole, - const QString &yPosRole, const QString &zPosRole, const QString &valueRole); -signals: - void mappingChanged(); + void remap(const QString &xPosRole, const QString &yPosRole, const QString &zPosRole); + +protected: + QItemModelScatterDataMappingPrivate *dptr(); + const QItemModelScatterDataMappingPrivate *dptrc() const; private: - QScopedPointer<QItemModelScatterDataMappingPrivate> d_ptr; + Q_DISABLE_COPY(QItemModelScatterDataMapping) }; - -QT_DATAVIS3D_END_NAMESPACE +QT_DATAVISUALIZATION_END_NAMESPACE #endif diff --git a/src/datavis3d/data/qitemmodelscatterdatamapping_p.h b/src/datavisualization/data/qitemmodelscatterdatamapping_p.h index 90a826c0..62ff42b4 100644 --- a/src/datavis3d/data/qitemmodelscatterdatamapping_p.h +++ b/src/datavisualization/data/qitemmodelscatterdatamapping_p.h @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -20,20 +20,21 @@ // W A R N I N G // ------------- // -// This file is not part of the QtDataVis3D API. It exists purely as an +// 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 "qitemmodelscatterdatamapping.h" - #ifndef QITEMMODELSCATTERDATAMAPPING_P_H #define QITEMMODELSCATTERDATAMAPPING_P_H -QT_DATAVIS3D_BEGIN_NAMESPACE +#include "qitemmodelscatterdatamapping.h" +#include "qabstractdatamapping_p.h" -class QItemModelScatterDataMappingPrivate : public QObject +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +class QItemModelScatterDataMappingPrivate : public QAbstractDataMappingPrivate { Q_OBJECT public: @@ -47,11 +48,9 @@ private: QString m_zPosRole; //QString m_valueRole; - QItemModelScatterDataMapping *q_ptr; - friend class QItemModelScatterDataMapping; }; -QT_DATAVIS3D_END_NAMESPACE +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/datavis3d/data/qitemmodelscatterdataproxy.h b/src/datavisualization/data/qitemmodelscatterdataproxy.h index f609e84b..891950c1 100644 --- a/src/datavis3d/data/qitemmodelscatterdataproxy.h +++ b/src/datavisualization/data/qitemmodelscatterdataproxy.h @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -19,42 +19,44 @@ #ifndef QITEMMODELSCATTERDATAPROXY_H #define QITEMMODELSCATTERDATAPROXY_H -#include <QtDataVis3D/qscatterdataproxy.h> -#include <QtDataVis3D/qitemmodelscatterdatamapping.h> +#include <QtDataVisualization/qscatterdataproxy.h> +#include <QtDataVisualization/qitemmodelscatterdatamapping.h> #include <QAbstractItemModel> #include <QStringList> -QT_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVISUALIZATION_BEGIN_NAMESPACE class QItemModelScatterDataProxyPrivate; -class QT_DATAVIS3D_EXPORT QItemModelScatterDataProxy : public QScatterDataProxy +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(QAbstractItemModel *itemModel, + explicit QItemModelScatterDataProxy(const QAbstractItemModel *itemModel, QItemModelScatterDataMapping *mapping); virtual ~QItemModelScatterDataProxy(); - // Doesn't gain ownership of the model, but does connect to it to listen for data changes. - void setItemModel(QAbstractItemModel *itemModel); - QAbstractItemModel *itemModel(); + void setItemModel(const QAbstractItemModel *itemModel); + const QAbstractItemModel *itemModel() const; - // Map scatter role (xPos, yPos, zPos) to role in model - // Doesn't gain ownership of mapping, but does connect to it to listen for mapping changes. - // Modifying mapping that is set to proxy will trigger dataset re-resolving. - void setMapping(QItemModelScatterDataMapping *mapping); - QItemModelScatterDataMapping *mapping(); + 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_DATAVIS3D_END_NAMESPACE +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/datavis3d/data/qscatterdataitem.cpp b/src/datavisualization/data/qscatterdataitem.cpp index e2580339..055a9dad 100644 --- a/src/datavis3d/data/qscatterdataitem.cpp +++ b/src/datavisualization/data/qscatterdataitem.cpp @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -18,11 +18,11 @@ #include "qscatterdataitem_p.h" -QT_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVISUALIZATION_BEGIN_NAMESPACE /*! * \class QScatterDataItem - * \inmodule QtDataVis3D + * \inmodule QtDataVisualization * \brief The QScatterDataItem class provides a container for resolved data to be added to scatter * graphs. * \since 1.0.0 @@ -30,7 +30,7 @@ QT_DATAVIS3D_BEGIN_NAMESPACE * 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 3D C++ Classes} + * \sa QScatterDataProxy, {Qt Data Visualization C++ Classes} */ /*! @@ -42,12 +42,18 @@ QScatterDataItem::QScatterDataItem() { } +/*! + * 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); @@ -60,6 +66,9 @@ QScatterDataItem::~QScatterDataItem() { } +/*! + * Assigns a copy of \a other to this object. + */ QScatterDataItem &QScatterDataItem::operator=(const QScatterDataItem &other) { m_position = other.m_position; @@ -74,15 +83,45 @@ QScatterDataItem &QScatterDataItem::operator=(const QScatterDataItem &other) return *this; } -void QScatterDataItem::setPosition(const QVector3D &position) -{ - m_position = position; -} +/*! + * \fn void QScatterDataItem::setPosition(const QVector3D &position) + * Sets \a position to this data item. + */ -const QVector3D &QScatterDataItem::position() const -{ - return m_position; -} +/*! + * \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) //{ @@ -94,6 +133,9 @@ const QVector3D &QScatterDataItem::position() const // return m_size; //} +/*! + * \internal + */ void QScatterDataItem::createExtraData() { if (!d_ptr) @@ -108,4 +150,4 @@ QScatterDataItemPrivate::~QScatterDataItemPrivate() { } -QT_DATAVIS3D_END_NAMESPACE +QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavis3d/data/qscatterdataitem.h b/src/datavisualization/data/qscatterdataitem.h index 82383ae6..29154259 100644 --- a/src/datavis3d/data/qscatterdataitem.h +++ b/src/datavisualization/data/qscatterdataitem.h @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -19,14 +19,14 @@ #ifndef QSCATTERDATAITEM_H #define QSCATTERDATAITEM_H -#include <QtDataVis3D/qdatavis3denums.h> +#include <QtDataVisualization/qdatavisualizationenums.h> #include <QVector3D> -QT_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVISUALIZATION_BEGIN_NAMESPACE class QScatterDataItemPrivate; -class QT_DATAVIS3D_EXPORT QScatterDataItem +class QT_DATAVISUALIZATION_EXPORT QScatterDataItem { public: QScatterDataItem(); @@ -36,8 +36,14 @@ public: QScatterDataItem &operator=(const QScatterDataItem &other); - void setPosition(const QVector3D &position); - const QVector3D &position() const; + 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; @@ -52,6 +58,6 @@ private: //qreal m_size; }; -QT_DATAVIS3D_END_NAMESPACE +QT_DATAVISUALIZATION_END_NAMESPACE #endif diff --git a/src/datavis3d/data/qscatterdataitem_p.h b/src/datavisualization/data/qscatterdataitem_p.h index 3718a185..acc67347 100644 --- a/src/datavis3d/data/qscatterdataitem_p.h +++ b/src/datavisualization/data/qscatterdataitem_p.h @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -20,7 +20,7 @@ // W A R N I N G // ------------- // -// This file is not part of the QtDataVis3D API. It exists purely as an +// 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. // @@ -29,10 +29,10 @@ #ifndef QSCATTERDATAITEM_P_H #define QSCATTERDATAITEM_P_H -#include "datavis3dglobal_p.h" +#include "datavisualizationglobal_p.h" #include "qscatterdataitem.h" -QT_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVISUALIZATION_BEGIN_NAMESPACE class QScatterDataItemPrivate { @@ -46,6 +46,6 @@ protected: friend class QScatterDataItem; }; -QT_DATAVIS3D_END_NAMESPACE +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/datavis3d/data/qscatterdataproxy.h b/src/datavisualization/data/qscatterdataproxy.h index 9e139c00..178bc900 100644 --- a/src/datavis3d/data/qscatterdataproxy.h +++ b/src/datavisualization/data/qscatterdataproxy.h @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -19,60 +19,59 @@ #ifndef QSCATTERDATAPROXY_H #define QSCATTERDATAPROXY_H -#include <QtDataVis3D/qabstractdataproxy.h> -#include <QtDataVis3D/qscatterdataitem.h> +#include <QtDataVisualization/qabstractdataproxy.h> +#include <QtDataVisualization/qscatterdataitem.h> -QT_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVISUALIZATION_BEGIN_NAMESPACE typedef QVector<QScatterDataItem> QScatterDataArray; class QScatterDataProxyPrivate; -class QT_DATAVIS3D_EXPORT QScatterDataProxy : public QAbstractDataProxy +class QT_DATAVISUALIZATION_EXPORT QScatterDataProxy : public QAbstractDataProxy { Q_OBJECT + Q_PROPERTY(int itemCount READ itemCount) + public: - explicit QScatterDataProxy(); - explicit QScatterDataProxy(QScatterDataProxyPrivate *d); + explicit QScatterDataProxy(QObject *parent = 0); virtual ~QScatterDataProxy(); - // 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. + // 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. + */ - // Item pointers are guaranteed to be valid only until next call that modifies data. - // Array pointer is guaranteed to be valid for lifetime of proxy. int itemCount() const; const QScatterDataArray *array() const; const QScatterDataItem *itemAt(int index) const; - // Clears the existing array and takes ownership of the new array. - // Passing null array clears all data. void resetArray(QScatterDataArray *newArray); - // Change existing items void setItem(int index, const QScatterDataItem &item); void setItems(int index, const QScatterDataArray &items); - int addItem(const QScatterDataItem &item); // returns the index of added item - int addItems(const QScatterDataArray &items); // returns the index of first added item + int addItem(const QScatterDataItem &item); + int addItems(const QScatterDataArray &items); - // If index is equal to data array size, item(s) are added to the array. void insertItem(int index, const QScatterDataItem &item); void insertItems(int index, const QScatterDataArray &items); - // Attempting to remove items past the end of the array does nothing. 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); // Index may be over current array size if removed from end + 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; @@ -82,6 +81,6 @@ private: friend class Scatter3DController; }; -QT_DATAVIS3D_END_NAMESPACE +QT_DATAVISUALIZATION_END_NAMESPACE #endif diff --git a/src/datavis3d/data/qscatterdataproxy_p.h b/src/datavisualization/data/qscatterdataproxy_p.h index 526845fd..9920e3a7 100644 --- a/src/datavis3d/data/qscatterdataproxy_p.h +++ b/src/datavisualization/data/qscatterdataproxy_p.h @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -20,7 +20,7 @@ // W A R N I N G // ------------- // -// This file is not part of the QtDataVis3D API. It exists purely as an +// 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. // @@ -33,7 +33,7 @@ #include "qabstractdataproxy_p.h" #include "qscatterdataitem.h" -QT_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVISUALIZATION_BEGIN_NAMESPACE class QScatterDataProxyPrivate : public QAbstractDataProxyPrivate { @@ -42,7 +42,7 @@ public: QScatterDataProxyPrivate(QScatterDataProxy *q); virtual ~QScatterDataProxyPrivate(); - bool resetArray(QScatterDataArray *newArray); + void resetArray(QScatterDataArray *newArray); void setItem(int index, const QScatterDataItem &item); void setItems(int index, const QScatterDataArray &items); int addItem(const QScatterDataItem &item); @@ -55,11 +55,10 @@ public: private: QScatterDataArray *m_dataArray; - QString m_itemLabelFormat; friend class QScatterDataProxy; }; -QT_DATAVIS3D_END_NAMESPACE +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/datavis3d/data/qmapdataitem_p.h b/src/datavisualization/data/qsurfacedataitem_p.h index 2926e3ef..d13679a8 100644 --- a/src/datavis3d/data/qmapdataitem_p.h +++ b/src/datavisualization/data/qsurfacedataitem_p.h @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -20,33 +20,32 @@ // W A R N I N G // ------------- // -// This file is not part of the QtDataVis3D API. It exists purely as an +// 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 QMAPDATAITEM_P_H -#define QMAPDATAITEM_P_H +#ifndef QSURFACEDATAITEM_P_H +#define QSURFACEDATAITEM_P_H -#include "datavis3dglobal_p.h" -#include "qmapdataitem.h" -#include "qbardataitem_p.h" +#include "datavisualizationglobal_p.h" +#include "qsurfacedataitem.h" -QT_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVISUALIZATION_BEGIN_NAMESPACE -class QMapDataItemPrivate : public QBarDataItemPrivate +class QSurfaceDataItemPrivate { public: - QMapDataItemPrivate(); - virtual ~QMapDataItemPrivate(); + QSurfaceDataItemPrivate(); + virtual ~QSurfaceDataItemPrivate(); - // TODO stores other data for map items besides position + // TODO stores other data for surface items besides position protected: - friend class QMapDataItem; + friend class QSurfaceDataItem; }; -QT_DATAVIS3D_END_NAMESPACE +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/datavis3d/doc/src/qtdatavis3dlicense.qdoc b/src/datavisualization/data/scatterrenderitem.cpp index 610fb9b7..83c66583 100644 --- a/src/datavis3d/doc/src/qtdatavis3dlicense.qdoc +++ b/src/datavisualization/data/scatterrenderitem.cpp @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -16,16 +16,27 @@ ** ****************************************************************************/ -/*! - \page qtdatavis3dlicense.html - \title Qt Data Visualization 3D License Information - \ingroup licensing - \brief License information for Qt Data Visualization 3D +#include "scatterrenderitem_p.h" +#include "scatter3drenderer_p.h" +#include "qscatterdataproxy.h" - TODO +QT_DATAVISUALIZATION_BEGIN_NAMESPACE - \legalese - TODO - \endlegalese +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/datavis3d/data/scatterrenderitem_p.h b/src/datavisualization/data/scatterrenderitem_p.h index 47cfeed2..58e91e96 100644 --- a/src/datavis3d/data/scatterrenderitem_p.h +++ b/src/datavisualization/data/scatterrenderitem_p.h @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -20,7 +20,7 @@ // W A R N I N G // ------------- // -// This file is not part of the QtDataVis3D API. It exists purely as an +// 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. // @@ -29,40 +29,48 @@ #ifndef SCATTERRENDERITEM_P_H #define SCATTERRENDERITEM_P_H -#include "barrenderitem_p.h" +#include "abstractrenderitem_p.h" -QT_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVISUALIZATION_BEGIN_NAMESPACE class Scatter3DRenderer; -class ScatterRenderItem : public BarRenderItem +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) { m_position = pos; } + 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; } - // TODO should be in abstract, but currently there is no abstract renderer - // TODO change when maps refactored - inline void setRenderer(Scatter3DRenderer *renderer) { m_renderer = renderer; } - protected: - virtual void formatLabel(); - - Scatter3DRenderer *m_renderer; 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_DATAVIS3D_END_NAMESPACE +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 diff --git a/src/datavisualization/datavisualization.pro b/src/datavisualization/datavisualization.pro new file mode 100644 index 00000000..87857062 --- /dev/null +++ b/src/datavisualization/datavisualization.pro @@ -0,0 +1,27 @@ +TARGET = QtDataVisualization +QT = core gui + +DEFINES += QT_DATAVISUALIZATION_LIBRARY + +QMAKE_DOCS = $$PWD/doc/qtdatavisualization.qdocconf + +load(qt_module) + +include($$PWD/common.pri) +include($$PWD/engine/engine.pri) +include($$PWD/global/global.pri) +include($$PWD/utils/utils.pri) +include($$PWD/axis/axis.pri) +include($$PWD/data/data.pri) +include($$PWD/input/input.pri) + +android { + CONFIG += static +} + +OTHER_FILES += doc/qtdatavisualization.qdocconf \ + doc/src/* \ + doc/images/* \ + doc/snippets/* \ + global/*.qdoc + diff --git a/src/datavisualization/doc/images/q3dbars-minimal.png b/src/datavisualization/doc/images/q3dbars-minimal.png Binary files differnew file mode 100644 index 00000000..fff8d415 --- /dev/null +++ b/src/datavisualization/doc/images/q3dbars-minimal.png diff --git a/src/datavisualization/doc/images/q3dscatter-minimal.png b/src/datavisualization/doc/images/q3dscatter-minimal.png Binary files differnew file mode 100644 index 00000000..1c3290b3 --- /dev/null +++ b/src/datavisualization/doc/images/q3dscatter-minimal.png diff --git a/src/datavisualization/doc/images/q3dsurface-minimal.png b/src/datavisualization/doc/images/q3dsurface-minimal.png Binary files differnew file mode 100644 index 00000000..119cdfb9 --- /dev/null +++ b/src/datavisualization/doc/images/q3dsurface-minimal.png diff --git a/src/datavisualization/doc/qtdatavisualization.qdocconf b/src/datavisualization/doc/qtdatavisualization.qdocconf new file mode 100644 index 00000000..e3189604 --- /dev/null +++ b/src/datavisualization/doc/qtdatavisualization.qdocconf @@ -0,0 +1,51 @@ +include($QT_INSTALL_DOCS/global/qt-module-defaults.qdocconf) + +project = QtDataVisualization +description = Qt Data Visualization Reference Documentation +version = 1.0.0 + +exampledirs += ../../../examples \ + snippets + +headerdirs += .. +imagedirs += ../images \ + images +sourcedirs += .. + +depends += qtcore \ + qtgui + +qhp.projects = qtdatavisualization + +qhp.qtdatavisualization.file = qtdatavisualization.qhp +qhp.qtdatavisualization.namespace = org.qt-project.qtdatavisualization.1.0.0 +qhp.qtdatavisualization.virtualFolder = qtdatavisualization +qhp.qtdatavisualization.indexTitle = Qt Data Visualization +qhp.qtdatavisualization.indexRoot = + +qhp.qtdatavisualization.filterAttributes = qtdatavisualization 1.0.0 qtrefdoc +qhp.qtdatavisualization.customFilters.Qt.name = QtDataVisualization 1.0.0 +qhp.qtdatavisualization.customFilters.Qt.filterAttributes = qtdatavisualization 1.0.0 +qhp.qtdatavisualization.subprojects = classes +qhp.qtdatavisualization.subprojects.classes.title = C++ Classes +qhp.qtdatavisualization.subprojects.classes.indexTitle = Qt Data Visualization C++ Classes +qhp.qtdatavisualization.subprojects.classes.selectors = class fake:headerfile +qhp.qtdatavisualization.subprojects.classes.sortPages = true + + +HTML.footer = \ + "<div class=\"footer\">\n" \ + " <p>\n" \ + " <acronym title=\"Copyright\">©</acronym> 2013 Digia. Qt and Qt logos are\n" \ + " trademarks of of Digia Corporation in Finland and/or other countries worldwide.\n" \ + " </p>\n" \ + " All other trademarks are property of their respective owners.\n" \ + " <br />\n" \ + " <p>\n" \ + " Licensees holding valid Qt Enterprise licenses may use this document in accordance\n" \ + " with the Qt Enterprise License Agreement provided with the Software or,\n" \ + " alternatively, in accordance with the terms contained in a written agreement\n" \ + " between you and Digia.\n" \ + " </p>\n" \ + "</div>\n" + diff --git a/src/datavis3d/doc/src/qtdatavis3d.qdoc b/src/datavisualization/doc/snippets/doc_src_q3dbars_construction.cpp index c27fe0a3..a5615601 100644 --- a/src/datavis3d/doc/src/qtdatavis3d.qdoc +++ b/src/datavisualization/doc/snippets/doc_src_q3dbars_construction.cpp @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -16,11 +16,31 @@ ** ****************************************************************************/ -/*! - \module QtDataVis3D - \title Qt Data Visualization 3D C++ Classes - \ingroup modules +//! [3] +#include <QtDataVisualization> - \brief The QtDataVis3D module provides functionality for 3D visualization. -*/ +using namespace QtDataVisualization; +int main(int argc, char **argv) +{ + QGuiApplication app(argc, argv); + + //! [4] + Q3DBars *bars = new Q3DBars(); + //! [4] + //! [0] + bars->rowAxis()->setRange(0, 4); + bars->columnAxis()->setRange(0, 4); + //! [0] + //! [1] + QBarDataRow data; + data << 1.0 << 3.0 << 7.5 << 5.0 << 2.2; + bars->activeDataProxy()->addRow(&data); + //! [1] + //! [2] + bars->show(); + //! [2] + + return app.exec(); +} +//! [3] diff --git a/src/datavis3d/doc/snippets/doc_src_q3dbars_construction.cpp b/src/datavisualization/doc/snippets/doc_src_q3dscatter_construction.cpp index 09979d8c..b2f48921 100644 --- a/src/datavis3d/doc/snippets/doc_src_q3dbars_construction.cpp +++ b/src/datavisualization/doc/snippets/doc_src_q3dscatter_construction.cpp @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -17,23 +17,24 @@ ****************************************************************************/ //! [3] -#include <QtDataVis3D> +#include <QtDataVisualization> + +using namespace QtDataVisualization; int main(int argc, char **argv) { QGuiApplication app(argc, argv); //! [0] - Q3DBars bars; - bars.setupSampleSpace(5, 5); + Q3DScatter *scatter = new Q3DScatter(); //! [0] //! [1] - QVector<float> data; - data << 1.0f << 3.0f << 7.5f << 5.0f << 2.2f; - bars.addDataRow(data); + QScatterDataArray data; + data << QVector3D(1.0f, 0.5f, 1.0f) << QVector3D(-1.0f, -0.5f, -1.0f) << QVector3D(0.5f, 0.0f, 0.0f); + scatter->activeDataProxy()->addItems(data); //! [1] //! [2] - bars.show(); + scatter->show(); //! [2] return app.exec(); diff --git a/src/datavis3d/doc/snippets/doc_src_qtdatavis3d.cpp b/src/datavisualization/doc/snippets/doc_src_q3dsurface_construction.cpp index a3b3e8e8..33b6cf37 100644 --- a/src/datavis3d/doc/snippets/doc_src_qtdatavis3d.cpp +++ b/src/datavisualization/doc/snippets/doc_src_q3dsurface_construction.cpp @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -16,6 +16,35 @@ ** ****************************************************************************/ -//! [0] -#include <QtDataVis3D> -//! [0] +//! [5] +#include <QtDataVisualization> + +using namespace QtDataVisualization; + +int main(int argc, char **argv) +{ + QGuiApplication app(argc, argv); + + //! [0] + Q3DSurface surface; + //! [0] + //! [1] + QSurfaceDataArray *data = new QSurfaceDataArray; + QSurfaceDataRow *dataRow = new QSurfaceDataRow; + //! [1] + + //! [2] + *dataRow << 0.1 << 1.8 << 0.4; + *data << dataRow; + //! [2] + + //! [3] + surface.activeDataProxy()->resetArray(data); + //! [3] + //! [4] + surface.show(); + //! [4] + + return app.exec(); +} +//! [5] diff --git a/src/datavisualization/doc/snippets/doc_src_qmldatavisualization.cpp b/src/datavisualization/doc/snippets/doc_src_qmldatavisualization.cpp new file mode 100644 index 00000000..f4446e17 --- /dev/null +++ b/src/datavisualization/doc/snippets/doc_src_qmldatavisualization.cpp @@ -0,0 +1,121 @@ +/**************************************************************************** +** +** 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 +** +****************************************************************************/ + +//! [0] +import com.digia.QtDataVisualization 1.0 +//! [0] + +//! [1] +Bars3D { + rows: 4 + columns: 4 + dataProxy: barProxy // an ItemModelBarDataProxy + barSpacing: Qt.size(0.5, 0.5) + barSpacingRelative: false + itemLabelFormat: "@valueTitle for @colLabel, @rowLabel: @valueLabel" +} +//! [1] + +//! [2] +Scatter3D { + dataProxy: scatterProxy // an ItemModelScatterDataProxy + itemLabelFormat: "X:@xLabel Y:@yLabel Z:@zLabel" + axisX.segmentCount: 2 + axisX.subSegmentCount: 2 + axisX.labelFormat: "%.2f" + axisZ.segmentCount: 2 + axisZ.subSegmentCount: 2 + axisZ.labelFormat: "%.2f" + axisY.segmentCount: 3 + axisY.subSegmentCount: 2 + axisY.labelFormat: "%.2f" +} +//! [2] + +//! [3] +Surface3D { + dataProxy: surfaceProxy // an ItemModelSurfaceDataProxy + axisX.min: 0.0 + axisX.max: 10.0 + axisZ.min: 0.0 + axisZ.max: 10.0 + axisY.min: 0.0 + axisY.max: 5.0 + axisX.segmentCount: 5 + axisX.subSegmentCount: 2 + axisX.labelFormat: "%i" + axisZ.segmentCount: 5 + axisZ.subSegmentCount: 2 + axisZ.labelFormat: "%i" + axisY.segmentCount: 5 + axisY.labelFormat: "%.1f" +} +//! [3] + +//! [4] +BarDataMapping { + id: barMapping + rowRole: "year" + columnRole: "city" + valueRole: "expenses" + rowCategories: ["2010", "2011", "2012", "2013"] + columnCategories: ["Oulu", "Rauma", "Helsinki", "Tampere"] +} +//! [4] + +//! [5] +ScatterDataMapping { + id: scatterMapping + xPosRole: "xPos" + yPosRole: "yPos" + zPosRole: "zPos" +} +//! [5] + +//! [6] +SurfaceDataMapping { + id: surfaceMapping + rowRole: "latitude" + columnRole: "longitude" + valueRole: "population" +} +//! [6] + +//! [7] +ItemModelBarDataProxy { + id: barProxy + activeMapping: barMapping // a BarDataMapping + itemModel: dataModel // a ListModel +} +//! [7] + +//! [8] +ItemModelScatterDataProxy { + id: scatterProxy + activeMapping: scatterMapping // a ScatterDataMapping + itemModel: dataModel // a ListModel +} +//! [8] + +//! [9] +ItemModelSurfaceDataProxy { + id: surfaceProxy + activeMapping: surfaceMapping // a SurfaceDataMapping + itemModel: dataModel // a ListModel +} +//! [9] diff --git a/src/datavisualization/doc/snippets/doc_src_qtdatavisualization.cpp b/src/datavisualization/doc/snippets/doc_src_qtdatavisualization.cpp new file mode 100644 index 00000000..2f3d6a98 --- /dev/null +++ b/src/datavisualization/doc/snippets/doc_src_qtdatavisualization.cpp @@ -0,0 +1,118 @@ +/**************************************************************************** +** +** 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 +** +****************************************************************************/ + +//! [0] +#include <QtDataVisualization> + +using namespace QtDataVisualization; +//! [0] + +//! [1] +proxy->setItemLabelFormat(QStringLiteral("@valueTitle for (@rowLabel, @colLabel): %.1f")); +//! [1] + +//! [2] +proxy->setItemLabelFormat(QStringLiteral("@xTitle: @xValue, @yTitle: @yValue, @zTitle: @zValue")); +//! [2] + +//! [3] +// By defining row and column categories, you tell the mapping which row and column each item +// belongs to. The categories must match the data stored in the model in the roles you define +// for row and column mapping. In this example we expect "year" role to return four digit year +// and "month" to return three letter designation for the month. +// +// An example of an item in model would be: +// Requested role -> Returned data +// "year" -> "2006" // Matches the first row category, so this item is added to the first row. +// "month" -> "jan" // Matches the first column category, so this item is added as first item in the row. +// "income" -> "12.1" +// "expenses" -> "9.2" +QStringList years; +QStringList months; +years << "2006" << "2007" << "2008" << "2009" << "2010" << "2011" << "2012"; +months << "jan" << "feb" << "mar" << "apr" << "may" << "jun" << "jul" << "aug" << "sep" << "oct" << "nov" << "dec"; + +QItemModelBarDataMapping *mapping = new QItemModelBarDataMapping(QStringLiteral("year"), // Row role + QStringLiteral("month"), // Column role + QStringLiteral("income"), // Value role + years, // Row categories + months); // Column categories + +QItemModelBarDataProxy *proxy = new QItemModelBarDataProxy(customModel, mapping); + +//... + +// To display different data later, you can simply change the mapping of the current +// mapping object, or set another mapping object. +proxy->activeMapping()->setValueRole(QStringLiteral("expenses")); +//! [3] + +//! [4] +// Map "density" value to X-axis, "hardness" to Y-axis and "conductivity" to Z-axis. +QItemModelScatterDataMapping *mapping = new QItemModelScatterDataMapping(QStringLiteral("density"), + QStringLiteral("hardness"), + QStringLiteral("conductivity")) + +QItemModelScatterDataProxy *proxy = new QItemModelScatterDataProxy(customModel, mapping); +//! [4] + +//! [5] +QItemModelSurfaceDataMapping *mapping = new QItemModelSurfaceDataMapping(QStringLiteral("longitude"), // Row role + QStringLiteral("latitude"), // Column role + QStringLiteral("height")); // value role + +QItemModelSurfaceDataProxy *proxy = new QItemModelSurfaceDataProxy(customModel, mapping); +//! [5] + +//! [6] +qmake +make +//! [6] + +//! [7] +qmake CONFIG+=static +make +//! [7] + +//! [8] +qmake +make +./qmlsurface +//! [8] + +//! [9] +Q3DBars *graph = new Q3DBars(); +QWidget *container = QWidget::createWindowContainer(graph); +//! [9] + +//! [10] +Q3DBars graph; +QBarDataProxy *newProxy = new QBarDataProxy; + +QBarDataArray *dataArray = new QBarDataArray; +dataArray->reserve(10); +for (int i = 0; i < 10; i++) { + QBarDataRow *dataRow = new QBarDataRow(5); + for (int j = 0; j < 5; j++) + (*dataRow)[j].setValue(myData->getValue(i, j)); + dataArray->append(dataRow); +} + +newProxy->resetArray(dataArray); +graph->setActiveDataProxy(newProxy); +//! [10] diff --git a/src/datavis3d/doc/snippets/doc_src_qtdatavis3d.pro b/src/datavisualization/doc/snippets/doc_src_qtdatavisualization.pro index ba0f320b..81555f88 100644 --- a/src/datavis3d/doc/snippets/doc_src_qtdatavis3d.pro +++ b/src/datavisualization/doc/snippets/doc_src_qtdatavisualization.pro @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -17,5 +17,5 @@ ****************************************************************************/ #! [0] -QT += datavis3d +QT += datavisualization #! [0] diff --git a/src/datavisualization/doc/src/qtdatavisualization-index.qdoc b/src/datavisualization/doc/src/qtdatavisualization-index.qdoc new file mode 100644 index 00000000..f2245c12 --- /dev/null +++ b/src/datavisualization/doc/src/qtdatavisualization-index.qdoc @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** 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 +** +****************************************************************************/ + +/*! + \title Qt Data Visualization + \page qtdatavisualization-index.html + \brief QtDataVisualization module provides functionality for 3D visualization. + + Qt Data Visualization module provides a way to visualize data in 3D. + + \section1 Features + + \list + \li Multiple data visualization options: 3D Bars, 3D Scatter, and 3D Surface + \li 2D slice views of the 3D data + \li Interactive data: Rotate, zoom, and highlight data using mouse or touch + \li Uses OpenGL for rendering the data + \li QML2 support + \li Customizable axes for data - control viewable data window with axis ranges + \li Customizable input handling (upcoming feature - not supported in technology preview) + \li Customizable scene handling - full control of cameras and lights (upcoming feature - + not supported in technology preview) + \li Customizable themes (upcoming feature - not supported in technology preview) + \endlist + + \section1 Getting Started + + To import Qt Data Visualization QML types, add the following import statement to your \c .qml + file: + + \snippet doc_src_qmldatavisualization.cpp 0 + + If you intend to use Qt Data Visualization C++ classes in your application, use the + following include and using directives: + + \snippet doc_src_qtdatavisualization.cpp 0 + + \note If you are using a few classes from this module, we recommend including those specific + classes only instead of the whole module. + + To link against Qt Data Visualization module, add this line to your \c qmake project file: + + \snippet doc_src_qtdatavisualization.pro 0 + + See \l{Qt Data Visualization Getting Started}{Getting started} page for further information + how to use Qt Data Visualization in your application. + + \section1 Articles + \list + \li \l{Qt Data Visualization Data Handling}{Data input} + \li \l{Qt Data Visualization Interacting with Data}{Interacting with visualized data} + \endlist + + \section1 References + \list + \li \l{Qt Data Visualization C++ Classes} + \li \l{Qt Data Visualization QML Types} + \endlist + + Qt Data Visualization comes with the following examples: + + \annotatedlist qtdatavisualization_examples +*/ diff --git a/src/datavisualization/doc/src/qtdatavisualization-qml-abstractdeclarative.qdoc b/src/datavisualization/doc/src/qtdatavisualization-qml-abstractdeclarative.qdoc new file mode 100644 index 00000000..7a0d2c4a --- /dev/null +++ b/src/datavisualization/doc/src/qtdatavisualization-qml-abstractdeclarative.qdoc @@ -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 +** +****************************************************************************/ + +/*! + \qmltype AbstractGraph3D + \inqmlmodule com.digia.QtDataVisualization 1.0 + \since com.digia.QtDataVisualization 1.0 + \ingroup datavisualization_qml + \brief Base type for 3D visualizations. + + This type is the base type for all 3D visualizations in QtDataVisualization. + + It resides in the data visualization module that can be imported like this: + + \snippet doc_src_qmldatavisualization.cpp 0 + + Note that this type is uncreatable, but contains properties that are shared between + the 3D visualizations. + + \sa Bars3D, Scatter3D, Surface3D, {Qt Data Visualization C++ Classes} + */ + +/*! + \qmlproperty AbstractGraph3D.SelectionMode AbstractGraph3D::selectionMode + Active selection mode in the visualization. + */ +/*! + \qmlproperty AbstractGraph3D.LabelStyle AbstractGraph3D::labelStyle + Label style. + */ + +/*! + \qmlproperty AbstractGraph3D.ShadowQuality AbstractGraph3D::shadowQuality + Shadow quality. + */ + +/*! + \qmlproperty AbstractGraph3D.CameraPreset AbstractGraph3D::cameraPreset + Camera preset. + */ + +/*! + \qmlproperty AbstractGraph3D.Theme AbstractGraph3D::theme + Theme of the graph. Theme affects visualization colors, label colors, text color, background color, window + color and grid color. Lighting is also adjusted by themes. + */ + +/*! + \qmlproperty font AbstractGraph3D::font + Font used for labels. + */ + +/*! + \qmlproperty bool AbstractGraph3D::gridVisible + Grid visibility. If false, grid lines are not drawn. + */ + +/*! + \qmlproperty bool AbstractGraph3D::backgroundVisible + Background visibility. If false, background is not drawn. + */ + +/*! + \qmlproperty string AbstractGraph3D::itemLabelFormat + Label format of single item labels, e.g. a selected datapoint. + */ diff --git a/src/datavisualization/doc/src/qtdatavisualization-qml-bars3d.qdoc b/src/datavisualization/doc/src/qtdatavisualization-qml-bars3d.qdoc new file mode 100644 index 00000000..213542b9 --- /dev/null +++ b/src/datavisualization/doc/src/qtdatavisualization-qml-bars3d.qdoc @@ -0,0 +1,136 @@ +/**************************************************************************** +** +** 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 +** +****************************************************************************/ + +/*! + * \qmltype Bars3D + * \inherits AbstractGraph3D + * \inqmlmodule com.digia.QtDataVisualization 1.0 + * \since com.digia.QtDataVisualization 1.0 + * \ingroup datavisualization_qml + * \brief 3D bar graph. + * + * This type enables developers to render bar graphs in 3D with Qt Quick 2. + * + * You will need to import data visualization module to use this type: + * + * \snippet doc_src_qmldatavisualization.cpp 0 + * + * After that you can use Bars3D in your qml files: + * + * \snippet doc_src_qmldatavisualization.cpp 1 + * + * See \l{Qt Quick 2 Bars Example} for more thorough usage example. + * + * \sa ItemModelBarDataProxy, Scatter3D, Surface3D, {Qt Data Visualization C++ Classes} + */ + +/*! + * \qmlmethod void Bars3D::setBarColor(const QColor &baseColor, bool uniform) + * Set bar color using your own color. \a baseColor sets the base color of a bar. The \a uniform + * -flag is used to define if color needs to be uniform throughout bar's length, or will the colors + * be applied by height, starting with dark at the bottom. It is \c true by default. + * + * Calling this method overrides colors from theme. + * + * \sa AbstractGraph3D::theme + * + * \warning This method is subject to change. + */ + +/*! + * \qmlproperty BarDataProxy Bars3D::dataProxy + * The active data proxy. + * + * If a proxy is not given, a temporary default proxy is created and activated. + * This temporary proxy is destroyed if another proxy is explicitly set active via this property. + */ + +/*! + * \qmlproperty CategoryAxis3D Bars3D::rowAxis + * A user-defined row axis. + * + * If an axis is not given, a temporary default axis with no labels is created. + * This temporary axis is destroyed if another axis is explicitly set to same orientation. + */ + +/*! + * \qmlproperty ValueAxis3D Bars3D::valueAxis + * A user-defined value axis. + * + * If an axis is not given, a temporary default axis with no labels and automatically adjusting + * range is created. + * This temporary axis is destroyed if another axis is explicitly set to same orientation. + */ + +/*! + * \qmlproperty CategoryAxis3D Bars3D::columnAxis + * A user-defined column axis. + * + * If an axis is not given, a temporary default axis with no labels is created. + * This temporary axis is destroyed if another axis is explicitly set to same orientation. + */ + + +/*! + * \qmlproperty Bars3D.MeshStyle Bars3D::barType + * Bar object type. + */ + +/*! + * \qmlproperty real Bars3D::barThickness + * Bar thickness ratio between X and Z dimensions. 1.0 means bars are as wide as they are deep, 0.5 + * makes them twice as deep as they are wide. + */ + +/*! + * \qmlproperty size Bars3D::barSpacing + * Bar spacing in X and Z dimensions. + */ + +/*! + * \qmlproperty bool Bars3D::barSpacingRelative + * Relative or absolute bar spacing. + */ + +/*! + * \qmlproperty bool Bars3D::barSmoothingEnabled + * Bar smoothing. If false, bar shading is flat. + */ + +/*! + * \qmlproperty string Bars3D::meshFileName + * Override bar type with a mesh object. + * \note Object needs to be in Wavefront obj format and include vertices, normals and UVs. + * It also needs to be in triangles. + */ + +/*! + * \qmlproperty int Bars3D::rows + * Row count of data window. + */ + +/*! + * \qmlproperty int Bars3D::columns + * Column count of data window. + */ + +/*! + * \qmlproperty point Bars3D::selectedBarPos + * Position of the selected bar in data window. Only one bar can be selected at a time. + * To clear selection, specify an illegal position, e.g. Qt.point(-1.0, -1.0). + */ diff --git a/src/datavisualization/doc/src/qtdatavisualization-qml-colorgradient.qdoc b/src/datavisualization/doc/src/qtdatavisualization-qml-colorgradient.qdoc new file mode 100644 index 00000000..f8edf492 --- /dev/null +++ b/src/datavisualization/doc/src/qtdatavisualization-qml-colorgradient.qdoc @@ -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 +** +****************************************************************************/ + +/*! + \qmltype ColorGradientStop + \inqmlmodule com.digia.QtDataVisualization 1.0 + \since com.digia.QtDataVisualization 1.0 + \ingroup datavisualization_qml + \brief Defines the color at a position in ColorGradient. + + Defines the color at a position in a ColorGradient. + + \sa ColorGradient +*/ + +/*! + \qmlproperty real ColorGradientStop::position + + The position property describes the position of this gradient stop. + + The default position is 0.0. + + \sa ColorGradient +*/ + +/*! + \qmlproperty color ColorGradientStop::color + + The color property describes the color color of this gradient stop. + + The default color is black. + + \sa ColorGradient +*/ + +/*! + \qmltype ColorGradient + \inqmlmodule com.digia.QtDataVisualization 1.0 + \since com.digia.QtDataVisualization 1.0 + \ingroup datavisualization_qml + \brief Defines a color gradient. + + A gradient is defined by two or more colors, which will be blended seamlessly. + + The colors are specified as a set of ColorGradientStop child items, each of + which defines a position on the gradient from 0.0 to 1.0 and a color. + The position of each ColorGradientStop is defined by setting its + \l{ColorGradientStop::}{position} property; its color is defined using its + \l{ColorGradientStop::}{color} property. + + A gradient without any gradient stops falls back to QLinearGradient default, + which is black at 0.0 and white at 1.0. + + \sa ColorGradientStop +*/ + +/*! + \qmlproperty list<ColorGradientStop> ColorGradient::stops + \default + + This property holds the gradient stops describing the gradient. + + By default, this property contains an empty list. + + To set the gradient stops, define them as children of the ColorGradient. +*/ diff --git a/src/datavisualization/doc/src/qtdatavisualization-qml-scatter3d.qdoc b/src/datavisualization/doc/src/qtdatavisualization-qml-scatter3d.qdoc new file mode 100644 index 00000000..2839468e --- /dev/null +++ b/src/datavisualization/doc/src/qtdatavisualization-qml-scatter3d.qdoc @@ -0,0 +1,105 @@ +/**************************************************************************** +** +** 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 +** +****************************************************************************/ + +/*! + \qmltype Scatter3D + \inherits AbstractGraph3D + \inqmlmodule com.digia.QtDataVisualization 1.0 + \since com.digia.QtDataVisualization 1.0 + \ingroup datavisualization_qml + \brief 3D scatter graph. + + This type enables developers to render scatter graphs in 3D with Qt Quick 2. + + You will need to import data visualization module to use this type: + + \snippet doc_src_qmldatavisualization.cpp 0 + + After that you can use Scatter3D in your qml files: + + \snippet doc_src_qmldatavisualization.cpp 2 + + See \l{Qt Quick 2 Scatter Example} for more thorough usage example. + + \sa ItemModelScatterDataProxy, Bars3D, Surface3D, {Qt Data Visualization C++ Classes} + */ + +/*! + * \qmlmethod void Scatter3D::setObjectColor(const QColor &baseColor, bool uniform) + * Set item color using your own colors. \a baseColor sets the base color of a item. The \a uniform + * -flag is used to define if color needs to be uniform throughout item's length, or will the colors + * be applied by height. It is \c true by default. + * + * Calling this method overrides colors from theme. + * + * \sa AbstractGraph3D::theme + * + * \warning This method is subject to change. + */ + +/*! + \qmlproperty ScatterDataProxy Scatter3D::dataProxy + The active data proxy. + + If a proxy is not given, a temporary default proxy is created and activated. + This temporary proxy is destroyed if another proxy is explicitly set active via this property. + */ + +/*! + \qmlproperty ValueAxis3D Scatter3D::axisX + A user-defined X axis. + + If an axis is not given, a temporary default axis with no labels and automatically adjusting + range is created. + This temporary axis is destroyed if another axis is explicitly set to same orientation. + */ + +/*! + \qmlproperty ValueAxis3D Scatter3D::axisY + A user-defined Y axis. + + If an axis is not given, a temporary default axis with no labels and automatically adjusting + range is created. + This temporary axis is destroyed if another axis is explicitly set to same orientation. + */ + +/*! + \qmlproperty ValueAxis3D Scatter3D::axisZ + A user-defined Z axis. + + If an axis is not given, a temporary default axis with no labels and automatically adjusting + range is created. + This temporary axis is destroyed if another axis is explicitly set to same orientation. + */ + +/*! + \qmlproperty Scatter3D.MeshStyle Scatter3D::objectType + Dot object type. + */ + +/*! + \qmlproperty bool Scatter3D::objectSmoothingEnabled + Dot smoothing. If false, dot shading is flat. + */ + +/*! + \qmlproperty string Scatter3D::meshFileName + Override object type with a mesh object. + \note Object needs to be in Wavefront obj format and include vertices, normals and UVs. + It also needs to be in triangles. + */ diff --git a/src/datavisualization/doc/src/qtdatavisualization-qml-surface3d.qdoc b/src/datavisualization/doc/src/qtdatavisualization-qml-surface3d.qdoc new file mode 100644 index 00000000..3669c1cd --- /dev/null +++ b/src/datavisualization/doc/src/qtdatavisualization-qml-surface3d.qdoc @@ -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 +** +****************************************************************************/ + +/*! + \qmltype Surface3D + \inherits AbstractGraph3D + \inqmlmodule com.digia.QtDataVisualization 1.0 + \since com.digia.QtDataVisualization 1.0 + \ingroup datavisualization_qml + \brief 3D surface graph. + + This type enables developers to render surface plots in 3D with Qt Quick 2. + + You will need to import data visualization module to use this type: + + \snippet doc_src_qmldatavisualization.cpp 0 + + After that you can use Surface3D in your qml files: + + \snippet doc_src_qmldatavisualization.cpp 3 + + See \l{Qt Quick 2 Surface Example} for more thorough usage example. + + \sa ItemModelSurfaceDataProxy, Bars3D, Scatter3D, {Qt Data Visualization C++ Classes} + */ + +/*! + \qmlproperty SurfaceDataProxy Surface3D::dataProxy + The active data proxy. + + If a proxy is not given, a temporary default proxy is created and activated. + This temporary proxy is destroyed if another proxy is explicitly set active via this property. + */ + +/*! + \qmlproperty ValueAxis3D Surface3D::axisX + A user-defined X axis. + + If an axis is not given, a temporary default axis with no labels and automatically adjusting + range is created. + This temporary axis is destroyed if another axis is explicitly set to same orientation. + */ + +/*! + \qmlproperty ValueAxis3D Surface3D::axisY + A user-defined Y axis. + + If an axis is not given, a temporary default axis with no labels and automatically adjusting + range is created. + This temporary axis is destroyed if another axis is explicitly set to same orientation. + */ + +/*! + \qmlproperty ValueAxis3D Surface3D::axisZ + A user-defined Z axis. + + If an axis is not given, a temporary default axis with no labels and automatically adjusting + range is created. + This temporary axis is destroyed if another axis is explicitly set to same orientation. + */ + +/*! + \qmlproperty bool Surface3D::smoothSurfaceEnabled + Smoothing of surface. If false, shading of the surface is flat. + */ + +/*! + \qmlproperty bool Surface3D::surfaceGridEnabled + Surface grid visibility. If false, no surface grid is drawn. + */ + +/*! + \qmlproperty ColorGradient Surface3D::gradient + The current surface gradient. Setting this property replaces the previous gradient. + */ diff --git a/src/datavisualization/doc/src/qtdatavisualization.qdoc b/src/datavisualization/doc/src/qtdatavisualization.qdoc new file mode 100644 index 00000000..45087e9d --- /dev/null +++ b/src/datavisualization/doc/src/qtdatavisualization.qdoc @@ -0,0 +1,209 @@ +/**************************************************************************** +** +** 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 +** +****************************************************************************/ + +/*! + \module QtDataVisualization + \title Qt Data Visualization C++ Classes + \ingroup modules + + \brief The QtDataVisualization module provides functionality for 3D visualization. +*/ + +/*! + \group datavisualization_qml + \title Qt Data Visualization QML Types + + \brief QML types for the Qt Data Visualization API. + + Qt Data Visualization functionality can be accessed via these QML types. + + \section1 QML Types +*/ + +/*! + \page qtdatavisualization_getting_started.html + \title Qt Data Visualization Getting Started + + \section1 Building Qt Data Visualization + + To build Qt Data Visualization module, set up a command prompt with an environment for + building Qt applications, navigate to the directory containing \c qtdatavisualization.pro, + and give the following commands: + + \snippet doc_src_qtdatavisualization.cpp 6 + + \note The \c make tool name may vary depending on your target platform. + E.g. make/nmake/mingw32-make/... + + To build a statically linked version of the Qt Data Visualization module, give the following + commands: + + \snippet doc_src_qtdatavisualization.cpp 7 + + \section1 Running examples + + Qt Data Visualization examples are found under \c examples subdirectory. To build and run a + single example, e.g. the qmlsurface example, navigate to the example directory and give the + following commands: + + \snippet doc_src_qtdatavisualization.cpp 8 + + \note On some platforms, such as Windows, the executable can be generated under debug or + release folders, depending on your build. + + \section1 Creating a simple application + + To create a simple application, start by creating a new Qt Gui Application project in Qt + Creator and add this line to the \c .pro file of the project: + + \snippet doc_src_qtdatavisualization.pro 0 + + In the \c main.cpp file, include the module headers and declare namespace usage: + + \snippet doc_src_qtdatavisualization.cpp 0 + + Then, add the sample code found in one of the following pages, depending on what kind of + visualization you are interested in: \l{How to construct a minimal Q3DBars graph}, + \l{How to construct a minimal Q3DScatter graph}, or + \l{How to construct a minimal Q3DSurface graph}. + + To use Qt Data Visualization graphs in widget based applications, you can use + QWidget::createWindowContainer() function to wrap the graph into a widget: + + \snippet doc_src_qtdatavisualization.cpp 9 + + For further code examples, see one of the Qt Data Visualization examples: + + \annotatedlist qtdatavisualization_examples +*/ + +/*! + \page qtdatavisualization_data_handling.html + \title Qt Data Visualization Data Handling + + \section1 Data proxies + + The data users wish to visualize comes in many formats, all of which cannot obviously be + directly supported. Therefore Qt Data Visualization implements data proxies into which + user can feed their data in a known format. Each visualization type has a basic proxy type, + which takes data in a format suitable for that visualization. + For example, the basic proxy for Q3DBars is QBarDataProxy, which stores rows of QBarDataItem + objects. Each QBarDataItem stores a single bar value. Additional typedefs are provided for + QBarDataArray and QBarDataRow containers. + + This code snipped shows how to use basic proxy when your data is stored in some hypothetical + \c myData object: + + \snippet doc_src_qtdatavisualization.cpp 10 + + \note The graph objects can own more than one data proxy, but only one proxy can be + active at a time. If you need to switch back and forth between two different sets of data, + it may be more efficient to store each set in different proxy and just change the active + proxy, rather than reset the data in one proxy every time you need to switch. + + \section1 Item models and data mapping + + For common use cases, Qt Data Visualization offers specialized proxies. One such case is having + data in an item model (QAbstractItemModel subclass), which is a common way to store data in + Qt applications. Each of the visualization types offers a special proxy and a corresponding mapping + class for this purpose, e.g. QItemModelBarDataProxy and QItemModelBarDataMapping for Q3DBars. + These proxies are simple to use - just give them a pointer to the item model containing the + data and the mapping object containing rules how to map the data into format the basic proxy can + digest. + + Mapping objects work with item model roles. Each data item in the model can have different + values for different roles. For example, with QItemModelBarDataMapping you can specify which + role is used to determine which row the item belongs to, which role does the same for columns, + and which role specifies the value of the item. When the proxy resolves the data from the model, + it uses these mappings to generate the rows and columns of the bar graph. + + Depending on the visualization type, mapping classes may support other functionality as well, + such as QItemModelBarDataMapping optionally mapping QAbstractItemModel rows and columns directly + into bar graph rows and columns. See individual mapping classes for more information and examples + how to use them: QItemModelBarDataMapping, QItemModelScatterDataMapping, and + QItemModelSurfaceDataMapping. + + \section1 Other custom proxies + + QHeightMapSurfaceDataProxy is a specialized proxy for generating a surface graph from a + heightmap image. See QHeightMapSurfaceDataProxy documentation for more information. + + The \l{Custom Proxy Example}{Custom Proxy} example shows how a custom proxy can be created. It + defines a custom data set based on variant lists and an extension of the basic proxy to resolve + that data with an associated mapper. + + \section1 Dealing with real-time data + + When you have a data set that updates rapidly, it is important to handle data properly to + ensure good performance. Since memory allocation is a costly operation, always use + QList::reserve() and QVector::resize() where possible to avoid reallocations when constructing + the array to give to the proxy. If you need to change the entire data set for each frame, + it is in most cases best to re-use the existing array - especially if the array dimensions do not + change. If you need to add, insert, remove, or change several rows or items for each frame, it + is always more efficient to do it with one method call instead of multiple calls affecting + a single row or item each. For example, adding ten rows with a single QBarDataProxy::addRows() call + is much more efficient than ten separate QBarDataProxy::addRow() calls. + + Bars renderer is optimized to access only data that is within data window and thus should not + suffer noticeable slowdown even if more data is continually added to the proxy. + + Due to the unsorted nature of the scatter data, any change in the data window ranges requires + all data points to be checked for visibility, which can cause increasing slowdown if data is + continually added to the proxy. + + Surface data, while on item level similar to scatter data, is already assigned into rows and + columns, so the surface renderer can do some optimization by making assumption that the data in + rows and columns is sorted along their respective axes, but it is nowhere near as efficient + as in bars case. Surface rendering can suffer significant slowdown if the data size grows unchecked. + + For the best performance with the scatter and surface graphs, only keep the data you need in the + proxy. + + \note Data handling is not yet fully optimized in the technology preview version. +*/ + +/*! + \page qtdatavisualization_interacting_with_data.html + \title Qt Data Visualization Interacting with Data + + \section1 Interacting with data + + You can interact with the rendered graph with either mouse or touch to rotate, zoom, or select + data. For the mouse controls, see Q3DInputHandler documentation, and for the touch controls, + see QTouch3DInputHandler documentation. + + \note In the technology preview version, default input handlers cannot be replaced or even accessed + via public API. This feature is planned for the final release. + + \section1 Data selection modes + + All visualization types support selecting single data item - a bar, a scatter item, or a surface + vertex - using mouse, touch, and programmatically via the graph APIs. The selected item is highlighted + in the rendered graph, and selecting causes emission of a graph specific signal for this purpose, + e.g. Q3DBars::selectedBarPosChanged(), which the application can handle. + + \note Surface graph doesn't have fully implemented selection API yet, it only supports + selection with mouse and touch in the technology preview version. + + Bar and surface graphs support slice selection modes, where the selected row or column is drawn + in a separate viewport as a pseudo-2D graph. This makes it easier to see the actual values of + single row or column. + + Bar graph additionally supports simply highlighting the whole row and/or column of the selected bar + without opening the slice view. +*/ diff --git a/src/datavisualization/engine/abstract3dcontroller.cpp b/src/datavisualization/engine/abstract3dcontroller.cpp new file mode 100644 index 00000000..bfdc375e --- /dev/null +++ b/src/datavisualization/engine/abstract3dcontroller.cpp @@ -0,0 +1,1056 @@ +/**************************************************************************** +** +** 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 "abstract3dcontroller_p.h" +#include "camerahelper_p.h" +#include "q3dabstractaxis_p.h" +#include "q3dvalueaxis.h" +#include "q3dcategoryaxis.h" +#include "abstract3drenderer_p.h" +#include "q3dcamera.h" +#include "q3dlight.h" +#include "qabstractdataproxy_p.h" +#include "qabstract3dinputhandler_p.h" +#include "qtouch3dinputhandler.h" + +#include <QThread> + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +Abstract3DController::Abstract3DController(QRect boundRect, QObject *parent) : + QObject(parent), + m_boundingRect(boundRect.x(), boundRect.y(), boundRect.width(), boundRect.height()), + m_theme(), + m_font(QFont(QStringLiteral("Arial"))), + m_selectionMode(QDataVis::SelectionModeItem), + m_shadowQuality(QDataVis::ShadowQualityMedium), + m_labelStyle(QDataVis::LabelStyleTransparent), + m_isBackgroundEnabled(true), + m_isGridEnabled(true), + m_scene(new Q3DScene()), + m_activeInputHandler(0), + m_axisX(0), + m_axisY(0), + m_axisZ(0), + m_renderer(0), + m_isDataDirty(true), + m_data(0), + m_renderPending(false) +{ + m_theme.useTheme(QDataVis::ThemeQt); + + // Populate the scene + m_scene->activeLight()->setPosition(defaultLightPos); + + // Create initial default input handler + QAbstract3DInputHandler *inputHandler; + inputHandler = new QTouch3DInputHandler(); + inputHandler->d_ptr->m_isDefaultHandler = true; + setActiveInputHandler(inputHandler); + connect(inputHandler, &QAbstract3DInputHandler::inputStateChanged, this, + &Abstract3DController::emitNeedRender); + connect(m_scene, &Q3DScene::needRender, this, + &Abstract3DController::emitNeedRender); +} + +Abstract3DController::~Abstract3DController() +{ + // Renderer can be in another thread, don't delete it directly in that case + if (m_renderer && m_renderer->thread() != QThread::currentThread()) + m_renderer->deleteLater(); + else + delete m_renderer; + delete m_scene; +} + +void Abstract3DController::setRenderer(Abstract3DRenderer *renderer) +{ + m_renderer = renderer; +} + +void Abstract3DController::synchDataToRenderer() +{ + // If we don't have a renderer, don't do anything + if (!m_renderer) + return; + + if (m_changeTracker.boundingRectChanged || m_changeTracker.sizeChanged) { + m_renderer->updateBoundingRect(m_boundingRect); + m_changeTracker.boundingRectChanged = false; + m_changeTracker.sizeChanged = false; + } + + if (m_changeTracker.positionChanged) { + m_renderer->updatePosition(m_boundingRect); + m_changeTracker.positionChanged = false; + } + + m_renderer->updateScene(m_scene); + + if (m_changeTracker.themeChanged) { + m_renderer->updateTheme(m_theme); + m_changeTracker.themeChanged = false; + } + + if (m_changeTracker.fontChanged) { + m_renderer->updateFont(m_font); + m_changeTracker.fontChanged = false; + } + + if (m_changeTracker.labelStyleChanged) { + m_renderer->updateLabelStyle(m_labelStyle); + m_changeTracker.labelStyleChanged = false; + } + + if (m_changeTracker.shadowQualityChanged) { + m_renderer->updateShadowQuality(m_shadowQuality); + m_changeTracker.shadowQualityChanged = false; + } + + if (m_changeTracker.selectionModeChanged) { + m_renderer->updateSelectionMode(m_selectionMode); + m_changeTracker.selectionModeChanged = false; + } + + if (m_changeTracker.objFileChanged) { + m_renderer->updateMeshFileName(m_objFile); + m_changeTracker.objFileChanged = false; + } + + if (m_changeTracker.gridEnabledChanged) { + m_renderer->updateGridEnabled(m_isGridEnabled); + m_changeTracker.gridEnabledChanged = false; + } + + if (m_changeTracker.backgroundEnabledChanged) { + m_renderer->updateBackgroundEnabled(m_isBackgroundEnabled); + m_changeTracker.backgroundEnabledChanged = false; + } + + if (m_changeTracker.axisXTypeChanged) { + m_renderer->updateAxisType(Q3DAbstractAxis::AxisOrientationX, m_axisX->type()); + m_changeTracker.axisXTypeChanged = false; + } + + if (m_changeTracker.axisYTypeChanged) { + m_renderer->updateAxisType(Q3DAbstractAxis::AxisOrientationY, m_axisY->type()); + m_changeTracker.axisYTypeChanged = false; + } + + if (m_changeTracker.axisZTypeChanged) { + m_renderer->updateAxisType(Q3DAbstractAxis::AxisOrientationZ, m_axisZ->type()); + m_changeTracker.axisZTypeChanged = false; + } + + if (m_changeTracker.axisXTitleChanged) { + m_renderer->updateAxisTitle(Q3DAbstractAxis::AxisOrientationX, m_axisX->title()); + m_changeTracker.axisXTitleChanged = false; + } + + if (m_changeTracker.axisYTitleChanged) { + m_renderer->updateAxisTitle(Q3DAbstractAxis::AxisOrientationY, m_axisY->title()); + m_changeTracker.axisYTitleChanged = false; + } + + if (m_changeTracker.axisZTitleChanged) { + m_renderer->updateAxisTitle(Q3DAbstractAxis::AxisOrientationZ, m_axisZ->title()); + m_changeTracker.axisZTitleChanged = false; + } + + if (m_changeTracker.axisXLabelsChanged) { + m_renderer->updateAxisLabels(Q3DAbstractAxis::AxisOrientationX, m_axisX->labels()); + m_changeTracker.axisXLabelsChanged = false; + } + + if (m_changeTracker.axisYLabelsChanged) { + m_renderer->updateAxisLabels(Q3DAbstractAxis::AxisOrientationY, m_axisY->labels()); + m_changeTracker.axisYLabelsChanged = false; + } + if (m_changeTracker.axisZLabelsChanged) { + m_renderer->updateAxisLabels(Q3DAbstractAxis::AxisOrientationZ, m_axisZ->labels()); + m_changeTracker.axisZLabelsChanged = false; + } + + if (m_changeTracker.axisXRangeChanged) { + m_renderer->updateAxisRange(Q3DAbstractAxis::AxisOrientationX, m_axisX->min(), + m_axisX->max()); + m_changeTracker.axisXRangeChanged = false; + } + + if (m_changeTracker.axisYRangeChanged) { + m_renderer->updateAxisRange(Q3DAbstractAxis::AxisOrientationY, m_axisY->min(), + m_axisY->max()); + m_changeTracker.axisYRangeChanged = false; + } + + if (m_changeTracker.axisZRangeChanged) { + m_renderer->updateAxisRange(Q3DAbstractAxis::AxisOrientationZ, m_axisZ->min(), + m_axisZ->max()); + m_changeTracker.axisZRangeChanged = false; + } + + if (m_changeTracker.axisXSegmentCountChanged) { + m_changeTracker.axisXSegmentCountChanged = false; + if (m_axisX->type() & Q3DAbstractAxis::AxisTypeValue) { + Q3DValueAxis *valueAxisX = static_cast<Q3DValueAxis *>(m_axisX); + m_renderer->updateAxisSegmentCount(Q3DAbstractAxis::AxisOrientationX, + valueAxisX->segmentCount()); + } + } + + if (m_changeTracker.axisYSegmentCountChanged) { + m_changeTracker.axisYSegmentCountChanged = false; + if (m_axisY->type() & Q3DAbstractAxis::AxisTypeValue) { + Q3DValueAxis *valueAxisY = static_cast<Q3DValueAxis *>(m_axisY); + m_renderer->updateAxisSegmentCount(Q3DAbstractAxis::AxisOrientationY, + valueAxisY->segmentCount()); + } + } + + if (m_changeTracker.axisZSegmentCountChanged) { + m_changeTracker.axisZSegmentCountChanged = false; + if (m_axisZ->type() & Q3DAbstractAxis::AxisTypeValue) { + Q3DValueAxis *valueAxisZ = static_cast<Q3DValueAxis *>(m_axisZ); + m_renderer->updateAxisSegmentCount(Q3DAbstractAxis::AxisOrientationZ, + valueAxisZ->segmentCount()); + } + } + + if (m_changeTracker.axisXSubSegmentCountChanged) { + m_changeTracker.axisXSubSegmentCountChanged = false; + if (m_axisX->type() & Q3DAbstractAxis::AxisTypeValue) { + Q3DValueAxis *valueAxisX = static_cast<Q3DValueAxis *>(m_axisX); + m_renderer->updateAxisSubSegmentCount(Q3DAbstractAxis::AxisOrientationX, + valueAxisX->subSegmentCount()); + } + } + + if (m_changeTracker.axisYSubSegmentCountChanged) { + m_changeTracker.axisYSubSegmentCountChanged = false; + if (m_axisY->type() & Q3DAbstractAxis::AxisTypeValue) { + Q3DValueAxis *valueAxisY = static_cast<Q3DValueAxis *>(m_axisY); + m_renderer->updateAxisSubSegmentCount(Q3DAbstractAxis::AxisOrientationY, + valueAxisY->subSegmentCount()); + } + } + + if (m_changeTracker.axisZSubSegmentCountChanged) { + m_changeTracker.axisZSubSegmentCountChanged = false; + if (m_axisZ->type() & Q3DAbstractAxis::AxisTypeValue) { + Q3DValueAxis *valueAxisZ = static_cast<Q3DValueAxis *>(m_axisZ); + m_renderer->updateAxisSubSegmentCount(Q3DAbstractAxis::AxisOrientationZ, + valueAxisZ->subSegmentCount()); + } + } + + if (m_changeTracker.axisXLabelFormatChanged) { + m_changeTracker.axisXLabelFormatChanged = false; + if (m_axisX->type() & Q3DAbstractAxis::AxisTypeValue) { + Q3DValueAxis *valueAxisX = static_cast<Q3DValueAxis *>(m_axisX); + m_renderer->updateAxisLabelFormat(Q3DAbstractAxis::AxisOrientationX, + valueAxisX->labelFormat()); + } + } + + if (m_changeTracker.axisYLabelFormatChanged) { + m_changeTracker.axisYLabelFormatChanged = false; + if (m_axisY->type() & Q3DAbstractAxis::AxisTypeValue) { + Q3DValueAxis *valueAxisY = static_cast<Q3DValueAxis *>(m_axisY); + m_renderer->updateAxisLabelFormat(Q3DAbstractAxis::AxisOrientationY, + valueAxisY->labelFormat()); + } + } + + if (m_changeTracker.axisZLabelFormatChanged) { + m_changeTracker.axisZLabelFormatChanged = false; + if (m_axisZ->type() & Q3DAbstractAxis::AxisTypeValue) { + Q3DValueAxis *valueAxisZ = static_cast<Q3DValueAxis *>(m_axisZ); + m_renderer->updateAxisLabelFormat(Q3DAbstractAxis::AxisOrientationZ, + valueAxisZ->labelFormat()); + } + } +} + +void Abstract3DController::render(const GLuint defaultFboHandle) +{ + m_renderPending = false; + + // If not initialized, do nothing. + if (!m_renderer) + return; + + m_renderer->render(defaultFboHandle); + +#ifdef DISPLAY_RENDER_SPEED + // To get meaningful framerate, don't just do render on demand. + emitNeedRender(); +#endif +} + +void Abstract3DController::mouseDoubleClickEvent(QMouseEvent *event) +{ + if (m_activeInputHandler) + m_activeInputHandler->mouseDoubleClickEvent(event); + + emitNeedRender(); +} + +void Abstract3DController::touchEvent(QTouchEvent *event) +{ + if (m_activeInputHandler) + m_activeInputHandler->touchEvent(event); + + emitNeedRender(); +} + +void Abstract3DController::mousePressEvent(QMouseEvent *event, const QPoint &mousePos) +{ + if (m_activeInputHandler) + m_activeInputHandler->mousePressEvent(event, mousePos); + + emitNeedRender(); +} + +void Abstract3DController::mouseReleaseEvent(QMouseEvent *event, const QPoint &mousePos) +{ + if (m_activeInputHandler) + m_activeInputHandler->mouseReleaseEvent(event, mousePos); + + emitNeedRender(); +} + +void Abstract3DController::mouseMoveEvent(QMouseEvent *event, const QPoint &mousePos) +{ + if (m_activeInputHandler) + m_activeInputHandler->mouseMoveEvent(event, mousePos); + + emitNeedRender(); +} + +void Abstract3DController::wheelEvent(QWheelEvent *event) +{ + if (m_activeInputHandler) + m_activeInputHandler->wheelEvent(event); + + emitNeedRender(); +} + +void Abstract3DController::setSize(const int width, const int height) +{ + m_boundingRect.setWidth(width); + m_boundingRect.setHeight(height); + m_scene->setViewportSize(width, height); + + m_changeTracker.boundingRectChanged = true; + emitNeedRender(); +} + +const QSize Abstract3DController::size() +{ + return m_boundingRect.size(); +} + +const QRect Abstract3DController::boundingRect() +{ + return m_boundingRect; +} + +void Abstract3DController::setBoundingRect(const QRect boundingRect) +{ + m_boundingRect = boundingRect; + m_scene->setViewport(boundingRect); + + m_changeTracker.boundingRectChanged = true; + emitNeedRender(); +} + +void Abstract3DController::setWidth(const int width) +{ + m_boundingRect.setWidth(width); + m_scene->setViewportSize(width, m_scene->viewport().height()); + + m_changeTracker.sizeChanged = true; + emitNeedRender(); +} + +int Abstract3DController::width() +{ + return m_boundingRect.width(); +} + +void Abstract3DController::setHeight(const int height) +{ + m_boundingRect.setHeight(height); + m_scene->setViewportSize(m_scene->viewport().width(), height); + + m_changeTracker.sizeChanged = true; + emitNeedRender(); +} + +int Abstract3DController::height() +{ + return m_boundingRect.height(); +} + +void Abstract3DController::setX(const int x) +{ + m_boundingRect.setX(x); + + m_changeTracker.positionChanged = true; + emitNeedRender(); +} + +int Abstract3DController::x() +{ + return m_boundingRect.x(); +} + +void Abstract3DController::setY(const int y) +{ + m_boundingRect.setY(y); + + m_changeTracker.positionChanged = true; + emitNeedRender(); +} + +int Abstract3DController::y() +{ + return m_boundingRect.y(); +} + +QRect Abstract3DController::primarySubViewport() const +{ + return m_scene->primarySubViewport(); +} + +void Abstract3DController::setPrimarySubViewport(const QRect &primarySubViewport) +{ + m_scene->setPrimarySubViewport(primarySubViewport); +} + +QRect Abstract3DController::secondarySubViewport() const +{ + return m_scene->secondarySubViewport(); +} + +void Abstract3DController::setSecondarySubViewport(const QRect &secondarySubViewport) +{ + m_scene->setSecondarySubViewport(secondarySubViewport); +} + +void Abstract3DController::updateDevicePixelRatio(qreal ratio) +{ + m_scene->setDevicePixelRatio(ratio); +} + +void Abstract3DController::setAxisX(Q3DAbstractAxis *axis) +{ + setAxisHelper(Q3DAbstractAxis::AxisOrientationX, axis, &m_axisX); +} + +Q3DAbstractAxis *Abstract3DController::axisX() +{ + return m_axisX; +} + +void Abstract3DController::setAxisY(Q3DAbstractAxis *axis) +{ + setAxisHelper(Q3DAbstractAxis::AxisOrientationY, axis, &m_axisY); +} + +Q3DAbstractAxis *Abstract3DController::axisY() +{ + return m_axisY; +} + +void Abstract3DController::setAxisZ(Q3DAbstractAxis *axis) +{ + setAxisHelper(Q3DAbstractAxis::AxisOrientationZ, axis, &m_axisZ); +} + +Q3DAbstractAxis *Abstract3DController::axisZ() +{ + return m_axisZ; +} + +void Abstract3DController::addAxis(Q3DAbstractAxis *axis) +{ + Q_ASSERT(axis); + Abstract3DController *owner = qobject_cast<Abstract3DController *>(axis->parent()); + if (owner != this) { + Q_ASSERT_X(!owner, "addAxis", "Axis already attached to a graph."); + axis->setParent(this); + } + if (!m_axes.contains(axis)) + m_axes.append(axis); +} + +void Abstract3DController::releaseAxis(Q3DAbstractAxis *axis) +{ + if (axis && m_axes.contains(axis)) { + // Clear the default status from released default axes + if (axis->d_ptr->isDefaultAxis()) + axis->d_ptr->setDefaultAxis(false); + + // If the axis is in use, replace it with a temporary one + switch (axis->orientation()) { + case Q3DAbstractAxis::AxisOrientationX: + setAxisX(0); + break; + case Q3DAbstractAxis::AxisOrientationY: + setAxisY(0); + break; + case Q3DAbstractAxis::AxisOrientationZ: + setAxisZ(0); + break; + default: + break; + } + + m_axes.removeAll(axis); + axis->setParent(0); + } +} + +QList<Q3DAbstractAxis *> Abstract3DController::axes() const +{ + return m_axes; +} + +QAbstractDataProxy *Abstract3DController::activeDataProxy() const +{ + return m_data; +} + +void Abstract3DController::addDataProxy(QAbstractDataProxy *proxy) +{ + Q_ASSERT(proxy); + Abstract3DController *owner = qobject_cast<Abstract3DController *>(proxy->parent()); + if (owner != this) { + Q_ASSERT_X(!owner, "addDataProxy", "Proxy already attached to a graph."); + proxy->setParent(this); + } + if (!m_dataProxies.contains(proxy)) + m_dataProxies.append(proxy); +} + +void Abstract3DController::releaseDataProxy(QAbstractDataProxy *proxy) +{ + if (proxy && m_dataProxies.contains(proxy)) { + // Clear the default status from released default proxies + if (proxy->d_ptr->isDefaultProxy()) + proxy->d_ptr->setDefaultProxy(false); + + // If the proxy is in use, replace it with a temporary one + if (m_data == proxy) + setActiveDataProxy(0); + + m_dataProxies.removeAll(proxy); + proxy->setParent(0); + } +} + +QList<QAbstractDataProxy *> Abstract3DController::dataProxies() const +{ + return m_dataProxies; +} + +void Abstract3DController::setActiveDataProxy(QAbstractDataProxy *proxy) +{ + // If existing proxy is the default proxy, delete it + if (m_data) { + if (m_data->d_ptr->isDefaultProxy()) { + m_dataProxies.removeAll(m_data); + delete m_data; + } else { + // Disconnect the old proxy from use + QObject::disconnect(m_data, 0, this, 0); + } + } + + // Assume ownership and activate + addDataProxy(proxy); + m_data = proxy; + m_isDataDirty = true; + emitNeedRender(); +} + +void Abstract3DController::addInputHandler(QAbstract3DInputHandler *inputHandler) +{ + Q_ASSERT(inputHandler); + Abstract3DController *owner = qobject_cast<Abstract3DController *>(inputHandler->parent()); + if (owner != this) { + Q_ASSERT_X(!owner, "addInputHandler", "Input handler already attached to another component."); + inputHandler->setParent(this); + } + + if (!m_inputHandlers.contains(inputHandler)) + m_inputHandlers.append(inputHandler); +} + +void Abstract3DController::releaseInputHandler(QAbstract3DInputHandler *inputHandler) +{ + if (inputHandler && m_inputHandlers.contains(inputHandler)) { + // Clear the default status from released default input handler + if (inputHandler->d_ptr->m_isDefaultHandler) + inputHandler->d_ptr->m_isDefaultHandler = false; + + // If the input handler is in use, remove it + if (m_activeInputHandler == inputHandler) + setActiveInputHandler(0); + + m_inputHandlers.removeAll(inputHandler); + inputHandler->setParent(0); + } +} + +void Abstract3DController::setActiveInputHandler(QAbstract3DInputHandler *inputHandler) +{ + if (inputHandler == m_activeInputHandler) + return; + + // If existing input handler is the default input handler, delete it + if (m_activeInputHandler) { + if (m_activeInputHandler->d_ptr->m_isDefaultHandler) { + m_inputHandlers.removeAll(m_activeInputHandler); + delete m_activeInputHandler; + } else { + // Disconnect the old input handler from the scene + m_activeInputHandler->setScene(0); + } + } + + // Assume ownership and connect to this controller's scene + if (inputHandler) + addInputHandler(inputHandler); + + m_activeInputHandler = inputHandler; + if (m_activeInputHandler) + m_activeInputHandler->setScene(m_scene); + + // Notify change of input handler + emit activeInputHandlerChanged(m_activeInputHandler); +} + +QAbstract3DInputHandler* Abstract3DController::activeInputHandler() +{ + return m_activeInputHandler; +} + +int Abstract3DController::zoomLevel() +{ + return m_scene->activeCamera()->zoomLevel(); +} + +void Abstract3DController::setZoomLevel(int zoomLevel) +{ + m_scene->activeCamera()->setZoomLevel(zoomLevel); + + m_changeTracker.zoomLevelChanged = true; + emitNeedRender(); +} + +void Abstract3DController::setObjectColor(const QColor &baseColor, bool uniform) +{ + m_theme.m_baseColor = baseColor; + m_theme.m_uniformColor = uniform; + + m_changeTracker.themeChanged = true; + emitNeedRender(); +} + +QColor Abstract3DController::objectColor() const +{ + return m_theme.m_baseColor; +} + +void Abstract3DController::setTheme(QDataVis::Theme theme) +{ + m_theme.useTheme(theme); + + m_changeTracker.themeChanged = true; + emitNeedRender(); +} + +Theme Abstract3DController::theme() +{ + return m_theme; +} + +void Abstract3DController::setFont(const QFont &font) +{ + m_font = font; + + m_changeTracker.fontChanged = true; + emitNeedRender(); +} + +QFont Abstract3DController::font() +{ + return m_font; +} + +void Abstract3DController::setSelectionMode(QDataVis::SelectionMode mode) +{ + m_selectionMode = mode; + m_changeTracker.selectionModeChanged = true; + emitNeedRender(); +} + +QDataVis::SelectionMode Abstract3DController::selectionMode() +{ + return m_selectionMode; +} + +void Abstract3DController::setShadowQuality(QDataVis::ShadowQuality quality) +{ + m_shadowQuality = quality; + + m_changeTracker.shadowQualityChanged = true; + emit shadowQualityChanged(m_shadowQuality); + emitNeedRender(); +} + +QDataVis::ShadowQuality Abstract3DController::shadowQuality() +{ + return m_shadowQuality; +} + +void Abstract3DController::setLabelStyle(QDataVis::LabelStyle style) +{ + m_labelStyle = style; + + m_changeTracker.labelStyleChanged = true; + emitNeedRender(); +} + +QDataVis::LabelStyle Abstract3DController::labelStyle() +{ + return m_labelStyle; +} + +void Abstract3DController::setBackgroundEnabled(bool enable) +{ + m_isBackgroundEnabled = enable; + m_changeTracker.backgroundEnabledChanged = true; + emitNeedRender(); +} + +bool Abstract3DController::backgroundEnabled() +{ + return m_isBackgroundEnabled; +} + +void Abstract3DController::setGridEnabled(bool enable) +{ + m_isGridEnabled = enable; + m_changeTracker.gridEnabledChanged = true; + emitNeedRender(); +} + +bool Abstract3DController::gridEnabled() +{ + return m_isGridEnabled; +} + +bool Abstract3DController::isSlicingActive() +{ + return m_scene->isSlicingActive(); +} + +void Abstract3DController::setSlicingActive(bool isSlicing) +{ + m_scene->setSlicingActive(isSlicing); + emitNeedRender(); +} + +QDataVis::InputState Abstract3DController::inputState() +{ + if (m_activeInputHandler) + return m_activeInputHandler->inputState(); + else + return QDataVis::InputStateNone; +} + +QPoint Abstract3DController::inputPosition() +{ + if (m_activeInputHandler) + return m_activeInputHandler->inputPosition(); + else + return QPoint(0,0); +} + +void Abstract3DController::setMeshFileName(const QString &fileName) +{ + m_objFile = fileName; + m_changeTracker.objFileChanged = true; + emitNeedRender(); +} + +QString Abstract3DController::meshFileName() +{ + return m_objFile; +} + +Q3DScene *Abstract3DController::scene() +{ + return m_scene; +} + +void Abstract3DController::handleAxisTitleChanged(const QString &title) +{ + Q_UNUSED(title) + handleAxisTitleChangedBySender(sender()); +} + +void Abstract3DController::handleAxisTitleChangedBySender(QObject *sender) +{ + if (sender == m_axisX) + m_changeTracker.axisXTitleChanged = true; + else if (sender == m_axisY) + m_changeTracker.axisYTitleChanged = true; + else if (sender == m_axisZ) + m_changeTracker.axisZTitleChanged = true; + else + qWarning() << __FUNCTION__ << "invoked for invalid axis"; + emitNeedRender(); +} + +void Abstract3DController::handleAxisLabelsChanged() +{ + handleAxisLabelsChangedBySender(sender()); +} + +void Abstract3DController::handleAxisLabelsChangedBySender(QObject *sender) +{ + if (sender == m_axisX) + m_changeTracker.axisXLabelsChanged = true; + else if (sender == m_axisY) + m_changeTracker.axisYLabelsChanged = true; + else if (sender == m_axisZ) + m_changeTracker.axisZLabelsChanged = true; + else + qWarning() << __FUNCTION__ << "invoked for invalid axis"; + emitNeedRender(); +} + +void Abstract3DController::handleAxisRangeChanged(qreal min, qreal max) +{ + Q_UNUSED(min) + Q_UNUSED(max) + handleAxisRangeChangedBySender(sender()); +} + +void Abstract3DController::handleAxisRangeChangedBySender(QObject *sender) +{ + if (sender == m_axisX) { + m_isDataDirty = true; + m_changeTracker.axisXRangeChanged = true; + } else if (sender == m_axisY) { + m_isDataDirty = true; + m_changeTracker.axisYRangeChanged = true; + } else if (sender == m_axisZ) { + m_isDataDirty = true; + m_changeTracker.axisZRangeChanged = true; + } else { + qWarning() << __FUNCTION__ << "invoked for invalid axis"; + } + emitNeedRender(); +} + +void Abstract3DController::handleAxisSegmentCountChanged(int count) +{ + Q_UNUSED(count) + handleAxisSegmentCountChangedBySender(sender()); +} + +void Abstract3DController::handleAxisSegmentCountChangedBySender(QObject *sender) +{ + if (sender == m_axisX) + m_changeTracker.axisXSegmentCountChanged = true; + else if (sender == m_axisY) + m_changeTracker.axisYSegmentCountChanged = true; + else if (sender == m_axisZ) + m_changeTracker.axisZSegmentCountChanged = true; + else + qWarning() << __FUNCTION__ << "invoked for invalid axis"; + emitNeedRender(); +} + +void Abstract3DController::handleAxisSubSegmentCountChanged(int count) +{ + Q_UNUSED(count) + handleAxisSubSegmentCountChangedBySender(sender()); +} + +void Abstract3DController::handleAxisSubSegmentCountChangedBySender(QObject *sender) +{ + if (sender == m_axisX) + m_changeTracker.axisXSubSegmentCountChanged = true; + else if (sender == m_axisY) + m_changeTracker.axisYSubSegmentCountChanged = true; + else if (sender == m_axisZ) + m_changeTracker.axisZSubSegmentCountChanged = true; + else + qWarning() << __FUNCTION__ << "invoked for invalid axis"; + emitNeedRender(); +} + +void Abstract3DController::handleAxisAutoAdjustRangeChanged(bool autoAdjust) +{ + QObject *sender = QObject::sender(); + if (sender != m_axisX && sender != m_axisY && sender != m_axisZ) + return; + + Q3DAbstractAxis *axis = static_cast<Q3DAbstractAxis*>(sender); + handleAxisAutoAdjustRangeChangedInOrientation(axis->orientation(), autoAdjust); +} + +void Abstract3DController::handleAxisLabelFormatChanged(const QString &format) +{ + Q_UNUSED(format) + handleAxisLabelFormatChangedBySender(sender()); +} + +void Abstract3DController::handleAxisLabelFormatChangedBySender(QObject *sender) +{ + // Label format changing needs to dirty the data so that labels are reset. + if (sender == m_axisX) { + m_isDataDirty = true; + m_changeTracker.axisXLabelFormatChanged = true; + } else if (sender == m_axisY) { + m_isDataDirty = true; + m_changeTracker.axisYLabelFormatChanged = true; + } else if (sender == m_axisZ) { + m_isDataDirty = true; + m_changeTracker.axisZLabelFormatChanged = true; + } else { + qWarning() << __FUNCTION__ << "invoked for invalid axis"; + } + emitNeedRender(); +} + +void Abstract3DController::setAxisHelper(Q3DAbstractAxis::AxisOrientation orientation, + Q3DAbstractAxis *axis, Q3DAbstractAxis **axisPtr) +{ + // Setting null axis indicates using default axis + if (!axis) + axis = createDefaultAxis(orientation); + + // If old axis is default axis, delete it + Q3DAbstractAxis *oldAxis = *axisPtr; + if (oldAxis) { + if (oldAxis->d_ptr->isDefaultAxis()) { + m_axes.removeAll(oldAxis); + delete oldAxis; + oldAxis = 0; + } else { + // Disconnect the old axis from use + QObject::disconnect(oldAxis, 0, this, 0); + oldAxis->d_ptr->setOrientation(Q3DAbstractAxis::AxisOrientationNone); + } + } + + // Assume ownership + addAxis(axis); + + // Connect the new axis + *axisPtr = axis; + + axis->d_ptr->setOrientation(orientation); + + QObject::connect(axis, &Q3DAbstractAxis::titleChanged, + this, &Abstract3DController::handleAxisTitleChanged); + QObject::connect(axis, &Q3DAbstractAxis::labelsChanged, + this, &Abstract3DController::handleAxisLabelsChanged); + QObject::connect(axis, &Q3DAbstractAxis::rangeChanged, + this, &Abstract3DController::handleAxisRangeChanged); + QObject::connect(axis, &Q3DAbstractAxis::autoAdjustRangeChanged, + this, &Abstract3DController::handleAxisAutoAdjustRangeChanged); + + if (orientation == Q3DAbstractAxis::AxisOrientationX) + m_changeTracker.axisXTypeChanged = true; + else if (orientation == Q3DAbstractAxis::AxisOrientationY) + m_changeTracker.axisYTypeChanged = true; + else if (orientation == Q3DAbstractAxis::AxisOrientationZ) + m_changeTracker.axisZTypeChanged = true; + + handleAxisTitleChangedBySender(axis); + handleAxisLabelsChangedBySender(axis); + handleAxisRangeChangedBySender(axis); + handleAxisAutoAdjustRangeChangedInOrientation(axis->orientation(), + axis->isAutoAdjustRange()); + + if (axis->type() & Q3DAbstractAxis::AxisTypeValue) { + Q3DValueAxis *valueAxis = static_cast<Q3DValueAxis *>(axis); + QObject::connect(valueAxis, &Q3DValueAxis::segmentCountChanged, + this, &Abstract3DController::handleAxisSegmentCountChanged); + QObject::connect(valueAxis, &Q3DValueAxis::subSegmentCountChanged, + this, &Abstract3DController::handleAxisSubSegmentCountChanged); + QObject::connect(valueAxis, &Q3DValueAxis::labelFormatChanged, + this, &Abstract3DController::handleAxisLabelFormatChanged); + + handleAxisSegmentCountChangedBySender(valueAxis); + handleAxisSubSegmentCountChangedBySender(valueAxis); + handleAxisLabelFormatChangedBySender(valueAxis); + } +} + +Q3DAbstractAxis *Abstract3DController::createDefaultAxis(Q3DAbstractAxis::AxisOrientation orientation) +{ + Q_UNUSED(orientation) + + // The default default axis is a value axis. If the graph type has a different default axis + // for some orientation, this function needs to be overridden. + Q3DAbstractAxis *defaultAxis = createDefaultValueAxis(); + return defaultAxis; +} + +Q3DValueAxis *Abstract3DController::createDefaultValueAxis() +{ + // Default value axis has single segment, empty label format, and auto scaling + // TODO: Grid should be also hidden, but that is not currently controlled by axis + Q3DValueAxis *defaultAxis = new Q3DValueAxis; + defaultAxis->setSegmentCount(1); + defaultAxis->setSubSegmentCount(1); + defaultAxis->setAutoAdjustRange(true); + defaultAxis->setLabelFormat(QString()); + defaultAxis->d_ptr->setDefaultAxis(true); + + return defaultAxis; +} + +Q3DCategoryAxis *Abstract3DController::createDefaultCategoryAxis() +{ + // Default category axis has no labels + // TODO: Grid should be also hidden, but that is not currently controlled by axis. + Q3DCategoryAxis *defaultAxis = new Q3DCategoryAxis; + defaultAxis->setAutoAdjustRange(true); + defaultAxis->d_ptr->setDefaultAxis(true); + return defaultAxis; +} + +void Abstract3DController::emitNeedRender() +{ + if (!m_renderPending) { + emit needRender(); + m_renderPending = true; + } +} + +QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavis3d/engine/abstract3dcontroller_p.h b/src/datavisualization/engine/abstract3dcontroller_p.h index 8f21c97f..f17c6c4d 100644 --- a/src/datavis3d/engine/abstract3dcontroller_p.h +++ b/src/datavisualization/engine/abstract3dcontroller_p.h @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -20,7 +20,7 @@ // W A R N I N G // ------------- // -// This file is not part of the QtDataVis3D API. It exists purely as an +// 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. // @@ -29,16 +29,20 @@ #ifndef CONTROLLER3DBASE_H #define CONTROLLER3DBASE_H -#include <QObject> - -#include "datavis3dglobal_p.h" +#include "datavisualizationglobal_p.h" #include "theme_p.h" -#include "qabstractaxis.h" +#include "q3dabstractaxis.h" #include "drawer_p.h" +#include "qabstract3dinputhandler.h" +#include "qabstractdataproxy.h" +#include "q3dscene.h" +#include "q3dbox.h" + +#include <QObject> class QFont; -QT_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVISUALIZATION_BEGIN_NAMESPACE class CameraHelper; class Abstract3DRenderer; @@ -48,7 +52,7 @@ struct Abstract3DChangeBitField { bool zoomLevelChanged : 1; bool themeChanged : 1; bool fontChanged : 1; - bool labelTransparencyChanged : 1; + bool labelStyleChanged : 1; bool boundingRectChanged : 1; bool sizeChanged : 1; bool shadowQualityChanged : 1; @@ -74,13 +78,16 @@ struct Abstract3DChangeBitField { bool axisXSubSegmentCountChanged : 1; bool axisYSubSegmentCountChanged : 1; bool axisZSubSegmentCountChanged : 1; + bool axisXLabelFormatChanged : 1; + bool axisYLabelFormatChanged : 1; + bool axisZLabelFormatChanged : 1; Abstract3DChangeBitField() : positionChanged(true), zoomLevelChanged(true), themeChanged(true), fontChanged(true), - labelTransparencyChanged(true), + labelStyleChanged(true), boundingRectChanged(true), sizeChanged(true), shadowQualityChanged(true), @@ -105,12 +112,15 @@ struct Abstract3DChangeBitField { axisZSegmentCountChanged(true), axisXSubSegmentCountChanged(true), axisYSubSegmentCountChanged(true), - axisZSubSegmentCountChanged(true) + axisZSubSegmentCountChanged(true), + axisXLabelFormatChanged(true), + axisYLabelFormatChanged(true), + axisZLabelFormatChanged(true) { } }; -class QT_DATAVIS3D_EXPORT Abstract3DController : public QObject +class QT_DATAVISUALIZATION_EXPORT Abstract3DController : public QObject { Q_OBJECT @@ -140,22 +150,33 @@ private: QFont m_font; QDataVis::SelectionMode m_selectionMode; QDataVis::ShadowQuality m_shadowQuality; - QDataVis::LabelTransparency m_labelTransparency; + QDataVis::LabelStyle m_labelStyle; bool m_isBackgroundEnabled; bool m_isGridEnabled; QString m_objFile; + Q3DScene *m_scene; + protected: + QList<QAbstract3DInputHandler *> m_inputHandlers; // List of all added input handlers + QAbstract3DInputHandler *m_activeInputHandler; CameraHelper *m_cameraHelper; - int m_zoomLevel; - QAbstractAxis *m_axisX; - QAbstractAxis *m_axisY; - QAbstractAxis *m_axisZ; + // Active axes + Q3DAbstractAxis *m_axisX; + Q3DAbstractAxis *m_axisY; + Q3DAbstractAxis *m_axisZ; + + QList<Q3DAbstractAxis *> m_axes; // List of all added axes Abstract3DRenderer *m_renderer; bool m_isDataDirty; + QAbstractDataProxy *m_data; + QList<QAbstractDataProxy *> m_dataProxies; + + bool m_renderPending; + explicit Abstract3DController(QRect boundRect, QObject *parent = 0); - ~Abstract3DController(); + virtual ~Abstract3DController(); public: @@ -166,7 +187,6 @@ public: */ virtual void synchDataToRenderer(); - virtual void render(const GLuint defaultFboHandle = 0); /** @@ -188,38 +208,47 @@ public: virtual int x(); virtual void setY(const int y); virtual int y(); - virtual void setAxisX(QAbstractAxis *axis); - virtual QAbstractAxis *axisX(); - virtual void setAxisY(QAbstractAxis *axis); - virtual QAbstractAxis *axisY(); - virtual void setAxisZ(QAbstractAxis *axis); - virtual QAbstractAxis *axisZ(); + + virtual QRect primarySubViewport() const; + virtual void setPrimarySubViewport(const QRect &primarySubViewport); + + virtual QRect secondarySubViewport() const; + virtual void setSecondarySubViewport(const QRect &secondarySubViewport); + + virtual void setAxisX(Q3DAbstractAxis *axis); + virtual Q3DAbstractAxis *axisX(); + virtual void setAxisY(Q3DAbstractAxis *axis); + virtual Q3DAbstractAxis *axisY(); + virtual void setAxisZ(Q3DAbstractAxis *axis); + virtual Q3DAbstractAxis *axisZ(); + virtual void addAxis(Q3DAbstractAxis *axis); + virtual void releaseAxis(Q3DAbstractAxis *axis); + virtual QList<Q3DAbstractAxis *> axes() const; // Omits default axes + + virtual void addInputHandler(QAbstract3DInputHandler *inputHandler); + virtual void releaseInputHandler(QAbstract3DInputHandler *inputHandler); + virtual void setActiveInputHandler(QAbstract3DInputHandler *inputHandler); + virtual QAbstract3DInputHandler *activeInputHandler(); + + virtual QAbstractDataProxy *activeDataProxy() const; + virtual void addDataProxy(QAbstractDataProxy *proxy); + virtual void releaseDataProxy(QAbstractDataProxy *proxy); + virtual QList<QAbstractDataProxy *> dataProxies() const; + virtual void setActiveDataProxy(QAbstractDataProxy *proxy); + virtual void updateDevicePixelRatio(qreal ratio); virtual int zoomLevel(); virtual void setZoomLevel(int zoomLevel); - // Select preset camera placement - virtual void setCameraPreset(QDataVis::CameraPreset preset); - - // Set camera rotation if you don't want to use the presets (in horizontal (-180...180) and - // vertical (0...90) (or (-90...90) if there are negative values) angles and distance in - // percentage (10...500)) - virtual void setCameraPosition(GLfloat horizontal, GLfloat vertical, GLint distance = 100); - - // Set color if you don't want to use themes. Set uniform to false if you want the (height) - // color to change from bottom to top - virtual void setObjectColor(QColor baseColor, QColor heightColor, QColor depthColor, - bool uniform = true); + // Set color if you don't want to use themes. + virtual void setObjectColor(const QColor &baseColor, bool uniform = true); + virtual QColor objectColor() const; // Set theme (bar colors, shaders, window color, background colors, light intensity and text // colors are affected) - virtual void setColorTheme(QDataVis::ColorTheme colorTheme); + virtual void setTheme(QDataVis::Theme theme); virtual Theme theme(); - // Font size adjustment - virtual void setFontSize(float fontsize); - virtual float fontSize(); - // Set font virtual void setFont(const QFont &font); virtual QFont font(); @@ -232,9 +261,9 @@ public: virtual void setShadowQuality(QDataVis::ShadowQuality quality); virtual QDataVis::ShadowQuality shadowQuality(); - // Label transparency adjustment - virtual void setLabelTransparency(QDataVis::LabelTransparency transparency); - virtual QDataVis::LabelTransparency labelTransparency(); + // Label style adjustment + virtual void setLabelStyle(QDataVis::LabelStyle style); + virtual QDataVis::LabelStyle labelStyle(); // Enable or disable background mesh virtual void setBackgroundEnabled(bool enable); @@ -244,16 +273,36 @@ public: virtual void setGridEnabled(bool enable); virtual bool gridEnabled(); + // Query input state and position + QDataVis::InputState inputState(); + QPoint inputPosition(); + + // Enable or disable slicing mode + bool isSlicingActive(); + void setSlicingActive(bool isSlicing); + + // override bar type with own mesh virtual void setMeshFileName(const QString &fileName); virtual QString meshFileName(); - virtual void handleAxisTitleChangedBySender(QObject *sender, const QString &title); + Q3DScene *scene(); + + virtual void mouseDoubleClickEvent(QMouseEvent *event); + virtual void touchEvent(QTouchEvent *event); + virtual void mousePressEvent(QMouseEvent *event, const QPoint &mousePos); + virtual void mouseReleaseEvent(QMouseEvent *event, const QPoint &mousePos); + virtual void mouseMoveEvent(QMouseEvent *event, const QPoint &mousePos); + virtual void wheelEvent(QWheelEvent *event); + + virtual void handleAxisTitleChangedBySender(QObject *sender); virtual void handleAxisLabelsChangedBySender(QObject *sender); - virtual void handleAxisRangeChangedBySender(QObject *sender, qreal min, qreal max); - virtual void handleAxisSegmentCountChangedBySender(QObject *sender, int count); - virtual void handleAxisSubSegmentCountChangedBySender(QObject *sender, int count); - virtual void handleAxisAutoAdjustRangeChangedInOrientation(QAbstractAxis::AxisOrientation orientation, bool autoAdjust) = 0; + virtual void handleAxisRangeChangedBySender(QObject *sender); + virtual void handleAxisSegmentCountChangedBySender(QObject *sender); + virtual void handleAxisSubSegmentCountChangedBySender(QObject *sender); + virtual void handleAxisAutoAdjustRangeChangedInOrientation( + Q3DAbstractAxis::AxisOrientation orientation, bool autoAdjust) = 0; + virtual void handleAxisLabelFormatChangedBySender(QObject *sender); public slots: void handleAxisTitleChanged(const QString &title); @@ -262,32 +311,24 @@ public slots: void handleAxisSegmentCountChanged(int count); void handleAxisSubSegmentCountChanged(int count); void handleAxisAutoAdjustRangeChanged(bool autoAdjust); + void handleAxisLabelFormatChanged(const QString &format); signals: - void boundingRectChanged(QRect boundingRect); - void sizeChanged(QRect boundingRect); - void positionChanged(QRect boundingRect); - void zoomLevelChanged(int zoomLevel); - void themeChanged(Theme theme); - void fontChanged(QFont font); // TODO should be handled via axis?? What about font for selection label? void shadowQualityChanged(QDataVis::ShadowQuality quality); - void labelTransparencyChanged(QDataVis::LabelTransparency transparency); - void axisTypeChanged(QAbstractAxis::AxisOrientation orientation, QAbstractAxis::AxisType type); - void axisTitleChanged(QAbstractAxis::AxisOrientation orientation, QString title); - void axisLabelsChanged(QAbstractAxis::AxisOrientation orientation, QStringList labels); - void axisRangeChanged(QAbstractAxis::AxisOrientation orientation, qreal min, qreal max); - void axisSegmentCountChanged(QAbstractAxis::AxisOrientation orientation, int count); - void axisSubSegmentCountChanged(QAbstractAxis::AxisOrientation orientation, int count); - void selectionModeChanged(QDataVis::SelectionMode mode); - void backgroundEnabledChanged(bool enable); - void gridEnabledChanged(bool enable); // TODO: Should be handled via axes? - void meshFileNameChanged(QString fileName); + void activeInputHandlerChanged(QAbstract3DInputHandler *inputHandler); + void needRender(); + +protected: + virtual Q3DAbstractAxis *createDefaultAxis(Q3DAbstractAxis::AxisOrientation orientation); + Q3DValueAxis *createDefaultValueAxis(); + Q3DCategoryAxis *createDefaultCategoryAxis(); + void emitNeedRender(); private: - void setAxisHelper(QAbstractAxis::AxisOrientation orientation, QAbstractAxis *axis, - QAbstractAxis **axisPtr); + void setAxisHelper(Q3DAbstractAxis::AxisOrientation orientation, Q3DAbstractAxis *axis, + Q3DAbstractAxis **axisPtr); }; -QT_DATAVIS3D_END_NAMESPACE +QT_DATAVISUALIZATION_END_NAMESPACE #endif // CONTROLLER3DBASE_H diff --git a/src/datavisualization/engine/abstract3drenderer.cpp b/src/datavisualization/engine/abstract3drenderer.cpp new file mode 100644 index 00000000..eef810df --- /dev/null +++ b/src/datavisualization/engine/abstract3drenderer.cpp @@ -0,0 +1,313 @@ +/**************************************************************************** +** +** 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 "abstract3drenderer_p.h" +#include "q3dvalueaxis.h" +#include "texturehelper_p.h" +#include "utils_p.h" +#include "q3dscene_p.h" +#include "q3dcamera_p.h" +#include "q3dlight_p.h" + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +Abstract3DRenderer::Abstract3DRenderer(Abstract3DController *controller) + : QObject(0), + m_controller(controller), + m_hasNegativeValues(false), + m_cachedTheme(), + m_cachedFont(QFont(QStringLiteral("Arial"))), + m_cachedLabelStyle(QDataVis::LabelStyleFromTheme), + m_drawer(new Drawer(m_cachedTheme, m_cachedFont, m_cachedLabelStyle)), + m_cachedBoundingRect(QRect(0,0,0,0)), + m_cachedShadowQuality(QDataVis::ShadowQualityMedium), + m_autoScaleAdjustment(1.0f), + m_cachedSelectionMode(QDataVis::SelectionModeNone), + m_cachedIsGridEnabled(false), + m_cachedIsBackgroundEnabled(false), + m_cachedScene(new Q3DScene()) + #ifdef DISPLAY_RENDER_SPEED + , m_isFirstFrame(true), + m_numFrames(0) + #endif + +{ + QObject::connect(m_drawer, &Drawer::drawerChanged, this, &Abstract3DRenderer::updateTextures); + QObject::connect(this, &Abstract3DRenderer::needRender, m_controller, + &Abstract3DController::needRender, Qt::QueuedConnection); +} + +Abstract3DRenderer::~Abstract3DRenderer() +{ + delete m_drawer; + delete m_textureHelper; + delete m_cachedScene; +} + +void Abstract3DRenderer::initializeOpenGL() +{ + // Set OpenGL features + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LESS); + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); + +#if !defined(QT_OPENGL_ES_2) + glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); + glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); + glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST); +#endif + + m_textureHelper = new TextureHelper(); + m_drawer->initializeOpenGL(); + + axisCacheForOrientation(Q3DAbstractAxis::AxisOrientationX).setDrawer(m_drawer); + axisCacheForOrientation(Q3DAbstractAxis::AxisOrientationY).setDrawer(m_drawer); + axisCacheForOrientation(Q3DAbstractAxis::AxisOrientationZ).setDrawer(m_drawer); +} + +void Abstract3DRenderer::render(const GLuint defaultFboHandle) +{ +#ifdef DISPLAY_RENDER_SPEED + // For speed computation + if (m_isFirstFrame) { + m_lastFrameTime.start(); + m_isFirstFrame = false; + } + + // Measure speed (as milliseconds per frame) + m_numFrames++; + if (m_lastFrameTime.elapsed() >= 1000) { // print only if last measurement was more than 1s ago + qDebug() << qreal(m_lastFrameTime.elapsed()) / qreal(m_numFrames) << "ms/frame (=" << qreal(m_numFrames) << "fps)"; + m_numFrames = 0; + m_lastFrameTime.restart(); + } +#endif + + if (defaultFboHandle) { + glDepthMask(true); + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LESS); + glEnable(GL_CULL_FACE); + glCullFace(GL_BACK); + glDisable(GL_BLEND); // For QtQuick2 blending is enabled by default, but we don't want it to be + } + + glViewport(m_cachedScene->viewport().x(), + m_cachedScene->viewport().y(), + m_cachedScene->viewport().width(), + m_cachedScene->viewport().height()); + + QVector3D clearColor = Utils::vectorFromColor(m_cachedTheme.m_windowColor); + glClearColor(clearColor.x(), clearColor.y(), clearColor.z(), 1.0f); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); +} + +QString Abstract3DRenderer::generateValueLabel(const QString &format, qreal value) +{ + QString valueLabelFormat = format; + Utils::ParamType valueParamType = Utils::findFormatParamType(valueLabelFormat); + QByteArray valueFormatArray = valueLabelFormat.toUtf8(); + return Utils::formatLabel(valueFormatArray, valueParamType, value); +} + +void Abstract3DRenderer::updateDataModel(QAbstractDataProxy *dataProxy) +{ + m_cachedItemLabelFormat = dataProxy->itemLabelFormat(); +} + +QString Abstract3DRenderer::itemLabelFormat() const +{ + return m_cachedItemLabelFormat; +} + +void Abstract3DRenderer::updateBoundingRect(const QRect &boundingRect) +{ + m_cachedBoundingRect = boundingRect; + handleResize(); +} + +void Abstract3DRenderer::updatePosition(const QRect &boundingRect) +{ + m_cachedBoundingRect = boundingRect; +} + +void Abstract3DRenderer::updateTheme(Theme theme) +{ + m_cachedTheme.setFromTheme(theme); + + m_drawer->setTheme(m_cachedTheme); + // Re-initialize shaders + handleShadowQualityChange(); +} + +void Abstract3DRenderer::updateScene(Q3DScene *scene) +{ + // Synchronize the controller scene to that of the renderer, and vice versa. + // Controller scene had priority if both have changed same values. + scene->d_ptr->sync(*m_cachedScene->d_ptr); + m_cachedScene->d_ptr->sync(*scene->d_ptr); +} + +void Abstract3DRenderer::handleShadowQualityChange() +{ +#if !defined(QT_OPENGL_ES_2) + if (m_cachedShadowQuality > QDataVis::ShadowQualityNone) { + if (!m_cachedTheme.m_uniformColor) { + initShaders(QStringLiteral(":/shaders/vertexShadow"), + QStringLiteral(":/shaders/fragmentShadowNoTexColorOnY")); + } else { + initShaders(QStringLiteral(":/shaders/vertexShadow"), + QStringLiteral(":/shaders/fragmentShadowNoTex")); + } + initBackgroundShaders(QStringLiteral(":/shaders/vertexShadow"), + QStringLiteral(":/shaders/fragmentShadowNoTex")); + } else { + if (!m_cachedTheme.m_uniformColor) { + initShaders(QStringLiteral(":/shaders/vertex"), + QStringLiteral(":/shaders/fragmentColorOnY")); + } else { + initShaders(QStringLiteral(":/shaders/vertex"), + QStringLiteral(":/shaders/fragment")); + } + initBackgroundShaders(QStringLiteral(":/shaders/vertex"), + QStringLiteral(":/shaders/fragment")); + } +#else + if (!m_cachedTheme.m_uniformColor) { + initShaders(QStringLiteral(":/shaders/vertexES2"), + QStringLiteral(":/shaders/fragmentColorOnYES2")); + } else { + initShaders(QStringLiteral(":/shaders/vertexES2"), + QStringLiteral(":/shaders/fragmentES2")); + } + initBackgroundShaders(QStringLiteral(":/shaders/vertexES2"), + QStringLiteral(":/shaders/fragmentES2")); +#endif +} + +void Abstract3DRenderer::updateFont(const QFont &font) +{ + m_cachedFont = font; + m_drawer->setFont(font); +} + +void Abstract3DRenderer::updateLabelStyle(QDataVis::LabelStyle style) +{ + m_cachedLabelStyle = style; + m_drawer->setStyle(style); +} + +void Abstract3DRenderer::updateMeshFileName(const QString &objFileName) +{ + if (objFileName != m_cachedObjFile) { + m_cachedObjFile = objFileName; + loadMeshFile(); + } +} + +void Abstract3DRenderer::updateSelectionMode(QDataVis::SelectionMode mode) +{ + m_cachedSelectionMode = mode; +} + +void Abstract3DRenderer::updateGridEnabled(bool enable) +{ + m_cachedIsGridEnabled = enable; +} + +void Abstract3DRenderer::updateBackgroundEnabled(bool enable) +{ + m_cachedIsBackgroundEnabled = enable; +} + +void Abstract3DRenderer::handleResize() +{ + if (m_cachedBoundingRect.width() == 0 || m_cachedBoundingRect.height() == 0) + return; + // Calculate zoom level based on aspect ratio + GLfloat div; + GLfloat zoomAdjustment; + div = qMin(m_cachedBoundingRect.width(), m_cachedBoundingRect.height()); + zoomAdjustment = defaultRatio * ((m_cachedBoundingRect.width() / div) + / (m_cachedBoundingRect.height() / div)); + m_autoScaleAdjustment = qMin(zoomAdjustment, 1.0f); // clamp to 1.0f + + // Re-init selection buffer + initSelectionBuffer(); + +#if !defined(QT_OPENGL_ES_2) + // Re-init depth buffer + updateDepthBuffer(); +#endif +} + +void Abstract3DRenderer::updateAxisType(Q3DAbstractAxis::AxisOrientation orientation, Q3DAbstractAxis::AxisType type) +{ + axisCacheForOrientation(orientation).setType(type); +} + +void Abstract3DRenderer::updateAxisTitle(Q3DAbstractAxis::AxisOrientation orientation, const QString &title) +{ + axisCacheForOrientation(orientation).setTitle(title); +} + +void Abstract3DRenderer::updateAxisLabels(Q3DAbstractAxis::AxisOrientation orientation, const QStringList &labels) +{ + axisCacheForOrientation(orientation).setLabels(labels); +} + +void Abstract3DRenderer::updateAxisRange(Q3DAbstractAxis::AxisOrientation orientation, qreal min, qreal max) +{ + AxisRenderCache &cache = axisCacheForOrientation(orientation); + cache.setMin(min); + cache.setMax(max); +} + +void Abstract3DRenderer::updateAxisSegmentCount(Q3DAbstractAxis::AxisOrientation orientation, int count) +{ + axisCacheForOrientation(orientation).setSegmentCount(count); +} + +void Abstract3DRenderer::updateAxisSubSegmentCount(Q3DAbstractAxis::AxisOrientation orientation, int count) +{ + axisCacheForOrientation(orientation).setSubSegmentCount(count); +} + +void Abstract3DRenderer::updateAxisLabelFormat(Q3DAbstractAxis::AxisOrientation orientation, const QString &format) +{ + axisCacheForOrientation(orientation).setLabelFormat(format); +} + +AxisRenderCache &Abstract3DRenderer::axisCacheForOrientation(Q3DAbstractAxis::AxisOrientation orientation) +{ + switch (orientation) { + case Q3DAbstractAxis::AxisOrientationX: + return m_axisCacheX; + case Q3DAbstractAxis::AxisOrientationY: + return m_axisCacheY; + case Q3DAbstractAxis::AxisOrientationZ: + return m_axisCacheZ; + default: + qFatal("Abstract3DRenderer::axisCacheForOrientation"); + return m_axisCacheX; + } +} + + +QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavis3d/engine/abstract3drenderer_p.h b/src/datavisualization/engine/abstract3drenderer_p.h index 3c5d1388..1c61ac07 100644 --- a/src/datavis3d/engine/abstract3drenderer_p.h +++ b/src/datavisualization/engine/abstract3drenderer_p.h @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -20,7 +20,7 @@ // W A R N I N G // ------------- // -// This file is not part of the QtDataVis3D API. It exists purely as an +// 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. // @@ -31,87 +31,111 @@ #include <QtGui/QOpenGLFunctions> #include <QtGui/QFont> +#include <QTime> -#include "datavis3dglobal_p.h" +#include "datavisualizationglobal_p.h" #include "abstract3dcontroller_p.h" #include "axisrendercache_p.h" #include "qabstractdataproxy.h" -QT_DATAVIS3D_BEGIN_NAMESPACE +//#define DISPLAY_RENDER_SPEED + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +class TextureHelper; +class Theme; +class Drawer; class Abstract3DRenderer : public QObject, protected QOpenGLFunctions { -protected: + Q_OBJECT + +private: Abstract3DController *m_controller; - bool m_isInitialized; + +protected: bool m_hasNegativeValues; - QRect m_cachedBoundingRect; - QDataVis::ShadowQuality m_cachedShadowQuality; Theme m_cachedTheme; QFont m_cachedFont; - QDataVis::LabelTransparency m_cachedLabelTransparency; + QDataVis::LabelStyle m_cachedLabelStyle; Drawer *m_drawer; + QRect m_cachedBoundingRect; + QDataVis::ShadowQuality m_cachedShadowQuality; GLfloat m_autoScaleAdjustment; + QString m_cachedItemLabelFormat; QString m_cachedObjFile; QDataVis::SelectionMode m_cachedSelectionMode; bool m_cachedIsGridEnabled; bool m_cachedIsBackgroundEnabled; - int m_cachedZoomLevel; AxisRenderCache m_axisCacheX; AxisRenderCache m_axisCacheY; AxisRenderCache m_axisCacheZ; + TextureHelper *m_textureHelper; + Q3DBox m_boundingBox; - Abstract3DRenderer(Abstract3DController *controller); - virtual void initializeOpenGL(); + Q3DScene *m_cachedScene; + +#ifdef DISPLAY_RENDER_SPEED + bool m_isFirstFrame; + QTime m_lastFrameTime; + GLint m_numFrames; +#endif + + QString generateValueLabel(const QString &format, qreal value); public: - inline bool isInitialized() { return m_isInitialized; } + virtual ~Abstract3DRenderer(); - virtual void updateBoundingRect(const QRect boundingRect); - virtual void updatePosition(const QRect boundingRect); - virtual void handleResize(); + void updateDataModel(QAbstractDataProxy *dataProxy); + + virtual void render(GLuint defaultFboHandle); + + virtual void updateBoundingRect(const QRect &boundingRect); + virtual void updatePosition(const QRect &boundingRect); - virtual void updateZoomLevel(int newZoomLevel); virtual void updateTheme(Theme theme); virtual void updateFont(const QFont &font); - virtual void updateLabelTransparency(QDataVis::LabelTransparency transparency); + virtual void updateLabelStyle(QDataVis::LabelStyle style); virtual void updateSelectionMode(QDataVis::SelectionMode newMode); virtual void updateGridEnabled(bool enable); virtual void updateBackgroundEnabled(bool enable); virtual void updateMeshFileName(const QString &objFileName); - - virtual void handleShadowQualityChange(); - - void updateDataModel(QAbstractDataProxy *dataProxy); + virtual void updateScene(Q3DScene *scene); virtual QString itemLabelFormat() const; - virtual void requestSelectionAtPoint(const QPoint &point) = 0; virtual void updateTextures() = 0; virtual void initSelectionBuffer() = 0; + #if !defined(QT_OPENGL_ES_2) virtual void updateDepthBuffer() = 0; #endif virtual void updateShadowQuality(QDataVis::ShadowQuality quality) = 0; virtual void initShaders(const QString &vertexShader, const QString &fragmentShader) = 0; virtual void initBackgroundShaders(const QString &vertexShader, const QString &fragmentShader) = 0; - virtual void updateAxisType(QAbstractAxis::AxisOrientation orientation, QAbstractAxis::AxisType type); - virtual void updateAxisTitle(QAbstractAxis::AxisOrientation orientation, const QString &title); - virtual void updateAxisLabels(QAbstractAxis::AxisOrientation orientation, const QStringList &labels); - virtual void updateAxisRange(QAbstractAxis::AxisOrientation orientation, qreal min, qreal max); - virtual void updateAxisSegmentCount(QAbstractAxis::AxisOrientation orientation, int count); - virtual void updateAxisSubSegmentCount(QAbstractAxis::AxisOrientation orientation, int count); + virtual void updateAxisType(Q3DAbstractAxis::AxisOrientation orientation, Q3DAbstractAxis::AxisType type); + virtual void updateAxisTitle(Q3DAbstractAxis::AxisOrientation orientation, const QString &title); + virtual void updateAxisLabels(Q3DAbstractAxis::AxisOrientation orientation, const QStringList &labels); + virtual void updateAxisRange(Q3DAbstractAxis::AxisOrientation orientation, qreal min, qreal max); + virtual void updateAxisSegmentCount(Q3DAbstractAxis::AxisOrientation orientation, int count); + virtual void updateAxisSubSegmentCount(Q3DAbstractAxis::AxisOrientation orientation, int count); + virtual void updateAxisLabelFormat(Q3DAbstractAxis::AxisOrientation orientation, const QString &format); - AxisRenderCache &axisCacheForOrientation(QAbstractAxis::AxisOrientation orientation); +signals: + void needRender(); // Emit this if something in renderer causes need for another render pass. -public: - /** - * @brief render Implements OpenGL rendering that occurs in the rendering thread. - * @param defaultFboHandle Defaults FBO handle (defaults to 0). - */ - virtual void render(CameraHelper *camera, const GLuint defaultFboHandle) = 0; +protected: + Abstract3DRenderer(Abstract3DController *controller); + + virtual void initializeOpenGL(); + + virtual void handleShadowQualityChange(); + virtual void handleResize(); + virtual void loadMeshFile() = 0; + + AxisRenderCache &axisCacheForOrientation(Q3DAbstractAxis::AxisOrientation orientation); }; -QT_DATAVIS3D_END_NAMESPACE +QT_DATAVISUALIZATION_END_NAMESPACE #endif // ABSTRACT3DRENDERER_P_H diff --git a/src/datavis3d/engine/axisrendercache.cpp b/src/datavisualization/engine/axisrendercache.cpp index 4374d545..55ac0765 100644 --- a/src/datavis3d/engine/axisrendercache.cpp +++ b/src/datavisualization/engine/axisrendercache.cpp @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -18,15 +18,17 @@ #include "axisrendercache_p.h" #include "qmath.h" +#include <QFontMetrics> -QT_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVISUALIZATION_BEGIN_NAMESPACE AxisRenderCache::AxisRenderCache() - : m_type(QAbstractAxis::AxisTypeNone), + : m_type(Q3DAbstractAxis::AxisTypeNone), m_min(0.0), m_max(10.0), m_segmentCount(5), m_subSegmentCount(1), + m_font(QFont(QStringLiteral("Arial"))), m_drawer(0), m_segmentStep(10.0f), m_subSegmentStep(10.0f) @@ -42,21 +44,32 @@ AxisRenderCache::~AxisRenderCache() void AxisRenderCache::setDrawer(Drawer *drawer) { m_drawer = drawer; + m_font = m_drawer->font(); if (m_drawer) { QObject::connect(m_drawer, &Drawer::drawerChanged, this, &AxisRenderCache::updateTextures); updateTextures(); } } -void AxisRenderCache::setType(QAbstractAxis::AxisType type) +void AxisRenderCache::setType(Q3DAbstractAxis::AxisType type) { m_type = type; - // If type is set, it means completely new axis instance, so clear all generated label items. + // If type is set, it means completely new axis instance, so clear all old data + m_labels.clear(); + m_title.clear(); + m_min = 0.0; + m_max = 10.0; + m_segmentCount = 5; + m_subSegmentCount = 1; + m_labelFormat.clear(); + m_titleItem.clear(); foreach (LabelItem *label, m_labelItems) delete label; m_labelItems.clear(); + m_segmentStep = 10.0f; + m_subSegmentStep = 10.0f; } void AxisRenderCache::setTitle(const QString &title) @@ -80,14 +93,16 @@ void AxisRenderCache::setLabels(const QStringList &labels) m_labelItems.reserve(newSize); - if (m_drawer) { - for (int i = 0; i < newSize; i++) { - if (i >= oldSize) - m_labelItems.append(new LabelItem); + int widest = maxLabelWidth(labels); + + for (int i = 0; i < newSize; i++) { + if (i >= oldSize) + m_labelItems.append(new LabelItem); + if (m_drawer) { if (labels.at(i).isEmpty()) m_labelItems[i]->clear(); else if (i >= oldSize || labels.at(i) != m_labels.at(i)) - m_drawer->generateLabelItem(*m_labelItems[i], labels.at(i)); + m_drawer->generateLabelItem(*m_labelItems[i], labels.at(i), widest); } } m_labels = labels; @@ -120,16 +135,20 @@ void AxisRenderCache::setSubSegmentCount(int count) void AxisRenderCache::updateTextures() { + m_font = m_drawer->font(); + if (m_title.isEmpty()) m_titleItem.clear(); else m_drawer->generateLabelItem(m_titleItem, m_title); + int widest = maxLabelWidth(m_labels); + for (int i = 0; i < m_labels.size(); i++) { if (m_labels.at(i).isEmpty()) m_labelItems[i]->clear(); else - m_drawer->generateLabelItem(*m_labelItems[i], m_labels.at(i)); + m_drawer->generateLabelItem(*m_labelItems[i], m_labels.at(i), widest); } } @@ -150,4 +169,18 @@ void AxisRenderCache::updateSubSegmentStep() m_subSegmentStep = m_segmentStep; } -QT_DATAVIS3D_END_NAMESPACE +int AxisRenderCache::maxLabelWidth(const QStringList &labels) const +{ + int labelWidth = 0; + QFont labelFont = m_font; + labelFont.setPointSize(textureFontSize); + QFontMetrics labelFM(labelFont); + for (int i = 0; i < labels.size(); i++) { + int newWidth = labelFM.width(labels.at(i)); + if (labelWidth < newWidth) + labelWidth = newWidth; + } + return labelWidth; +} + +QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavis3d/engine/axisrendercache_p.h b/src/datavisualization/engine/axisrendercache_p.h index 4b38fa20..0bb1cf92 100644 --- a/src/datavis3d/engine/axisrendercache_p.h +++ b/src/datavisualization/engine/axisrendercache_p.h @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -20,7 +20,7 @@ // W A R N I N G // ------------- // -// This file is not part of the QtDataVis3D API. It exists purely as an +// 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. // @@ -29,12 +29,12 @@ #ifndef AXISRENDERCACHE_P_H #define AXISRENDERCACHE_P_H -#include "datavis3dglobal_p.h" +#include "datavisualizationglobal_p.h" #include "labelitem_p.h" -#include "qabstractaxis_p.h" +#include "q3dabstractaxis_p.h" #include "drawer_p.h" -QT_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVISUALIZATION_BEGIN_NAMESPACE class AxisRenderCache : public QObject { @@ -45,8 +45,8 @@ public: void setDrawer(Drawer *drawer); - void setType(QAbstractAxis::AxisType type); - inline QAbstractAxis::AxisType type() const { return m_type; } + void setType(Q3DAbstractAxis::AxisType type); + inline Q3DAbstractAxis::AxisType type() const { return m_type; } void setTitle(const QString &title); inline const QString &title() { return m_title; } void setLabels(const QStringList &labels); @@ -59,6 +59,8 @@ public: inline int segmentCount() const { return m_segmentCount; } void setSubSegmentCount(int count); inline int subSegmentCount() const { return m_subSegmentCount; } + inline void setLabelFormat(const QString &format) { m_labelFormat = format; } + inline const QString &labelFormat() { return m_labelFormat; } inline LabelItem &titleItem() { return m_titleItem; } inline QList<LabelItem *> &labelItems() { return m_labelItems; } @@ -71,15 +73,18 @@ public slots: private: void updateSegmentStep(); void updateSubSegmentStep(); + int maxLabelWidth(const QStringList &labels) const; // Cached axis values - QAbstractAxis::AxisType m_type; + Q3DAbstractAxis::AxisType m_type; QString m_title; QStringList m_labels; qreal m_min; qreal m_max; int m_segmentCount; int m_subSegmentCount; + QString m_labelFormat; + QFont m_font; // Renderer items Drawer *m_drawer; // Not owned @@ -91,6 +96,6 @@ private: Q_DISABLE_COPY(AxisRenderCache) }; -QT_DATAVIS3D_END_NAMESPACE +QT_DATAVISUALIZATION_END_NAMESPACE #endif diff --git a/src/datavisualization/engine/bars3dcontroller.cpp b/src/datavisualization/engine/bars3dcontroller.cpp new file mode 100644 index 00000000..50d8d030 --- /dev/null +++ b/src/datavisualization/engine/bars3dcontroller.cpp @@ -0,0 +1,428 @@ +/**************************************************************************** +** +** 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 "bars3dcontroller_p.h" +#include "bars3drenderer_p.h" +#include "camerahelper_p.h" +#include "q3dabstractaxis_p.h" +#include "q3dvalueaxis_p.h" +#include "q3dcategoryaxis_p.h" +#include "qbardataproxy_p.h" + +#include <QMatrix4x4> +#include <qmath.h> + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +Bars3DController::Bars3DController(QRect boundRect) + : Abstract3DController(boundRect), + m_selectedBarPos(noSelectionPoint()), + m_isBarSpecRelative(true), + m_barThicknessRatio(1.0f), + m_barSpacing(QSizeF(1.0, 1.0)), + m_renderer(0) +{ + // Default bar type; specific to bars + setBarType(QDataVis::MeshStyleBevelBars, false); + + setActiveDataProxy(0); + + // Setting a null axis creates a new default axis according to orientation and graph type. + // Note: These cannot be set in Abstract3DController constructor, as they will call virtual + // functions implemented by subclasses. + setAxisX(0); + setAxisY(0); + setAxisZ(0); +} + +Bars3DController::~Bars3DController() +{ +} + +void Bars3DController::initializeOpenGL() +{ + // Initialization is called multiple times when Qt Quick components are used + if (isInitialized()) + return; + + m_renderer = new Bars3DRenderer(this); + + setRenderer(m_renderer); + synchDataToRenderer(); + + QObject::connect(m_renderer, &Bars3DRenderer::selectedBarPosChanged, this, + &Bars3DController::handleSelectedBarPosChanged, Qt::QueuedConnection); + emitNeedRender(); +} + +void Bars3DController::synchDataToRenderer() +{ + Abstract3DController::synchDataToRenderer(); + + if (!isInitialized()) + return; + + // Notify changes to renderer + if (m_changeTracker.barSpecsChanged) { + m_renderer->updateBarSpecs(m_barThicknessRatio, m_barSpacing, m_isBarSpecRelative); + m_changeTracker.barSpecsChanged = false; + } + + if (m_changeTracker.selectedBarPosChanged) { + m_renderer->updateSelectedBarPos(m_selectedBarPos); + m_changeTracker.selectedBarPosChanged = false; + } + + if (m_isDataDirty) { + m_renderer->updateDataModel(static_cast<QBarDataProxy *>(m_data)); + m_isDataDirty = false; + } +} + +void Bars3DController::setActiveDataProxy(QAbstractDataProxy *proxy) +{ + // Setting null proxy indicates default proxy + if (!proxy) { + proxy = new QBarDataProxy; + proxy->d_ptr->setDefaultProxy(true); + } + + Q_ASSERT(proxy->type() == QAbstractDataProxy::DataTypeBar); + + Abstract3DController::setActiveDataProxy(proxy); + + QBarDataProxy *barDataProxy = static_cast<QBarDataProxy *>(m_data); + + QObject::connect(barDataProxy, &QBarDataProxy::arrayReset, this, + &Bars3DController::handleArrayReset); + QObject::connect(barDataProxy, &QBarDataProxy::rowsAdded, this, + &Bars3DController::handleRowsAdded); + QObject::connect(barDataProxy, &QBarDataProxy::rowsChanged, this, + &Bars3DController::handleRowsChanged); + QObject::connect(barDataProxy, &QBarDataProxy::rowsRemoved, this, + &Bars3DController::handleRowsRemoved); + QObject::connect(barDataProxy, &QBarDataProxy::rowsInserted, this, + &Bars3DController::handleRowsInserted); + QObject::connect(barDataProxy, &QBarDataProxy::itemChanged, this, + &Bars3DController::handleItemChanged); + QObject::connect(barDataProxy, &QBarDataProxy::rowLabelsChanged, this, + &Bars3DController::handleDataRowLabelsChanged); + QObject::connect(barDataProxy, &QBarDataProxy::columnLabelsChanged, this, + &Bars3DController::handleDataColumnLabelsChanged); + + scene()->setSlicingActive(false); + adjustAxisRanges(); + + // Always clear selection on proxy change + setSelectedBarPos(noSelectionPoint()); + + handleDataRowLabelsChanged(); + handleDataColumnLabelsChanged(); + m_isDataDirty = true; + emitNeedRender(); +} + +void Bars3DController::handleArrayReset() +{ + scene()->setSlicingActive(false); + adjustAxisRanges(); + m_isDataDirty = true; + // Clear selection unless still valid + setSelectedBarPos(m_selectedBarPos); + emitNeedRender(); +} + +void Bars3DController::handleRowsAdded(int startIndex, int count) +{ + Q_UNUSED(startIndex) + Q_UNUSED(count) + // TODO should update slice instead of deactivating? + scene()->setSlicingActive(false); + adjustAxisRanges(); + m_isDataDirty = true; + emitNeedRender(); +} + +void Bars3DController::handleRowsChanged(int startIndex, int count) +{ + Q_UNUSED(startIndex) + Q_UNUSED(count) + // TODO should update slice instead of deactivating? + scene()->setSlicingActive(false); + adjustAxisRanges(); + m_isDataDirty = true; + emitNeedRender(); +} + +void Bars3DController::handleRowsRemoved(int startIndex, int count) +{ + Q_UNUSED(startIndex) + Q_UNUSED(count) + // TODO should update slice instead of deactivating? + scene()->setSlicingActive(false); + adjustAxisRanges(); + m_isDataDirty = true; + + // Clear selection unless still valid + setSelectedBarPos(m_selectedBarPos); + + emitNeedRender(); +} + +void Bars3DController::handleRowsInserted(int startIndex, int count) +{ + Q_UNUSED(startIndex) + Q_UNUSED(count) + // TODO should update slice instead of deactivating? + scene()->setSlicingActive(false); + adjustAxisRanges(); + m_isDataDirty = true; + emitNeedRender(); +} + +void Bars3DController::handleItemChanged(int rowIndex, int columnIndex) +{ + Q_UNUSED(rowIndex) + Q_UNUSED(columnIndex) + // TODO should update slice instead of deactivating? + scene()->setSlicingActive(false); + adjustAxisRanges(); + m_isDataDirty = true; + emitNeedRender(); +} + +void Bars3DController::handleDataRowLabelsChanged() +{ + if (m_axisX && m_data) { + // Grab a sublist equal to data window (no need to have more labels in axis) + int min = int(m_axisX->min()); + int count = int(m_axisX->max()) - min + 1; + QStringList subList = static_cast<QBarDataProxy *>(m_data)->rowLabels().mid(min, count); + static_cast<Q3DCategoryAxis *>(m_axisX)->dptr()->setDataLabels(subList); + } +} + +void Bars3DController::handleDataColumnLabelsChanged() +{ + if (m_axisZ && m_data) { + // Grab a sublist equal to data window (no need to have more labels in axis) + int min = int(m_axisZ->min()); + int count = int(m_axisZ->max()) - min + 1; + QStringList subList = static_cast<QBarDataProxy *>(m_data)->columnLabels().mid(min, count); + static_cast<Q3DCategoryAxis *>(m_axisZ)->dptr()->setDataLabels(subList); + } +} + +void Bars3DController::handleSelectedBarPosChanged(const QPoint &position) +{ + QPoint pos = position; + if (pos == QPoint(255, 255)) + pos = noSelectionPoint(); + if (pos != m_selectedBarPos) { + m_selectedBarPos = pos; + emit selectedBarPosChanged(pos); + emitNeedRender(); + } +} + +void Bars3DController::handleAxisAutoAdjustRangeChangedInOrientation( + Q3DAbstractAxis::AxisOrientation orientation, bool autoAdjust) +{ + Q_UNUSED(orientation) + Q_UNUSED(autoAdjust) + adjustAxisRanges(); +} + +QPoint Bars3DController::noSelectionPoint() +{ + static QPoint noSelectionPos(-1, -1); + return noSelectionPos; +} + +void Bars3DController::setAxisX(Q3DAbstractAxis *axis) +{ + Abstract3DController::setAxisX(axis); + handleDataRowLabelsChanged(); +} + +void Bars3DController::setAxisZ(Q3DAbstractAxis *axis) +{ + Abstract3DController::setAxisZ(axis); + handleDataColumnLabelsChanged(); +} + +void Bars3DController::handleAxisRangeChangedBySender(QObject *sender) +{ + // Data window changed + if (sender == m_axisX || sender == m_axisZ) { + // Disable zoom mode if we're in it (causes crash if not, as zoom selection is deleted) + scene()->setSlicingActive(false); + + // Clear selection unless still valid + setSelectedBarPos(m_selectedBarPos); + + if (sender == m_axisX) + handleDataRowLabelsChanged(); + if (sender == m_axisZ) + handleDataColumnLabelsChanged(); + } + + Abstract3DController::handleAxisRangeChangedBySender(sender); +} + +void Bars3DController::setBarSpecs(GLfloat thicknessRatio, const QSizeF &spacing, bool relative) +{ + m_barThicknessRatio = thicknessRatio; + m_barSpacing = spacing; + m_isBarSpecRelative = relative; + + m_changeTracker.barSpecsChanged = true; + emitNeedRender(); +} + +GLfloat Bars3DController::barThickness() +{ + return m_barThicknessRatio; +} + +QSizeF Bars3DController::barSpacing() +{ + return m_barSpacing; +} + +bool Bars3DController::isBarSpecRelative() +{ + return m_isBarSpecRelative; +} + +void Bars3DController::setBarType(QDataVis::MeshStyle style, bool smooth) +{ + QString objFile; + if (style == QDataVis::MeshStyleBars) + objFile = QStringLiteral(":/defaultMeshes/bar"); + else if (style == QDataVis::MeshStylePyramids) + objFile = QStringLiteral(":/defaultMeshes/pyramid"); + else if (style == QDataVis::MeshStyleCones) + objFile = QStringLiteral(":/defaultMeshes/cone"); + else if (style == QDataVis::MeshStyleCylinders) + objFile = QStringLiteral(":/defaultMeshes/cylinder"); + else if (style == QDataVis::MeshStyleBevelBars) + objFile = QStringLiteral(":/defaultMeshes/bevelbar"); + + if (smooth) + objFile += QStringLiteral("Smooth"); + + Abstract3DController::setMeshFileName(objFile); +} + +void Bars3DController::setSelectionMode(QDataVis::SelectionMode mode) +{ + // Disable zoom if selection mode changes + scene()->setSlicingActive(false); + Abstract3DController::setSelectionMode(mode); +} + +void Bars3DController::setSelectedBarPos(const QPoint &position) +{ + // If the selection is outside data window or targets non-existent + // bar, clear selection instead. + QPoint pos = position; + + if (pos != noSelectionPoint()) { + int minRow = int(m_axisX->min()); + int maxRow = int(m_axisX->max()); + int minCol = int(m_axisZ->min()); + int maxCol = int(m_axisZ->max()); + + if (pos.x() < minRow || pos.x() > maxRow || pos.y() < minCol || pos.y() > maxCol + || pos.x() + minRow >= static_cast<QBarDataProxy *>(m_data)->rowCount() + || pos.y() + minCol >= static_cast<QBarDataProxy *>(m_data)->rowAt(pos.x())->size()) { + pos = noSelectionPoint(); + } + } + + if (pos != m_selectedBarPos) { + m_selectedBarPos = pos; + m_changeTracker.selectedBarPosChanged = true; + emit selectedBarPosChanged(pos); + emitNeedRender(); + } +} + +QPoint Bars3DController::selectedBarPos() const +{ + return m_selectedBarPos; +} + +void Bars3DController::adjustAxisRanges() +{ + const QBarDataProxy *proxy = static_cast<QBarDataProxy *>(m_data); + const QBarDataArray *array = proxy->array(); + + Q3DCategoryAxis *categoryAxisX = static_cast<Q3DCategoryAxis *>(m_axisX); + if (categoryAxisX && categoryAxisX->isAutoAdjustRange() && proxy) { + int rowCount = proxy->rowCount(); + if (rowCount) + rowCount--; + categoryAxisX->dptr()->setRange(0.0, qreal(rowCount)); + } + + Q3DCategoryAxis *categoryAxisZ = static_cast<Q3DCategoryAxis *>(m_axisZ); + if (categoryAxisZ && categoryAxisZ->isAutoAdjustRange() && proxy) { + int columnCount = 0; + for (int i = 0; i < array->size(); i++) { + if (columnCount < array->at(i)->size()) + columnCount = array->at(i)->size(); + } + if (columnCount) + columnCount--; + categoryAxisZ->dptr()->setRange(0.0, qreal(columnCount)); + } + + Q3DValueAxis *valueAxis = static_cast<Q3DValueAxis *>(m_axisY); + if (valueAxis && categoryAxisX && categoryAxisZ && valueAxis->isAutoAdjustRange() && proxy) { + QPair<GLfloat, GLfloat> limits = proxy->dptrc()->limitValues(categoryAxisX->min(), + categoryAxisX->max(), + categoryAxisZ->min(), + categoryAxisZ->max()); + if (limits.first < 0) { + // TODO: Currently we only support symmetric y-axis for bar graph if there are negative values + qreal maxAbs = qMax(qFabs(limits.first), qFabs(limits.second)); + // Call private implementation to avoid unsetting auto adjust flag + valueAxis->dptr()->setRange(-maxAbs, maxAbs); + } else if (limits.second == 0.0) { + valueAxis->dptr()->setRange(0.0, 1.0); // Only zero value values in data set, set range to something. + } else { + valueAxis->dptr()->setRange(0.0, limits.second); + } + } +} + +Q3DAbstractAxis *Bars3DController::createDefaultAxis(Q3DAbstractAxis::AxisOrientation orientation) +{ + Q3DAbstractAxis *defaultAxis = 0; + + if (orientation == Q3DAbstractAxis::AxisOrientationY) + defaultAxis = createDefaultValueAxis(); + else + defaultAxis = createDefaultCategoryAxis(); + + return defaultAxis; +} + +QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavis3d/engine/bars3dcontroller_p.h b/src/datavisualization/engine/bars3dcontroller_p.h index 9811eb0d..8398dd81 100644 --- a/src/datavis3d/engine/bars3dcontroller_p.h +++ b/src/datavisualization/engine/bars3dcontroller_p.h @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -20,7 +20,7 @@ // W A R N I N G // ------------- // -// This file is not part of the QtDataVis3D API. It exists purely as an +// 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. // @@ -29,106 +29,83 @@ #ifndef Q3DBARSCONTROLLER_p_H #define Q3DBARSCONTROLLER_p_H -#include "datavis3dglobal_p.h" +#include "datavisualizationglobal_p.h" #include "abstract3dcontroller_p.h" //#define DISPLAY_RENDER_SPEED -QT_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVISUALIZATION_BEGIN_NAMESPACE -class Bars3dRenderer; +class Bars3DRenderer; class QBarDataProxy; struct Bars3DChangeBitField { bool slicingActiveChanged : 1; - bool sampleSpaceChanged : 1; bool barSpecsChanged : 1; + bool selectedBarPosChanged : 1; Bars3DChangeBitField() : slicingActiveChanged(true), - sampleSpaceChanged(true), - barSpecsChanged(true) + barSpecsChanged(true), + selectedBarPosChanged(true) { } }; -class QT_DATAVIS3D_EXPORT Bars3dController : public Abstract3DController +class QT_DATAVISUALIZATION_EXPORT Bars3DController : public Abstract3DController { Q_OBJECT private: - - Bars3DChangeBitField m_changeTracker; - // Data - int m_rowCount; - int m_columnCount; - // Interaction - MouseState m_mouseState; - QPoint m_mousePos; - bool m_isSlicingActivated; + QPoint m_selectedBarPos; // Points to row & column in data window. // Look'n'feel bool m_isBarSpecRelative; - QSizeF m_barThickness; + GLfloat m_barThicknessRatio; QSizeF m_barSpacing; // Rendering - Bars3dRenderer *m_renderer; - QBarDataProxy *m_data; + Bars3DRenderer *m_renderer; public: - explicit Bars3dController(QRect rect); - ~Bars3dController(); + explicit Bars3DController(QRect rect); + ~Bars3DController(); void initializeOpenGL(); virtual void synchDataToRenderer(); - int columnCount(); - int rowCount(); - - MouseState mouseState(); - QPoint mousePosition(); - - bool isSlicingActive(); - void setSlicingActive(bool isSlicing); - - QMatrix4x4 calculateViewMatrix(int zoom, int viewPortWidth, int viewPortHeight, bool showUnder = false); - // bar thickness, spacing between bars, and is spacing relative to thickness or absolute // y -component sets the thickness/spacing of z -direction // With relative 0.0f means side-to-side, 1.0f = one thickness in between - void setBarSpecs(QSizeF thickness = QSizeF(1.0f, 1.0f), - QSizeF spacing = QSizeF(1.0f, 1.0f), + void setBarSpecs(GLfloat thicknessRatio = 1.0f, + const QSizeF &spacing = QSizeF(1.0, 1.0), bool relative = true); - QSizeF barThickness(); + GLfloat barThickness(); QSizeF barSpacing(); bool isBarSpecRelative(); // bar type; bars (=cubes), pyramids, cones, cylinders, etc. void setBarType(QDataVis::MeshStyle style, bool smooth = false); - // how many samples per row and column, and names for axes - void setupSampleSpace(int samplesRow, int samplesColumn); - // Change selection mode; single bar, bar and row, bar and column, or all void setSelectionMode(QDataVis::SelectionMode mode); -#if defined(Q_OS_ANDROID) - void mouseDoubleClickEvent(QMouseEvent *event); - void touchEvent(QTouchEvent *event); -#endif - void mousePressEvent(QMouseEvent *event, const QPoint &mousePos); - void mouseReleaseEvent(QMouseEvent *event, const QPoint &mousePos); - void mouseMoveEvent(QMouseEvent *event, const QPoint &mousePos); - void wheelEvent(QWheelEvent *event); + void setSelectedBarPos(const QPoint &position); + QPoint selectedBarPos() const; + + virtual void setActiveDataProxy(QAbstractDataProxy *proxy); + + virtual void handleAxisAutoAdjustRangeChangedInOrientation(Q3DAbstractAxis::AxisOrientation orientation, bool autoAdjust); - // Sets the data proxy. Assumes ownership of the data proxy. Deletes old proxy. - void setDataProxy(QBarDataProxy *proxy); - QBarDataProxy *dataProxy(); - virtual void handleAxisAutoAdjustRangeChangedInOrientation(QAbstractAxis::AxisOrientation orientation, bool autoAdjust); + static QPoint noSelectionPoint(); + + virtual void setAxisX(Q3DAbstractAxis *axis); + virtual void setAxisZ(Q3DAbstractAxis *axis); + + virtual void handleAxisRangeChangedBySender(QObject *sender); public slots: void handleArrayReset(); @@ -137,21 +114,25 @@ public slots: void handleRowsRemoved(int startIndex, int count); void handleRowsInserted(int startIndex, int count); void handleItemChanged(int rowIndex, int columnIndex); + void handleDataRowLabelsChanged(); + void handleDataColumnLabelsChanged(); + void handleSelectedBarPosChanged(const QPoint &position); signals: - void slicingActiveChanged(bool isSlicing); - void sampleSpaceChanged(int samplesRow, int samplesColumn); - void barSpecsChanged(QSizeF thickness, QSizeF spacing, bool relative); + void selectedBarPosChanged(QPoint position); + +protected: + virtual Q3DAbstractAxis *createDefaultAxis(Q3DAbstractAxis::AxisOrientation orientation); private: - void adjustValueAxisRange(); + void adjustAxisRanges(); - Q_DISABLE_COPY(Bars3dController) + Q_DISABLE_COPY(Bars3DController) }; -QT_DATAVIS3D_END_NAMESPACE +QT_DATAVISUALIZATION_END_NAMESPACE #endif diff --git a/src/datavis3d/engine/bars3drenderer.cpp b/src/datavisualization/engine/bars3drenderer.cpp index 81bad91f..74c1a99b 100644 --- a/src/datavis3d/engine/bars3drenderer.cpp +++ b/src/datavisualization/engine/bars3drenderer.cpp @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -18,7 +18,7 @@ #include "bars3drenderer_p.h" #include "bars3dcontroller_p.h" -#include "camerahelper_p.h" +#include "q3dcamera_p.h" #include "shaderhelper_p.h" #include "objecthelper_p.h" #include "texturehelper_p.h" @@ -26,6 +26,7 @@ #include "utils_p.h" #include "drawer_p.h" #include "qbardataitem.h" +#include "q3dlight.h" #include <QMatrix4x4> #include <QMouseEvent> @@ -33,30 +34,23 @@ #include <qmath.h> #include <QDebug> -// Commenting this draws the shadow map with perspective projection. Otherwise it's drawn in -// orthographic projection. -//#define USE_WIDER_SHADOWS - // You can verify that depth buffer drawing works correctly by uncommenting this. // You should see the scene from where the light is //#define SHOW_DEPTH_TEXTURE_SCENE -#ifdef DISPLAY_RENDER_SPEED -#include <QTime> -#endif - -QT_DATAVIS3D_BEGIN_NAMESPACE - -#define DISPLAY_FULL_DATA_ON_SELECTION // Append selection value text with row and column labels +QT_DATAVISUALIZATION_BEGIN_NAMESPACE +const GLfloat labelMargin = 0.05f; const GLfloat gridLineWidth = 0.005f; static QVector3D selectionSkipColor = QVector3D(255, 255, 255); // Selection texture's background color -Bars3dRenderer::Bars3dRenderer(Bars3dController *controller) +Bars3DRenderer::Bars3DRenderer(Bars3DController *controller) : Abstract3DRenderer(controller), m_controller(controller), + m_cachedIsSlicingActivated(false), + m_cachedRowCount(0), + m_cachedColumnCount(0), m_selectedBar(0), - m_previouslySelectedBar(0), m_sliceSelection(0), m_sliceCache(0), m_sliceTitleItem(0), @@ -79,7 +73,8 @@ Bars3dRenderer::Bars3dRenderer(Bars3dController *controller) m_depthFrameBuffer(0), m_selectionFrameBuffer(0), m_selectionDepthBuffer(0), - m_shadowQualityToShader(33.3f), + m_shadowQualityToShader(100.0f), + m_shadowQualityMultiplier(3), m_heightNormalizer(1.0f), m_yAdjustment(0.0f), m_rowWidth(0), @@ -90,18 +85,14 @@ Bars3dRenderer::Bars3dRenderer(Bars3dController *controller) m_scaleFactor(0), m_maxSceneSize(40.0), m_selection(selectionSkipColor), + m_previousSelection(selectionSkipColor), m_hasHeightAdjustmentChanged(true) - #ifdef DISPLAY_RENDER_SPEED - ,m_isFirstFrame(true), - m_numFrames(0) - #endif { - m_dummyBarRenderItem.setRenderer(this); initializeOpenGLFunctions(); initializeOpenGL(); } -Bars3dRenderer::~Bars3dRenderer() +Bars3DRenderer::~Bars3DRenderer() { m_textureHelper->glDeleteFramebuffers(1, &m_selectionFrameBuffer); m_textureHelper->glDeleteRenderbuffers(1, &m_selectionDepthBuffer); @@ -119,17 +110,17 @@ Bars3dRenderer::~Bars3dRenderer() delete m_barObj; delete m_backgroundObj; delete m_gridLineObj; - delete m_textureHelper; - delete m_drawer; + delete m_labelObj; + delete m_labelShader; } -void Bars3dRenderer::initializeOpenGL() +void Bars3DRenderer::initializeOpenGL() { - m_textureHelper = new TextureHelper(); - m_drawer->initializeOpenGL(); + Abstract3DRenderer::initializeOpenGL(); // Initialize shaders handleShadowQualityChange(); + initLabelShaders(QStringLiteral(":/shaders/vertexLabel"), QStringLiteral(":/shaders/fragmentLabel")); @@ -147,42 +138,59 @@ void Bars3dRenderer::initializeOpenGL() // Load label mesh loadLabelMesh(); - // Set OpenGL features - glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_LESS); - glEnable(GL_CULL_FACE); - glCullFace(GL_BACK); - -#if !defined(QT_OPENGL_ES_2) - glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); - glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); - glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST); -#endif - // Set view port glViewport(m_sliceViewPort.x(), m_sliceViewPort.y(), m_sliceViewPort.width(), m_sliceViewPort.height()); // Load background mesh (we need to be initialized first) loadBackgroundMesh(); - - Abstract3DRenderer::initializeOpenGL(); } -void Bars3dRenderer::updateDataModel(QBarDataProxy *dataProxy) +void Bars3DRenderer::updateDataModel(QBarDataProxy *dataProxy) { + int minRow = m_axisCacheX.min(); + int maxRow = m_axisCacheX.max(); + int minCol = m_axisCacheZ.min(); + int maxCol = m_axisCacheZ.max(); + int newRows = maxRow - minRow + 1; + int newColumns = maxCol - minCol + 1; + if (newRows != m_renderItemArray.size() || newColumns != m_renderItemArray.at(0).size()) { + // Destroy old render items and reallocate new array + m_renderItemArray.clear(); + m_renderItemArray.resize(newRows); + for (int i = 0; i < newRows; i++) + m_renderItemArray[i].resize(newColumns); + + // Force update for selection related items + m_sliceCache = 0; + m_sliceTitleItem = 0; + if (m_sliceSelection) + m_sliceSelection->clear(); + + m_cachedColumnCount = newColumns; + m_cachedRowCount = newRows; + // TODO: Invent foolproof max scene size formula + // This seems to work ok if spacing is not negative (and row/column or column/row ratio is not too high) + m_maxSceneSize = 2 * qSqrt(newColumns * newRows); + // Calculate here and at setting bar specs + calculateSceneScalingFactors(); + } + // Update cached data window int dataRowCount = dataProxy->rowCount(); - for (int i = 0; i < m_renderItemArray.size(); i++) { + int dataRowIndex = minRow; + for (int i = 0; i < newRows; i++) { int j = 0; - if (i < dataRowCount) { - const QBarDataRow *dataRow = dataProxy->rowAt(i); - int updateSize = qMin(dataRow->size(), m_renderItemArray[i].size()); + if (dataRowIndex < dataRowCount) { + const QBarDataRow *dataRow = dataProxy->rowAt(dataRowIndex); + int updateSize = qMin((dataRow->size() - minCol), m_renderItemArray[i].size()); if (dataRow) { + int dataColIndex = minCol; for (; j < updateSize ; j++) { - qreal value = dataRow->at(j).value(); + qreal value = dataRow->at(dataColIndex).value(); m_renderItemArray[i][j].setValue(value); - m_renderItemArray[i][j].setHeight(value / m_heightNormalizer); + m_renderItemArray[i][j].setHeight(GLfloat(value) / m_heightNormalizer); + dataColIndex++; } } } @@ -190,59 +198,63 @@ void Bars3dRenderer::updateDataModel(QBarDataProxy *dataProxy) m_renderItemArray[i][j].setValue(0.0); m_renderItemArray[i][j].setHeight(0.0f); } + dataRowIndex++; } Abstract3DRenderer::updateDataModel(dataProxy); } -void Bars3dRenderer::render(CameraHelper *camera, const GLuint defaultFboHandle) +void Bars3DRenderer::updateScene(Q3DScene *scene) { -#ifdef DISPLAY_RENDER_SPEED - // For speed computation - if (m_isFirstFrame) { - m_lastFrameTime.start(); - m_isFirstFrame = false; - } - - // Measure speed (as milliseconds per frame) - m_numFrames++; - if (m_lastFrameTime.elapsed() >= 1000) { // print only if last measurement was more than 1s ago - qDebug() << qreal(m_lastFrameTime.elapsed()) / qreal(m_numFrames) << "ms/frame (=" << qreal(m_numFrames) << "fps)"; - m_numFrames = 0; - m_lastFrameTime.restart(); - } -#endif - - if (defaultFboHandle) { - glDepthMask(true); - glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_LESS); - glEnable(GL_CULL_FACE); - glCullFace(GL_BACK); - } + // TODO: Move these to more suitable place e.g. controller should be controlling the viewports. + scene->setSecondarySubViewport(m_sliceViewPort); + scene->setPrimarySubViewport(m_mainViewPort); - QVector3D clearColor = Utils::vectorFromColor(m_cachedTheme.m_windowColor); - glClearColor(clearColor.x(), clearColor.y(), clearColor.z(), 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + // TODO: See QTRD-2374 + if (m_hasNegativeValues) + scene->activeCamera()->setMinYRotation(-90.0); + else + scene->activeCamera()->setMinYRotation(0.0); if (m_hasHeightAdjustmentChanged) { // Set initial camera position. Also update if height adjustment has changed. - camera->setDefaultCameraOrientation(QVector3D(0.0f, 0.0f, 6.0f + zComp), - QVector3D(0.0f, -m_yAdjustment, zComp), - QVector3D(0.0f, 1.0f, 0.0f)); + scene->activeCamera()->setBaseOrientation(QVector3D(0.0f, 0.0f, cameraDistance + zComp), + QVector3D(0.0f, -m_yAdjustment, zComp), + QVector3D(0.0f, 1.0f, 0.0f)); m_hasHeightAdjustmentChanged = false; } + scene->activeCamera()->d_ptr->updateViewMatrix(m_autoScaleAdjustment); + // Set light position (rotate light with camera, a bit above it (as set in defaultLightPos)) + scene->setLightPositionRelativeToCamera(defaultLightPos); + + Abstract3DRenderer::updateScene(scene); + + updateSlicingActive(scene->isSlicingActive()); +} + +void Bars3DRenderer::render(GLuint defaultFboHandle) +{ + bool slicingChanged = m_cachedIsSlicingActivated != m_cachedScene->isSlicingActive(); + + // Handle GL state setup for FBO buffers and clearing of the render surface + Abstract3DRenderer::render(defaultFboHandle); + // If slice selection is on, draw the sliced scene if (m_cachedIsSlicingActivated) - drawSlicedScene(camera, m_axisCacheX.titleItem(), m_axisCacheY.titleItem(), m_axisCacheZ.titleItem()); + drawSlicedScene(m_axisCacheX.titleItem(), m_axisCacheY.titleItem(), m_axisCacheZ.titleItem()); // Draw bars scene - drawScene(camera, defaultFboHandle); + drawScene(defaultFboHandle); + + // If slicing has been activated by this render pass, we need another render + // Also trigger another render always when slicing changes in general to ensure + // final draw is correct. + if (m_cachedIsSlicingActivated != m_cachedScene->isSlicingActive() || slicingChanged) + emit needRender(); } -void Bars3dRenderer::drawSlicedScene(CameraHelper *camera, - const LabelItem &xLabel, +void Bars3DRenderer::drawSlicedScene(const LabelItem &xLabel, const LabelItem &yLabel, const LabelItem &zLabel) { @@ -251,6 +263,11 @@ void Bars3dRenderer::drawSlicedScene(CameraHelper *camera, GLint stopBar = m_sliceSelection->size(); GLint stepBar = 1; QVector3D lightPos; + GLfloat negativesComp = 1.0f; + + // Compensate bar scaling a bit to avoid drawing on axis titles when we have negative values + if (m_hasNegativeValues) + negativesComp = 0.67f; // Specify viewport glViewport(m_sliceViewPort.x(), m_sliceViewPort.y(), @@ -261,39 +278,18 @@ void Bars3dRenderer::drawSlicedScene(CameraHelper *camera, projectionMatrix.perspective(45.0f, (GLfloat)m_sliceViewPort.width() / (GLfloat)m_sliceViewPort.height(), 0.1f, 100.0f); -#ifdef ROTATE_ZOOM_SELECTION - // Calculate view matrix - QMatrix4x4 viewMatrix = m_controller->calculateViewMatrix(m_cachedZoomLevel * m_autoScaleAdjustment, - m_sliceViewPort.width(), - m_sliceViewPort.height()); - - // Get light position (rotate light with camera, a bit above it (as set in defaultLightPos)) - lightPos = camera->calculateLightPosition(defaultLightPos); - - if (viewMatrix.row(0).z() <= 0) { - startBar = m_sliceSelection->size() - 1; - stopBar = -1; - stepBar = -1; - } -#else // Set view matrix QMatrix4x4 viewMatrix; // Adjust scaling (zoom rate based on aspect ratio) - GLfloat camPosZoomed = 5.0f / m_autoScaleAdjustment + zComp; + GLfloat camZPosSliced = 5.0f / m_autoScaleAdjustment + zComp; - viewMatrix.lookAt(QVector3D(0.0f, 0.0f, camPosZoomed), + viewMatrix.lookAt(QVector3D(0.0f, 0.0f, camZPosSliced), QVector3D(0.0f, 0.0f, zComp), QVector3D(0.0f, 1.0f, 0.0f)); - // Set light position a bit below the camera to reduce glare (depends on do we have row or column zoom) - QVector3D sliceLightPos = defaultLightPos; - sliceLightPos.setY(-10.0f); - if (QDataVis::ModeZoomColumn == m_cachedSelectionMode) - lightPos = camera->calculateLightPosition(sliceLightPos, -85.0f); - else - lightPos = camera->calculateLightPosition(sliceLightPos, 5.0f); -#endif + // Set light position + lightPos = QVector3D(0.0f, -m_yAdjustment, zComp); // Bind bar shader m_barShader->bind(); @@ -314,23 +310,37 @@ void Bars3dRenderer::drawSlicedScene(CameraHelper *camera, QMatrix4x4 MVPMatrix; QMatrix4x4 itModelMatrix; - GLfloat barPosY = item->translation().y() - m_yAdjustment / 2.0f + 0.2f; // we need some room for labels underneath; add +0.2f - if (QDataVis::ModeZoomRow == m_cachedSelectionMode) + GLfloat barPosY = negativesComp * item->translation().y() - m_yAdjustment / 2.0f + 0.2f; // we need some room for labels underneath; add +0.2f + if (QDataVis::SelectionModeSliceRow == m_cachedSelectionMode) barPosX = item->translation().x(); else barPosX = -(item->translation().z() - zComp); // flip z; frontmost bar to the left modelMatrix.translate(barPosX, barPosY, zComp); - modelMatrix.scale(QVector3D(m_scaleX, item->height(), m_scaleZ)); - itModelMatrix.scale(QVector3D(m_scaleX, item->height(), m_scaleZ)); + modelMatrix.scale(QVector3D(m_scaleX, negativesComp * item->height(), m_scaleZ)); + itModelMatrix.scale(QVector3D(m_scaleX, negativesComp * item->height(), m_scaleZ)); MVPMatrix = projectionMatrix * viewMatrix * modelMatrix; - QVector3D baseColor = Utils::vectorFromColor(m_cachedTheme.m_baseColor); - QVector3D heightColor = Utils::vectorFromColor(m_cachedTheme.m_heightColor) * item->height(); +#if 0 + QVector3D baseColor; + if (m_selection.x() == item->position().x() && m_selection.y() == item->position().y()) + baseColor = Utils::vectorFromColor(m_cachedTheme.m_highlightBarColor); + else if (QDataVis::SelectionModeSliceRow == m_cachedSelectionMode) + baseColor = Utils::vectorFromColor(m_cachedTheme.m_highlightRowColor); + else + baseColor = Utils::vectorFromColor(m_cachedTheme.m_highlightColumnColor); + QVector3D heightColor = Utils::vectorFromColor(m_cachedTheme.m_heightColor) * item->height(); QVector3D barColor = baseColor + heightColor; - - GLfloat lightStrength = m_cachedTheme.m_lightStrength; +#else + QVector3D barColor; + if (m_selection.x() == item->position().x() && m_selection.y() == item->position().y()) + barColor = Utils::vectorFromColor(m_cachedTheme.m_highlightBarColor); + else if (QDataVis::SelectionModeSliceRow == m_cachedSelectionMode) + barColor = Utils::vectorFromColor(m_cachedTheme.m_highlightRowColor); + else + barColor = Utils::vectorFromColor(m_cachedTheme.m_highlightColumnColor); +#endif if (item->height() != 0) { // Set shader bindings @@ -341,11 +351,16 @@ void Bars3dRenderer::drawSlicedScene(CameraHelper *camera, itModelMatrix.inverted().transposed()); m_barShader->setUniformValue(m_barShader->MVP(), MVPMatrix); m_barShader->setUniformValue(m_barShader->color(), barColor); - m_barShader->setUniformValue(m_barShader->lightS(), lightStrength); - m_barShader->setUniformValue(m_barShader->ambientS(), m_cachedTheme.m_ambientStrength); - + m_barShader->setUniformValue(m_barShader->lightS(), 0.5f); + m_barShader->setUniformValue(m_barShader->ambientS(), + m_cachedTheme.m_ambientStrength * 2.0f); // Draw the object +#if defined (Q_OS_MAC) + // Mac slice issue hack fix. TODO: Fix correctly + m_drawer->drawObject(m_barShader, m_barObj, 0, -1); +#else m_drawer->drawObject(m_barShader, m_barObj); +#endif } } @@ -357,86 +372,88 @@ void Bars3dRenderer::drawSlicedScene(CameraHelper *camera, glDisable(GL_DEPTH_TEST); glEnable(GL_TEXTURE_2D); glCullFace(GL_BACK); - if (m_cachedLabelTransparency > QDataVis::TransparencyNone) { - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - } + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // Draw labels for axes BarRenderItem *dummyItem(0); const LabelItem &sliceSelectionLabel = *m_sliceTitleItem; - if (QDataVis::ModeZoomRow == m_cachedSelectionMode) { + if (QDataVis::SelectionModeSliceRow == m_cachedSelectionMode) { if (m_sliceTitleItem) { m_drawer->drawLabel(*dummyItem, sliceSelectionLabel, viewMatrix, projectionMatrix, - QVector3D(0.0f, m_yAdjustment, zComp), + QVector3D(0.0f, m_autoScaleAdjustment, zComp), QVector3D(0.0f, 0.0f, 0.0f), 0, m_cachedSelectionMode, m_labelShader, - m_labelObj, camera, false, false, Drawer::LabelTop); + m_labelObj, m_cachedScene->activeCamera(), false, false, Drawer::LabelTop); } m_drawer->drawLabel(*dummyItem, zLabel, viewMatrix, projectionMatrix, - QVector3D(0.0f, m_yAdjustment, zComp), + QVector3D(0.0f, m_autoScaleAdjustment, zComp), QVector3D(0.0f, 0.0f, 0.0f), 0, m_cachedSelectionMode, m_labelShader, - m_labelObj, camera, false, false, Drawer::LabelBottom); + m_labelObj, m_cachedScene->activeCamera(), false, false, Drawer::LabelBottom); } else { m_drawer->drawLabel(*dummyItem, xLabel, viewMatrix, projectionMatrix, - QVector3D(0.0f, m_yAdjustment, zComp), + QVector3D(0.0f, m_autoScaleAdjustment, zComp), QVector3D(0.0f, 0.0f, 0.0f), 0, m_cachedSelectionMode, m_labelShader, - m_labelObj, camera, false, false, Drawer::LabelBottom); + m_labelObj, m_cachedScene->activeCamera(), false, false, Drawer::LabelBottom); if (m_sliceTitleItem) { m_drawer->drawLabel(*dummyItem, sliceSelectionLabel, viewMatrix, projectionMatrix, - QVector3D(0.0f, m_yAdjustment, zComp), + QVector3D(0.0f, m_autoScaleAdjustment, zComp), QVector3D(0.0f, 0.0f, 0.0f), 0, m_cachedSelectionMode, m_labelShader, - m_labelObj, camera, false, false, Drawer::LabelTop); + m_labelObj, m_cachedScene->activeCamera(), false, false, Drawer::LabelTop); } } m_drawer->drawLabel(*dummyItem, yLabel, viewMatrix, projectionMatrix, - QVector3D(0.0f, m_yAdjustment, zComp), + QVector3D(0.0f, m_autoScaleAdjustment, zComp), QVector3D(0.0f, 0.0f, 90.0f), 0, m_cachedSelectionMode, m_labelShader, - m_labelObj, camera, false, false, Drawer::LabelLeft); + m_labelObj, m_cachedScene->activeCamera(), false, false, Drawer::LabelLeft); // Draw labels for bars for (int col = 0; col < m_sliceSelection->size(); col++) { BarRenderItem *item = m_sliceSelection->at(col); // Draw values - m_drawer->drawLabel(*item, item->labelItem(), viewMatrix, projectionMatrix, - QVector3D(0.0f, m_yAdjustment, zComp), - QVector3D(0.0f, 0.0f, 0.0f), item->height(), - m_cachedSelectionMode, m_labelShader, - m_labelObj, camera); + if (negativesComp == 1.0f) { + m_drawer->drawLabel(*item, item->sliceLabelItem(), viewMatrix, projectionMatrix, + QVector3D(0.0f, m_yAdjustment, zComp), + QVector3D(0.0f, 0.0f, 90.0f), + item->height(), + m_cachedSelectionMode, m_labelShader, + m_labelObj, m_cachedScene->activeCamera(), false, false, + Drawer::LabelOver, Qt::AlignTop); + } else { + m_drawer->drawLabel(*item, item->sliceLabelItem(), viewMatrix, projectionMatrix, + QVector3D(0.0f, m_yAdjustment, zComp), + QVector3D(0.0f, 0.0f, 0.0f), + negativesComp * negativesComp * item->height(), + m_cachedSelectionMode, m_labelShader, + m_labelObj, m_cachedScene->activeCamera()); + } // Draw labels if (m_sliceCache->labelItems().size() > col) { const LabelItem *labelItem(0); - // If draw order of bars is flipped, label draw order should be too - if (m_xFlipped) { - labelItem = m_sliceCache->labelItems().at( - m_sliceCache->labelItems().size() - col - 1); - } else { - labelItem = m_sliceCache->labelItems().at(col); - } + labelItem = m_sliceCache->labelItems().at(col); m_drawer->drawLabel(*item, *labelItem, viewMatrix, projectionMatrix, - QVector3D(0.0f, m_yAdjustment, zComp), + QVector3D(0.0f, m_autoScaleAdjustment, zComp), QVector3D(0.0f, 0.0f, -45.0f), item->height(), m_cachedSelectionMode, m_labelShader, - m_labelObj, camera, false, false, Drawer::LabelBelow); + m_labelObj, m_cachedScene->activeCamera(), false, false, + Drawer::LabelBelow); } } glDisable(GL_TEXTURE_2D); - if (m_cachedLabelTransparency > QDataVis::TransparencyNone) - glDisable(GL_BLEND); + glDisable(GL_BLEND); glEnable(GL_DEPTH_TEST); // Release label shader m_labelShader->release(); } -void Bars3dRenderer::drawScene(CameraHelper *camera, - const GLuint defaultFboHandle) +void Bars3DRenderer::drawScene(GLuint defaultFboHandle) { GLint startBar = 0; GLint stopBar = 0; @@ -448,11 +465,9 @@ void Bars3dRenderer::drawScene(CameraHelper *camera, GLfloat backgroundRotation = 0; - GLfloat barPos = 0; + GLfloat colPos = 0; GLfloat rowPos = 0; - //m_selection = selectionSkipColor; - // Specify viewport glViewport(m_mainViewPort.x(), m_mainViewPort.y(), m_mainViewPort.width(), m_mainViewPort.height()); @@ -462,12 +477,8 @@ void Bars3dRenderer::drawScene(CameraHelper *camera, projectionMatrix.perspective(45.0f, (GLfloat)m_mainViewPort.width() / (GLfloat)m_mainViewPort.height(), 0.1f, 100.0f); - // Calculate view matrix - QMatrix4x4 viewMatrix = m_controller->calculateViewMatrix( - m_cachedZoomLevel * m_autoScaleAdjustment, - m_mainViewPort.width(), - m_mainViewPort.height(), - m_hasNegativeValues); + // Get the view matrix + QMatrix4x4 viewMatrix = m_cachedScene->activeCamera()->viewMatrix(); // Calculate drawing order // Draw order is reversed to optimize amount of drawing (ie. draw front objects first, depth test handles not needing to draw objects behind them) @@ -510,17 +521,16 @@ void Bars3dRenderer::drawScene(CameraHelper *camera, else if (viewMatrix.row(0).x() <= 0 && viewMatrix.row(0).z() <= 0) backgroundRotation = 0.0f; - // Get light position (rotate light with camera, a bit above it (as set in defaultLightPos)) - QVector3D lightPos = camera->calculateLightPosition(defaultLightPos); + // Get light position from the scene + QVector3D lightPos = m_cachedScene->activeLight()->position(); // Skip depth rendering if we're in slice mode - // TODO: Fix this, causes problems if depth rendering is off in slice mode // Introduce regardless of shadow quality to simplify logic QMatrix4x4 depthViewMatrix; QMatrix4x4 depthProjectionMatrix; #if !defined(QT_OPENGL_ES_2) - if (m_cachedShadowQuality > QDataVis::ShadowNone/*!m_cachedIsSlicingActivated*/) { + if (m_cachedShadowQuality > QDataVis::ShadowQualityNone && !m_cachedIsSlicingActivated) { // Render scene into a depth texture for using with shadow mapping // Enable drawing to depth framebuffer glBindFramebuffer(GL_FRAMEBUFFER, m_depthFrameBuffer); @@ -531,30 +541,24 @@ void Bars3dRenderer::drawScene(CameraHelper *camera, // Set viewport for depth map rendering. Must match texture size. Larger values give smoother shadows. glViewport(m_mainViewPort.x(), m_mainViewPort.y(), - m_mainViewPort.width() * m_cachedShadowQuality, - m_mainViewPort.height() * m_cachedShadowQuality); + m_mainViewPort.width() * m_shadowQualityMultiplier, + m_mainViewPort.height() * m_shadowQualityMultiplier); // Get the depth view matrix // It may be possible to hack lightPos here if we want to make some tweaks to shadow - QVector3D depthLightPos = camera->calculateLightPosition( + QVector3D depthLightPos = m_cachedScene->activeCamera()->calculatePositionRelativeToCamera( QVector3D(0.0f, 0.0f, zComp), 0.0f, 1.5f / m_autoScaleAdjustment); depthViewMatrix.lookAt(depthLightPos, QVector3D(0.0f, -m_yAdjustment, zComp), QVector3D(0.0f, 1.0f, 0.0f)); - // TODO: Why does depthViewMatrix.column(3).y() goes to zero when we're directly above? That causes the scene to be not drawn from above -> must be fixed - //qDebug() << lightPos << depthViewMatrix << depthViewMatrix.column(3); + + // TODO: Why does depthViewMatrix.column(3).y() goes to zero when we're directly above? + // That causes the scene to be not drawn from above -> must be fixed + // qDebug() << lightPos << depthViewMatrix << depthViewMatrix.column(3); + // Set the depth projection matrix -#ifndef USE_WIDER_SHADOWS - // Use this for perspective shadows - depthProjectionMatrix.perspective(15.0f, (GLfloat)m_mainViewPort.width() + depthProjectionMatrix.perspective(10.0f, (GLfloat)m_mainViewPort.width() / (GLfloat)m_mainViewPort.height(), 3.0f, 100.0f); -#else - // Use these for orthographic shadows - //GLfloat testAspectRatio = (GLfloat)m_mainViewPort.width() / (GLfloat)m_mainViewPort.height(); - //qDebug() << m_autoScaleAdjustment << m_yAdjustment; - depthProjectionMatrix.ortho(-2.0f * 2.0f, 2.0f * 2.0f, - -2.0f, 2.0f, - 0.0f, 100.0f); -#endif + // Draw bars to depth buffer for (int row = startRow; row != stopRow; row += stepRow) { for (int bar = startBar; bar != stopBar; bar += stepBar) { @@ -562,23 +566,33 @@ void Bars3dRenderer::drawScene(CameraHelper *camera, if (!item.value()) continue; - // Set front face culling for positive valued bars and back face culling for - // negative valued bars to reduce self-shadowing issues - if (item.height() < 0) + GLfloat shadowOffset = 0.0f; + + // Set front face culling for negative valued bars and back face culling for + // positive valued bars to remove peter-panning issues + if (item.height() > 0) { glCullFace(GL_BACK); - else + if (m_yFlipped) + shadowOffset = 0.015f; + } else { glCullFace(GL_FRONT); + if (!m_yFlipped) + shadowOffset = -0.015f; + } QMatrix4x4 modelMatrix; QMatrix4x4 MVPMatrix; - barPos = (bar + 1) * (m_cachedBarSpacing.width()); - rowPos = (row + 1) * (m_cachedBarSpacing.height()); + colPos = (bar + 0.5f) * (m_cachedBarSpacing.width()); + rowPos = (row + 0.5f) * (m_cachedBarSpacing.height()); - modelMatrix.translate((m_rowWidth - barPos) / m_scaleFactor, - item.height() - m_yAdjustment, + // Draw shadows for bars "on the other side" a bit off ground to avoid seeing + // shadows through the ground + modelMatrix.translate((colPos - m_rowWidth) / m_scaleFactor, + item.height() - m_yAdjustment + shadowOffset, (m_columnDepth - rowPos) / m_scaleFactor + zComp); - modelMatrix.scale(QVector3D(m_scaleX, item.height(), m_scaleZ)); + // Scale the bars down in X and Z to reduce self-shadowing issues + modelMatrix.scale(QVector3D(m_scaleX * 0.9f, item.height(), m_scaleZ * 0.9f)); MVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; @@ -639,7 +653,7 @@ void Bars3dRenderer::drawScene(CameraHelper *camera, #endif // Skip selection mode drawing if we're slicing or have no selection mode - if (!m_cachedIsSlicingActivated && m_cachedSelectionMode > QDataVis::ModeNone) { + if (!m_cachedIsSlicingActivated && m_cachedSelectionMode > QDataVis::SelectionModeNone) { // Bind selection shader m_selectionShader->bind(); @@ -664,10 +678,10 @@ void Bars3dRenderer::drawScene(CameraHelper *camera, QMatrix4x4 modelMatrix; QMatrix4x4 MVPMatrix; - barPos = (bar + 1) * (m_cachedBarSpacing.width()); - rowPos = (row + 1) * (m_cachedBarSpacing.height()); + colPos = (bar + 0.5f) * (m_cachedBarSpacing.width()); + rowPos = (row + 0.5f) * (m_cachedBarSpacing.height()); - modelMatrix.translate((m_rowWidth - barPos) / m_scaleFactor, + modelMatrix.translate((colPos - m_rowWidth) / m_scaleFactor, item.height() - m_yAdjustment, (m_columnDepth - rowPos) / m_scaleFactor + zComp); modelMatrix.scale(QVector3D(m_scaleX, item.height(), m_scaleZ)); @@ -711,16 +725,10 @@ void Bars3dRenderer::drawScene(CameraHelper *camera, glEnable(GL_DITHER); // Read color under cursor - if (Bars3dController::MouseOnScene == m_controller->mouseState()) - m_selection = Utils::getSelection(m_controller->mousePosition(), m_cachedBoundingRect.height()); - - QMutexLocker locker(&m_mutex); - if (m_isSelectionPointRequestActive) { - m_isSelectionPointRequestActive = false; - m_selection = Utils::getSelection(m_selectionPointRequest, m_cachedBoundingRect.height()); - emit selectionUpdated(m_selection); + if (QDataVis::InputStateOnScene == m_controller->inputState()) { + m_selection = Utils::getSelection(m_controller->inputPosition(), + m_cachedBoundingRect.height()); } - locker.unlock(); glBindFramebuffer(GL_FRAMEBUFFER, defaultFboHandle); @@ -752,13 +760,27 @@ void Bars3dRenderer::drawScene(CameraHelper *camera, // Bind bar shader m_barShader->bind(); - // Draw bars - if (!m_cachedIsSlicingActivated && m_sliceSelection) { - m_sliceSelection->clear(); // Slice doesn't own its items - m_sliceCache = 0; - m_sliceTitleItem = 0; + bool selectionDirty = (m_selection != m_previousSelection + || (m_selection != selectionSkipColor + && QDataVis::InputStateOnScene == m_controller->inputState() + && !m_cachedIsSlicingActivated)); + if (selectionDirty) { + m_previousSelection = m_selection; + if (m_sliceSelection) { + if (!m_cachedIsSlicingActivated) { + m_sliceCache = 0; + m_sliceTitleItem = 0; + } + if (m_sliceSelection->size()) { + // Slice doesn't own its items, no need to delete them - just clear + m_sliceSelection->clear(); + } + } } + + // Draw bars bool barSelectionFound = false; + BarRenderItem *selectedBar(0); for (int row = startRow; row != stopRow; row += stepRow) { for (int bar = startBar; bar != stopBar; bar += stepBar) { BarRenderItem &item = m_renderItemArray[row][bar]; @@ -773,9 +795,10 @@ void Bars3dRenderer::drawScene(CameraHelper *camera, QMatrix4x4 MVPMatrix; QMatrix4x4 depthMVPMatrix; - barPos = (bar + 1) * (m_cachedBarSpacing.width()); - rowPos = (row + 1) * (m_cachedBarSpacing.height()); - modelMatrix.translate((m_rowWidth - barPos) / m_scaleFactor, + colPos = (bar + 0.5f) * (m_cachedBarSpacing.width()); + rowPos = (row + 0.5f) * (m_cachedBarSpacing.height()); + + modelMatrix.translate((colPos - m_rowWidth) / m_scaleFactor, item.height() - m_yAdjustment, (m_columnDepth - rowPos) / m_scaleFactor + zComp); modelMatrix.scale(QVector3D(m_scaleX, item.height(), m_scaleZ)); @@ -787,69 +810,81 @@ void Bars3dRenderer::drawScene(CameraHelper *camera, #endif depthMVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; +#if 0 QVector3D baseColor = Utils::vectorFromColor(m_cachedTheme.m_baseColor); QVector3D heightColor = Utils::vectorFromColor(m_cachedTheme.m_heightColor) * item.height(); QVector3D depthColor = Utils::vectorFromColor(m_cachedTheme.m_depthColor) - * (float(row) / GLfloat(m_cachedRowCount)); + * (float(row) / GLfloat(m_cachedRowCount)); QVector3D barColor = baseColor + heightColor + depthColor; +#else + QVector3D barColor = Utils::vectorFromColor(m_cachedTheme.m_baseColor); +#endif GLfloat lightStrength = m_cachedTheme.m_lightStrength; - if (m_cachedSelectionMode > QDataVis::ModeNone) { - Bars3dController::SelectionType selectionType = isSelected(row, bar); + if (m_cachedSelectionMode > QDataVis::SelectionModeNone) { + Bars3DController::SelectionType selectionType = isSelected(row, bar); switch (selectionType) { - case Bars3dController::SelectionItem: { + case Bars3DController::SelectionItem: { barColor = Utils::vectorFromColor(m_cachedTheme.m_highlightBarColor); lightStrength = m_cachedTheme.m_highlightLightStrength; - // Insert data to QDataItem. We have no ownership, don't delete the previous one + // Insert position data into render item. We have no ownership, don't delete the previous one if (!m_cachedIsSlicingActivated) { - m_selectedBar = &item; - m_selectedBar->setPosition(QPoint(row, bar)); + selectedBar = &item; + selectedBar->setPosition(QPoint(row, bar)); item.setTranslation(modelMatrix.column(3).toVector3D()); barSelectionFound = true; - if (m_cachedSelectionMode >= QDataVis::ModeZoomRow) { - item.setTranslation(modelMatrix.column(3).toVector3D()); - m_sliceSelection->append(&item); + } + if (selectionDirty && m_cachedSelectionMode >= QDataVis::SelectionModeSliceRow) { + item.setTranslation(modelMatrix.column(3).toVector3D()); + item.setPosition(QPoint(row, bar)); + m_sliceSelection->append(&item); + barSelectionFound = true; + if (m_cachedSelectionMode == QDataVis::SelectionModeSliceRow) { + if (m_axisCacheX.labelItems().size() > row) + m_sliceTitleItem = m_axisCacheX.labelItems().at(row); + if (!m_sliceCache) { + // m_sliceCache is the axis for labels, while title comes from different axis. + m_sliceCache = &m_axisCacheZ; + } + } else if (m_cachedSelectionMode == QDataVis::SelectionModeSliceColumn) { + if (m_axisCacheZ.labelItems().size() > bar) + m_sliceTitleItem = m_axisCacheZ.labelItems().at(bar); + if (!m_sliceCache) { + // m_sliceCache is the axis for labels, while title comes from different axis. + m_sliceCache = &m_axisCacheX; + } } } break; } - case Bars3dController::SelectionRow: { + case Bars3DController::SelectionRow: { // Current bar is on the same row as the selected bar barColor = Utils::vectorFromColor(m_cachedTheme.m_highlightRowColor); lightStrength = m_cachedTheme.m_highlightLightStrength; - if (!m_cachedIsSlicingActivated && QDataVis::ModeZoomRow == m_cachedSelectionMode) { + if (QDataVis::SelectionModeSliceRow == m_cachedSelectionMode) { item.setTranslation(modelMatrix.column(3).toVector3D()); - m_sliceSelection->append(&item); - if (!m_sliceCache) { - // m_sliceCache is the axis for labels, while title comes from different axis. - m_sliceCache = &m_axisCacheZ; - if (m_axisCacheX.labelItems().size() > row) - m_sliceTitleItem = m_axisCacheX.labelItems().at(row); - } + item.setPosition(QPoint(row, bar)); + if (selectionDirty) + m_sliceSelection->append(&item); } break; } - case Bars3dController::SelectionColumn: { + case Bars3DController::SelectionColumn: { // Current bar is on the same column as the selected bar barColor = Utils::vectorFromColor(m_cachedTheme.m_highlightColumnColor); lightStrength = m_cachedTheme.m_highlightLightStrength; - if (!m_cachedIsSlicingActivated - && QDataVis::ModeZoomColumn == m_cachedSelectionMode) { + if (QDataVis::SelectionModeSliceColumn == m_cachedSelectionMode) { item.setTranslation(modelMatrix.column(3).toVector3D()); - m_sliceSelection->append(&item); - if (!m_sliceCache) { - // m_sliceCache is the axis for labels, while title comes from different axis. - m_sliceCache = &m_axisCacheX; - if (m_axisCacheZ.labelItems().size() > bar) - m_sliceTitleItem = m_axisCacheZ.labelItems().at(bar); - } + item.setPosition(QPoint(row, bar)); + if (selectionDirty) + m_sliceSelection->append(&item); } break; } - case Bars3dController::SelectionNone: { + case Bars3DController::SelectionNone: { // Current bar is not selected, nor on a row or column // do nothing break; @@ -870,7 +905,8 @@ void Bars3dRenderer::drawScene(CameraHelper *camera, m_barShader->setUniformValue(m_barShader->ambientS(), m_cachedTheme.m_ambientStrength); #if !defined(QT_OPENGL_ES_2) - if (m_cachedShadowQuality > QDataVis::ShadowNone) { + if (m_cachedShadowQuality > QDataVis::ShadowQualityNone + && !m_cachedIsSlicingActivated) { // Set shadow shader bindings m_barShader->setUniformValue(m_barShader->shadowQ(), m_shadowQualityToShader); m_barShader->setUniformValue(m_barShader->depth(), depthMVPMatrix); @@ -885,12 +921,20 @@ void Bars3dRenderer::drawScene(CameraHelper *camera, m_barShader->setUniformValue(m_barShader->lightS(), lightStrength); // Draw the object +#if defined (Q_OS_MAC) + // Mac slice issue hack fix. TODO: Fix correctly + m_drawer->drawObject(m_barShader, m_barObj, 0, -1); +#else m_drawer->drawObject(m_barShader, m_barObj); +#endif } } } } + if (selectionDirty) + emit selectedBarPosChanged(QPoint(int(m_selection.x()), int(m_selection.y()))); + // Release bar shader m_barShader->release(); @@ -939,7 +983,7 @@ void Bars3dRenderer::drawScene(CameraHelper *camera, m_cachedTheme.m_ambientStrength * 2.0f); #if !defined(QT_OPENGL_ES_2) - if (m_cachedShadowQuality > QDataVis::ShadowNone) { + if (m_cachedShadowQuality > QDataVis::ShadowQualityNone) { // Set shadow shader bindings m_backgroundShader->setUniformValue(m_backgroundShader->shadowQ(), m_shadowQualityToShader); @@ -975,15 +1019,16 @@ void Bars3dRenderer::drawScene(CameraHelper *camera, // Draw grid lines if (m_cachedIsGridEnabled && m_heightNormalizer) { + ShaderHelper *lineShader = m_backgroundShader; // Bind bar shader - m_barShader->bind(); + lineShader->bind(); // Set unchanging shader bindings QVector3D barColor = Utils::vectorFromColor(m_cachedTheme.m_gridLine); - m_barShader->setUniformValue(m_barShader->lightP(), lightPos); - m_barShader->setUniformValue(m_barShader->view(), viewMatrix); - m_barShader->setUniformValue(m_barShader->color(), barColor); - m_barShader->setUniformValue(m_barShader->ambientS(), m_cachedTheme.m_ambientStrength); + lineShader->setUniformValue(lineShader->lightP(), lightPos); + lineShader->setUniformValue(lineShader->view(), viewMatrix); + lineShader->setUniformValue(lineShader->color(), barColor); + lineShader->setUniformValue(lineShader->ambientS(), m_cachedTheme.m_ambientStrength); // Floor lines: rows for (GLfloat row = 0.0f; row <= m_cachedRowCount; row++) { @@ -992,7 +1037,7 @@ void Bars3dRenderer::drawScene(CameraHelper *camera, QMatrix4x4 depthMVPMatrix; QMatrix4x4 itModelMatrix; - rowPos = (row + 0.5f) * (m_cachedBarSpacing.height()); + rowPos = row * m_cachedBarSpacing.height(); modelMatrix.translate(0.0f, -m_yAdjustment, (m_columnDepth - rowPos) / m_scaleFactor + zComp); modelMatrix.scale(QVector3D(m_rowWidth / m_scaleFactor, gridLineWidth, @@ -1007,29 +1052,29 @@ void Bars3dRenderer::drawScene(CameraHelper *camera, depthMVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; // Set the rest of the shader bindings - m_barShader->setUniformValue(m_barShader->model(), modelMatrix); - m_barShader->setUniformValue(m_barShader->nModel(), - itModelMatrix.inverted().transposed()); - m_barShader->setUniformValue(m_barShader->MVP(), MVPMatrix); + lineShader->setUniformValue(lineShader->model(), modelMatrix); + lineShader->setUniformValue(lineShader->nModel(), + itModelMatrix.inverted().transposed()); + lineShader->setUniformValue(lineShader->MVP(), MVPMatrix); #if !defined(QT_OPENGL_ES_2) - if (m_cachedShadowQuality > QDataVis::ShadowNone) { + if (m_cachedShadowQuality > QDataVis::ShadowQualityNone) { // Set shadow shader bindings - m_barShader->setUniformValue(m_barShader->shadowQ(), m_shadowQualityToShader); - m_barShader->setUniformValue(m_barShader->depth(), depthMVPMatrix); - m_barShader->setUniformValue(m_barShader->lightS(), - m_cachedTheme.m_lightStrength / 10.0f); + lineShader->setUniformValue(lineShader->shadowQ(), m_shadowQualityToShader); + lineShader->setUniformValue(lineShader->depth(), depthMVPMatrix); + lineShader->setUniformValue(lineShader->lightS(), + m_cachedTheme.m_lightStrength / 10.0f); // Draw the object - m_drawer->drawObject(m_barShader, m_gridLineObj, 0, m_depthTexture); + m_drawer->drawObject(lineShader, m_gridLineObj, 0, m_depthTexture); } else #endif { // Set shadowless shader bindings - m_barShader->setUniformValue(m_barShader->lightS(), m_cachedTheme.m_lightStrength); + lineShader->setUniformValue(lineShader->lightS(), m_cachedTheme.m_lightStrength); // Draw the object - m_drawer->drawObject(m_barShader, m_gridLineObj); + m_drawer->drawObject(lineShader, m_gridLineObj); } } @@ -1040,8 +1085,8 @@ void Bars3dRenderer::drawScene(CameraHelper *camera, QMatrix4x4 depthMVPMatrix; QMatrix4x4 itModelMatrix; - barPos = (bar + 0.5f) * (m_cachedBarSpacing.width()); - modelMatrix.translate((m_rowWidth - barPos) / m_scaleFactor, + colPos = bar * m_cachedBarSpacing.width(); + modelMatrix.translate((m_rowWidth - colPos) / m_scaleFactor, -m_yAdjustment, zComp); modelMatrix.scale(QVector3D(gridLineWidth, gridLineWidth, m_columnDepth / m_scaleFactor)); @@ -1056,29 +1101,29 @@ void Bars3dRenderer::drawScene(CameraHelper *camera, depthMVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; // Set the rest of the shader bindings - m_barShader->setUniformValue(m_barShader->model(), modelMatrix); - m_barShader->setUniformValue(m_barShader->nModel(), - itModelMatrix.inverted().transposed()); - m_barShader->setUniformValue(m_barShader->MVP(), MVPMatrix); + lineShader->setUniformValue(lineShader->model(), modelMatrix); + lineShader->setUniformValue(lineShader->nModel(), + itModelMatrix.inverted().transposed()); + lineShader->setUniformValue(lineShader->MVP(), MVPMatrix); #if !defined(QT_OPENGL_ES_2) - if (m_cachedShadowQuality > QDataVis::ShadowNone) { + if (m_cachedShadowQuality > QDataVis::ShadowQualityNone) { // Set shadow shader bindings - m_barShader->setUniformValue(m_barShader->shadowQ(), m_shadowQualityToShader); - m_barShader->setUniformValue(m_barShader->depth(), depthMVPMatrix); - m_barShader->setUniformValue(m_barShader->lightS(), - m_cachedTheme.m_lightStrength / 10.0f); + lineShader->setUniformValue(lineShader->shadowQ(), m_shadowQualityToShader); + lineShader->setUniformValue(lineShader->depth(), depthMVPMatrix); + lineShader->setUniformValue(lineShader->lightS(), + m_cachedTheme.m_lightStrength / 10.0f); // Draw the object - m_drawer->drawObject(m_barShader, m_gridLineObj, 0, m_depthTexture); + m_drawer->drawObject(lineShader, m_gridLineObj, 0, m_depthTexture); } else #endif { // Set shadowless shader bindings - m_barShader->setUniformValue(m_barShader->lightS(), m_cachedTheme.m_lightStrength); + lineShader->setUniformValue(lineShader->lightS(), m_cachedTheme.m_lightStrength); // Draw the object - m_drawer->drawObject(m_barShader, m_gridLineObj); + m_drawer->drawObject(lineShader, m_gridLineObj); } } @@ -1115,29 +1160,29 @@ void Bars3dRenderer::drawScene(CameraHelper *camera, depthMVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; // Set the rest of the shader bindings - m_barShader->setUniformValue(m_barShader->model(), modelMatrix); - m_barShader->setUniformValue(m_barShader->nModel(), - itModelMatrix.inverted().transposed()); - m_barShader->setUniformValue(m_barShader->MVP(), MVPMatrix); + lineShader->setUniformValue(lineShader->model(), modelMatrix); + lineShader->setUniformValue(lineShader->nModel(), + itModelMatrix.inverted().transposed()); + lineShader->setUniformValue(lineShader->MVP(), MVPMatrix); #if !defined(QT_OPENGL_ES_2) - if (m_cachedShadowQuality > QDataVis::ShadowNone) { + if (m_cachedShadowQuality > QDataVis::ShadowQualityNone) { // Set shadow shader bindings - m_barShader->setUniformValue(m_barShader->shadowQ(), m_shadowQualityToShader); - m_barShader->setUniformValue(m_barShader->depth(), depthMVPMatrix); - m_barShader->setUniformValue(m_barShader->lightS(), - m_cachedTheme.m_lightStrength / 10.0f); + lineShader->setUniformValue(lineShader->shadowQ(), m_shadowQualityToShader); + lineShader->setUniformValue(lineShader->depth(), depthMVPMatrix); + lineShader->setUniformValue(lineShader->lightS(), + m_cachedTheme.m_lightStrength / 10.0f); // Draw the object - m_drawer->drawObject(m_barShader, m_gridLineObj, 0, m_depthTexture); + m_drawer->drawObject(lineShader, m_gridLineObj, 0, m_depthTexture); } else #endif { // Set shadowless shader bindings - m_barShader->setUniformValue(m_barShader->lightS(), m_cachedTheme.m_lightStrength); + lineShader->setUniformValue(lineShader->lightS(), m_cachedTheme.m_lightStrength); // Draw the object - m_drawer->drawObject(m_barShader, m_gridLineObj); + m_drawer->drawObject(lineShader, m_gridLineObj); } } @@ -1167,118 +1212,34 @@ void Bars3dRenderer::drawScene(CameraHelper *camera, depthMVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; // Set the rest of the shader bindings - m_barShader->setUniformValue(m_barShader->model(), modelMatrix); - m_barShader->setUniformValue(m_barShader->nModel(), - itModelMatrix.inverted().transposed()); - m_barShader->setUniformValue(m_barShader->MVP(), MVPMatrix); + lineShader->setUniformValue(lineShader->model(), modelMatrix); + lineShader->setUniformValue(lineShader->nModel(), + itModelMatrix.inverted().transposed()); + lineShader->setUniformValue(lineShader->MVP(), MVPMatrix); #if !defined(QT_OPENGL_ES_2) - if (m_cachedShadowQuality > QDataVis::ShadowNone) { + if (m_cachedShadowQuality > QDataVis::ShadowQualityNone) { // Set shadow shader bindings - m_barShader->setUniformValue(m_barShader->shadowQ(), m_shadowQualityToShader); - m_barShader->setUniformValue(m_barShader->depth(), depthMVPMatrix); - m_barShader->setUniformValue(m_barShader->lightS(), - m_cachedTheme.m_lightStrength / 10.0f); + lineShader->setUniformValue(lineShader->shadowQ(), m_shadowQualityToShader); + lineShader->setUniformValue(lineShader->depth(), depthMVPMatrix); + lineShader->setUniformValue(lineShader->lightS(), + m_cachedTheme.m_lightStrength / 10.0f); // Draw the object - m_drawer->drawObject(m_barShader, m_gridLineObj, 0, m_depthTexture); + m_drawer->drawObject(lineShader, m_gridLineObj, 0, m_depthTexture); } else #endif { // Set shadowless shader bindings - m_barShader->setUniformValue(m_barShader->lightS(), m_cachedTheme.m_lightStrength); + lineShader->setUniformValue(lineShader->lightS(), m_cachedTheme.m_lightStrength); // Draw the object - m_drawer->drawObject(m_barShader, m_gridLineObj); + m_drawer->drawObject(lineShader, m_gridLineObj); } } } // Release bar shader - m_barShader->release(); - } - - // Generate label textures for slice selection if m_updateLabels is set - if (m_cachedIsSlicingActivated && m_updateLabels) { - // Create label textures - for (int col = 0; col < m_sliceSelection->size(); col++) { - BarRenderItem *item = m_sliceSelection->at(col); - m_drawer->generateLabelTexture(item); - } - } - - // Handle slice activation and label drawing - if (!barSelectionFound) { - // We have no ownership, don't delete. Just NULL the pointer. - m_selectedBar = NULL; - if (m_cachedIsSlicingActivated - && Bars3dController::MouseOnOverview == m_controller->mouseState()) - m_controller->setSlicingActive(false); - } else if (m_cachedSelectionMode >= QDataVis::ModeZoomRow - && Bars3dController::MouseOnScene == m_controller->mouseState()) { - // Activate slice mode - m_controller->setSlicingActive(true); - - // Create label textures - for (int col = 0; col < m_sliceSelection->size(); col++) { - BarRenderItem *item = m_sliceSelection->at(col); - m_drawer->generateLabelTexture(item); - } - } else { - // Print value of selected bar - m_labelShader->bind(); - glDisable(GL_DEPTH_TEST); - glEnable(GL_TEXTURE_2D); - if (m_cachedLabelTransparency > QDataVis::TransparencyNone) { - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - } -#ifndef DISPLAY_FULL_DATA_ON_SELECTION - // Draw just the value string of the selected bar - if (m_previouslySelectedBar != m_selectedBar || m_updateLabels) { - m_drawer->generateLabelTexture(m_selectedBar); - m_previouslySelectedBar = m_selectedBar; - } - - m_drawer->drawLabel(*m_selectedBar, m_selectedBar->labelItem(), - viewMatrix, projectionMatrix, - QVector3D(0.0f, m_yAdjustment, zComp), - QVector3D(0.0f, 0.0f, 0.0f), m_selectedBar->height(), - m_cachedSelectionMode, m_labelShader, - m_labelObj, true); -#else - // Draw the value string followed by row label and column label - LabelItem &labelItem = m_selectedBar->selectionLabel(); - if (m_previouslySelectedBar != m_selectedBar || m_updateLabels || !labelItem.textureId()) { - QString labelText = m_selectedBar->label(); - if ((m_axisCacheZ.labels().size() > m_selectedBar->position().y()) - && (m_axisCacheX.labels().size() > m_selectedBar->position().x())) { - labelText.append(QStringLiteral(" (")); - labelText.append(m_axisCacheX.labels().at(m_selectedBar->position().x())); - labelText.append(QStringLiteral(", ")); - labelText.append(m_axisCacheZ.labels().at(m_selectedBar->position().y())); - labelText.append(QStringLiteral(")")); - //qDebug() << labelText; - } - m_drawer->generateLabelItem(labelItem, labelText); - m_previouslySelectedBar = m_selectedBar; - } - - m_drawer->drawLabel(*m_selectedBar, labelItem, viewMatrix, projectionMatrix, - QVector3D(0.0f, m_yAdjustment, zComp), - QVector3D(0.0f, 0.0f, 0.0f), m_selectedBar->height(), - m_cachedSelectionMode, m_labelShader, - m_labelObj, camera, true, false); -#endif - glDisable(GL_TEXTURE_2D); - if (m_cachedLabelTransparency > QDataVis::TransparencyNone) - glDisable(GL_BLEND); - glEnable(GL_DEPTH_TEST); - - // Release label shader - m_labelShader->release(); - - // Reset label update flag; they should have been updated when we get here - m_updateLabels = false; + lineShader->release(); } // TODO: Calculations done temporarily here. When optimizing, move to after data set addition? Keep drawing of the labels here. @@ -1286,18 +1247,16 @@ void Bars3dRenderer::drawScene(CameraHelper *camera, m_labelShader->bind(); glEnable(GL_TEXTURE_2D); - if (m_cachedLabelTransparency > QDataVis::TransparencyNone) { - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - } + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // Calculate the positions for row and column labels and store them for (int row = 0; row != m_cachedRowCount; row++) { if (m_axisCacheX.labelItems().size() > row) { // Go through all rows and get position of max+1 or min-1 column, depending on x flip // We need only positions for them, labels have already been generated at QDataSetPrivate. Just add LabelItems - rowPos = (row + 1) * (m_cachedBarSpacing.height()); - barPos = m_rowWidth; + rowPos = (row + 0.5f) * m_cachedBarSpacing.height(); + colPos = (m_rowWidth / m_scaleFactor) + labelMargin; GLfloat rotLabelX = -90.0f; GLfloat rotLabelY = 0.0f; GLfloat rotLabelZ = 0.0f; @@ -1305,7 +1264,7 @@ void Bars3dRenderer::drawScene(CameraHelper *camera, if (m_zFlipped) rotLabelY = 180.0f; if (m_xFlipped) { - barPos = -m_rowWidth; + colPos = -(m_rowWidth / m_scaleFactor) - labelMargin; alignment = Qt::AlignLeft; } if (m_yFlipped) { @@ -1315,7 +1274,7 @@ void Bars3dRenderer::drawScene(CameraHelper *camera, rotLabelY = 180.0f; rotLabelZ = 180.0f; } - QVector3D labelPos = QVector3D(barPos / m_scaleFactor, + QVector3D labelPos = QVector3D(colPos, -m_yAdjustment + 0.005f, // raise a bit over background to avoid depth "glimmering" (m_columnDepth - rowPos) / m_scaleFactor + zComp); @@ -1327,17 +1286,16 @@ void Bars3dRenderer::drawScene(CameraHelper *camera, QVector3D(0.0f, m_yAdjustment, zComp), QVector3D(rotLabelX, rotLabelY, rotLabelZ), 0, m_cachedSelectionMode, - m_labelShader, m_labelObj, camera, true, true, Drawer::LabelMid, + m_labelShader, m_labelObj, m_cachedScene->activeCamera(), true, true, Drawer::LabelMid, alignment); } - } - for (int bar = 0; bar != m_cachedColumnCount; bar += 1) { - if (m_axisCacheZ.labelItems().size() > bar) { + for (int column = 0; column != m_cachedColumnCount; column += 1) { + if (m_axisCacheZ.labelItems().size() > column) { // Go through all columns and get position of max+1 or min-1 row, depending on z flip // We need only positions for them, labels have already been generated at QDataSetPrivate. Just add LabelItems - barPos = (bar + 1) * (m_cachedBarSpacing.width()); - rowPos = m_columnDepth; + colPos = (column + 0.5f) * m_cachedBarSpacing.width(); + rowPos = (m_columnDepth / m_scaleFactor) + labelMargin; GLfloat rotLabelX = -90.0f; GLfloat rotLabelY = 90.0f; GLfloat rotLabelZ = 0.0f; @@ -1345,7 +1303,7 @@ void Bars3dRenderer::drawScene(CameraHelper *camera, if (m_xFlipped) rotLabelY = -90.0f; if (m_zFlipped) { - rowPos = -m_columnDepth; + rowPos = -(m_columnDepth / m_scaleFactor) - labelMargin; alignment = Qt::AlignRight; } if (m_yFlipped) { @@ -1355,21 +1313,18 @@ void Bars3dRenderer::drawScene(CameraHelper *camera, rotLabelY = 90.0f; rotLabelZ = 180.0f; } - QVector3D labelPos = QVector3D((m_rowWidth - barPos) / m_scaleFactor, + QVector3D labelPos = QVector3D((colPos - m_rowWidth) / m_scaleFactor, -m_yAdjustment + 0.005f, // raise a bit over background to avoid depth "glimmering" - rowPos / m_scaleFactor + zComp); - - // TODO: Try it; draw the label here + rowPos + zComp); m_dummyBarRenderItem.setTranslation(labelPos); - const LabelItem &axisLabelItem = *m_axisCacheZ.labelItems().at(bar); - //qDebug() << "labelPos, col" << bar + 1 << ":" << labelPos << m_axisCacheZ.labels().at(bar); + const LabelItem &axisLabelItem = *m_axisCacheZ.labelItems().at(column); m_drawer->drawLabel(m_dummyBarRenderItem, axisLabelItem, viewMatrix, projectionMatrix, QVector3D(0.0f, m_yAdjustment, zComp), QVector3D(rotLabelX, rotLabelY, rotLabelZ), 0, m_cachedSelectionMode, - m_labelShader, m_labelObj, camera, true, true, Drawer::LabelMid, + m_labelShader, m_labelObj, m_cachedScene->activeCamera(), true, true, Drawer::LabelMid, alignment); } } @@ -1385,6 +1340,8 @@ void Bars3dRenderer::drawScene(CameraHelper *camera, for (int i = 0; i < labelCount; i++) { if (m_axisCacheY.labelItems().size() > labelNbr) { + GLfloat labelMarginXTrans = labelMargin; + GLfloat labelMarginZTrans = labelMargin; GLfloat labelXTrans = m_rowWidth / m_scaleFactor; GLfloat labelZTrans = m_columnDepth / m_scaleFactor; GLfloat labelYTrans = 2.0f * labelPos / m_heightNormalizer - m_yAdjustment; @@ -1394,17 +1351,20 @@ void Bars3dRenderer::drawScene(CameraHelper *camera, Qt::AlignmentFlag alignment = Qt::AlignLeft; if (!m_xFlipped) { labelXTrans = -labelXTrans; + labelMarginXTrans = -labelMargin; rotLabelY = 90.0f; } if (m_zFlipped) { labelZTrans = -labelZTrans; + labelMarginZTrans = -labelMargin; alignment = Qt::AlignRight; } const LabelItem &axisLabelItem = *m_axisCacheY.labelItems().at(labelNbr); // Back wall - QVector3D labelTrans = QVector3D(labelXTrans, labelYTrans, labelZTrans + zComp); + QVector3D labelTrans = QVector3D(labelXTrans, labelYTrans, + labelZTrans + labelMarginZTrans + zComp); //qDebug() << "labelPos, value:" << labelTrans; @@ -1413,7 +1373,7 @@ void Bars3dRenderer::drawScene(CameraHelper *camera, QVector3D(0.0f, m_yAdjustment, zComp), QVector3D(rotLabelX, rotLabelY, rotLabelZ), 0, m_cachedSelectionMode, - m_labelShader, m_labelObj, camera, true, true, Drawer::LabelMid, + m_labelShader, m_labelObj, m_cachedScene->activeCamera(), true, true, Drawer::LabelMid, alignment); // Side wall @@ -1426,37 +1386,111 @@ void Bars3dRenderer::drawScene(CameraHelper *camera, else rotLabelY = 0.0f; - labelTrans = QVector3D(-labelXTrans, labelYTrans, -labelZTrans + zComp); + labelTrans = QVector3D(-labelXTrans - labelMarginXTrans, labelYTrans, + -labelZTrans + zComp); m_dummyBarRenderItem.setTranslation(labelTrans); m_drawer->drawLabel(m_dummyBarRenderItem, axisLabelItem, viewMatrix, projectionMatrix, QVector3D(0.0f, m_yAdjustment, zComp), QVector3D(rotLabelX, rotLabelY, rotLabelZ), 0, m_cachedSelectionMode, - m_labelShader, m_labelObj, camera, true, true, Drawer::LabelMid, + m_labelShader, m_labelObj, m_cachedScene->activeCamera(), true, true, Drawer::LabelMid, alignment); } labelNbr++; labelPos += heightStep; } + // Handle slice activation and selection label drawing + if (!barSelectionFound) { + // We have no ownership, don't delete. Just NULL the pointer. + m_selectedBar = NULL; + if (m_cachedIsSlicingActivated + && (m_selection == selectionSkipColor + || QDataVis::InputStateOnOverview == m_controller->inputState())) { + m_cachedScene->setSlicingActive(false); + } + } else if (m_cachedSelectionMode >= QDataVis::SelectionModeSliceRow && selectionDirty) { + // Activate slice mode + m_cachedScene->setSlicingActive(true); + + // Create label textures + for (int col = 0; col < m_sliceSelection->size(); col++) { + BarRenderItem *item = m_sliceSelection->at(col); + if (item->sliceLabel().isNull()) + item->setSliceLabel(generateValueLabel(m_axisCacheY.labelFormat(), item->value())); + m_drawer->generateLabelItem(item->sliceLabelItem(), item->sliceLabel()); + } + } else { + // Print value of selected bar + glDisable(GL_DEPTH_TEST); + // Draw the selection label + LabelItem &labelItem = selectedBar->selectionLabelItem(); + if (m_selectedBar != selectedBar || m_updateLabels || !labelItem.textureId()) { + QString labelText = selectedBar->selectionLabel(); + if (labelText.isNull()) { + static const QString rowIndexTag(QStringLiteral("@rowIdx")); + static const QString rowLabelTag(QStringLiteral("@rowLabel")); + static const QString rowTitleTag(QStringLiteral("@rowTitle")); + static const QString colIndexTag(QStringLiteral("@colIdx")); + static const QString colLabelTag(QStringLiteral("@colLabel")); + static const QString colTitleTag(QStringLiteral("@colTitle")); + static const QString valueTitleTag(QStringLiteral("@valueTitle")); + static const QString valueLabelTag(QStringLiteral("@valueLabel")); + + // Custom format expects printf format specifier. There is no tag for it. + labelText = generateValueLabel(itemLabelFormat(), selectedBar->value()); + + int selBarPosX = selectedBar->position().x(); + int selBarPosY = selectedBar->position().y(); + labelText.replace(rowIndexTag, QString::number(selBarPosX)); + if (m_axisCacheX.labels().size() > selBarPosX) + labelText.replace(rowLabelTag, m_axisCacheX.labels().at(selBarPosX)); + else + labelText.replace(rowLabelTag, QString()); + labelText.replace(rowTitleTag, m_axisCacheX.title()); + labelText.replace(colIndexTag, QString::number(selBarPosY)); + if (m_axisCacheZ.labels().size() > selBarPosY) + labelText.replace(colLabelTag, m_axisCacheZ.labels().at(selBarPosY)); + else + labelText.replace(colLabelTag, QString()); + labelText.replace(colTitleTag, m_axisCacheZ.title()); + labelText.replace(valueTitleTag, m_axisCacheY.title()); + + if (labelText.contains(valueLabelTag)) { + QString labelFormat = m_axisCacheY.labelFormat(); + if (labelFormat.isEmpty()) + labelFormat = Utils::defaultLabelFormat(); + QString valueLabelText = generateValueLabel(labelFormat, selectedBar->value()); + labelText.replace(valueLabelTag, valueLabelText); + } + + selectedBar->setSelectionLabel(labelText); + } + m_drawer->generateLabelItem(labelItem, labelText); + m_selectedBar = selectedBar; + } + + m_drawer->drawLabel(*selectedBar, labelItem, viewMatrix, projectionMatrix, + QVector3D(0.0f, m_yAdjustment, zComp), + QVector3D(0.0f, 0.0f, 0.0f), selectedBar->height(), + m_cachedSelectionMode, m_labelShader, + m_labelObj, m_cachedScene->activeCamera(), true, false); + + // Reset label update flag; they should have been updated when we get here + m_updateLabels = false; + + glEnable(GL_DEPTH_TEST); + } + glDisable(GL_TEXTURE_2D); - if (m_cachedLabelTransparency > QDataVis::TransparencyNone) - glDisable(GL_BLEND); + glDisable(GL_BLEND); // Release label shader m_labelShader->release(); } -void Bars3dRenderer::requestSelectionAtPoint(const QPoint &point) -{ - QMutexLocker locker(&m_mutex); - m_selectionPointRequest.setX(point.x()); - m_selectionPointRequest.setY(point.y()); - m_isSelectionPointRequestActive = true; -} - -void Bars3dRenderer::handleResize() +void Bars3DRenderer::handleResize() { if (m_cachedBoundingRect.width() == 0 || m_cachedBoundingRect.height() == 0) return; @@ -1467,121 +1501,121 @@ void Bars3dRenderer::handleResize() m_cachedBoundingRect.height() - m_cachedBoundingRect.height() / 5, m_cachedBoundingRect.width() / 5, m_cachedBoundingRect.height() / 5); + m_sliceViewPort = QRect(0, 0, m_cachedBoundingRect.width(), m_cachedBoundingRect.height()); } else { m_mainViewPort = QRect(0, 0, m_cachedBoundingRect.width(), m_cachedBoundingRect.height()); + m_sliceViewPort = QRect(0, 0, 0, 0); } - m_sliceViewPort = QRect(0, 0, m_cachedBoundingRect.width(), m_cachedBoundingRect.height()); Abstract3DRenderer::handleResize(); } -void Bars3dRenderer::updateBarSpecs(QSizeF thickness, QSizeF spacing, bool relative) +void Bars3DRenderer::updateBarSpecs(GLfloat thicknessRatio, const QSizeF &spacing, bool relative) { - m_cachedBarThickness = thickness; + // Convert ratio to QSizeF, as we need it in that format for autoscaling calculations + m_cachedBarThickness.setWidth(1.0f); + m_cachedBarThickness.setHeight(1.0f / thicknessRatio); + if (relative) { - m_cachedBarSpacing.setWidth((thickness.width() * 2) * (spacing.width() + 1.0f)); - m_cachedBarSpacing.setHeight((thickness.height() * 2) * (spacing.height() + 1.0f)); + m_cachedBarSpacing.setWidth((m_cachedBarThickness.width() * 2) * (spacing.width() + 1.0f)); + m_cachedBarSpacing.setHeight((m_cachedBarThickness.height() * 2) * (spacing.height() + 1.0f)); } else { - m_cachedBarSpacing = thickness * 2 + spacing * 2; + m_cachedBarSpacing = m_cachedBarThickness * 2 + spacing * 2; } // Calculate here and at setting sample space calculateSceneScalingFactors(); } -void Bars3dRenderer::updateMeshFileName(const QString &objFileName) -{ - Abstract3DRenderer::updateMeshFileName(objFileName); - loadBarMesh(); -} - -void Bars3dRenderer::updateAxisRange(QAbstractAxis::AxisOrientation orientation, qreal min, qreal max) +void Bars3DRenderer::updateAxisRange(Q3DAbstractAxis::AxisOrientation orientation, qreal min, qreal max) { Abstract3DRenderer::updateAxisRange(orientation, min, max); - calculateHeightAdjustment(); - - // Check if we have negative values - if (min < 0 && !m_hasNegativeValues) { - m_hasNegativeValues = true; - // Reload background - loadBackgroundMesh(); - } else if (min >= 0 && m_hasNegativeValues) { - m_hasNegativeValues = false; - // Reload background - loadBackgroundMesh(); - } - // TODO Currently barchart only supports zero centered or zero minimum ranges - if (min > 0.0 || (min != 0.0 && (qFabs(min) != qFabs(max)))) - qWarning() << __FUNCTION__ << "Bar chart currently properly supports only zero-centered and zero minimum ranges for Y-axis."; -} + if (orientation == Q3DAbstractAxis::AxisOrientationY) { + calculateHeightAdjustment(); + // Check if we have negative values + if (min < 0 && !m_hasNegativeValues) { + m_hasNegativeValues = true; + // Reload background + loadBackgroundMesh(); + emit needRender(); + } else if (min >= 0 && m_hasNegativeValues) { + m_hasNegativeValues = false; + // Reload background + loadBackgroundMesh(); + emit needRender(); + } -void Bars3dRenderer::updateSampleSpace(int rowCount, int columnCount) -{ - // Destroy old render items and reallocate new array - // TODO is there a way to allocate the whole array with one allocation? - m_renderItemArray.clear(); - m_renderItemArray.resize(rowCount); - for (int i = 0; i < rowCount; i++) { - m_renderItemArray[i].resize(columnCount); - for (int j = 0; j < columnCount; j++) - m_renderItemArray[i][j].setRenderer(this); + // TODO Currently bargraph only supports zero centered or zero minimum ranges + if (min > 0.0 || (min != 0.0 && (qFabs(min) != qFabs(max)))) { + qWarning() << __FUNCTION__ << "Bar graph currently properly supports only " + "zero-centered and zero minimum ranges for Y-axis."; + } } - - // Force update for selection related items - m_sliceCache = 0; - m_sliceTitleItem = 0; - if (m_sliceSelection) - m_sliceSelection->clear(); - - m_cachedColumnCount = columnCount; - m_cachedRowCount = rowCount; - // TODO: Invent "idiotproof" max scene size formula.. - // This seems to work ok if spacing is not negative (and row/column or column/row ratio is not too high) - m_maxSceneSize = 2 * qSqrt(columnCount * rowCount); - //qDebug() << "maxSceneSize" << m_maxSceneSize; - // Calculate here and at setting bar specs - calculateSceneScalingFactors(); } -void Bars3dRenderer::updateSelectionMode(QDataVis::SelectionMode mode) +void Bars3DRenderer::updateSelectionMode(QDataVis::SelectionMode mode) { Abstract3DRenderer::updateSelectionMode(mode); // Create zoom selection if there isn't one - if (mode >= QDataVis::ModeZoomRow && !m_sliceSelection) { + if (mode >= QDataVis::SelectionModeSliceRow && !m_sliceSelection) { m_sliceSelection = new QList<BarRenderItem *>; - if (mode == QDataVis::ModeZoomRow) + if (mode == QDataVis::SelectionModeSliceRow) m_sliceSelection->reserve(m_cachedRowCount); else m_sliceSelection->reserve(m_cachedColumnCount); } } -void Bars3dRenderer::updateBackgroundEnabled(bool enable) +void Bars3DRenderer::updateBackgroundEnabled(bool enable) { if (enable != m_cachedIsBackgroundEnabled) { Abstract3DRenderer::updateBackgroundEnabled(enable); - loadBarMesh(); // Load changed bar type + loadMeshFile(); // Load changed bar type } } -void Bars3dRenderer::updateShadowQuality(QDataVis::ShadowQuality quality) +void Bars3DRenderer::updateSelectedBarPos(const QPoint &position) +{ + if (position == Bars3DController::noSelectionPoint()) + m_selection = selectionSkipColor; + else + m_selection = QVector3D(position.x(), position.y(), 0); + emit needRender(); +} + +void Bars3DRenderer::updateShadowQuality(QDataVis::ShadowQuality quality) { - qDebug() << __FUNCTION__ << quality; m_cachedShadowQuality = quality; switch (quality) { - case QDataVis::ShadowLow: + case QDataVis::ShadowQualityLow: m_shadowQualityToShader = 33.3f; + m_shadowQualityMultiplier = 1; break; - case QDataVis::ShadowMedium: + case QDataVis::ShadowQualityMedium: m_shadowQualityToShader = 100.0f; + m_shadowQualityMultiplier = 3; break; - case QDataVis::ShadowHigh: + case QDataVis::ShadowQualityHigh: m_shadowQualityToShader = 200.0f; + m_shadowQualityMultiplier = 5; + break; + case QDataVis::ShadowQualitySoftLow: + m_shadowQualityToShader = 7.5f; + m_shadowQualityMultiplier = 1; + break; + case QDataVis::ShadowQualitySoftMedium: + m_shadowQualityToShader = 10.0f; + m_shadowQualityMultiplier = 3; + break; + case QDataVis::ShadowQualitySoftHigh: + m_shadowQualityToShader = 15.0f; + m_shadowQualityMultiplier = 4; break; default: m_shadowQualityToShader = 0.0f; + m_shadowQualityMultiplier = 1; break; } @@ -1593,7 +1627,7 @@ void Bars3dRenderer::updateShadowQuality(QDataVis::ShadowQuality quality) #endif } -void Bars3dRenderer::loadBarMesh() +void Bars3DRenderer::loadMeshFile() { QString objectFileName = m_cachedObjFile; if (m_barObj) @@ -1605,7 +1639,7 @@ void Bars3dRenderer::loadBarMesh() m_barObj->load(); } -void Bars3dRenderer::loadBackgroundMesh() +void Bars3DRenderer::loadBackgroundMesh() { if (m_backgroundObj) delete m_backgroundObj; @@ -1616,7 +1650,7 @@ void Bars3dRenderer::loadBackgroundMesh() m_backgroundObj->load(); } -void Bars3dRenderer::loadGridLineMesh() +void Bars3DRenderer::loadGridLineMesh() { if (m_gridLineObj) delete m_gridLineObj; @@ -1624,7 +1658,7 @@ void Bars3dRenderer::loadGridLineMesh() m_gridLineObj->load(); } -void Bars3dRenderer::loadLabelMesh() +void Bars3DRenderer::loadLabelMesh() { if (m_labelObj) delete m_labelObj; @@ -1632,17 +1666,17 @@ void Bars3dRenderer::loadLabelMesh() m_labelObj->load(); } -void Bars3dRenderer::updateTextures() +void Bars3DRenderer::updateTextures() { // Drawer has changed; this flag needs to be checked when checking if we need to update labels m_updateLabels = true; } -void Bars3dRenderer::calculateSceneScalingFactors() +void Bars3DRenderer::calculateSceneScalingFactors() { // Calculate scene scaling and translation factors - m_rowWidth = ((m_cachedColumnCount + 1) * m_cachedBarSpacing.width()) / 2.0f; - m_columnDepth = ((m_cachedRowCount + 1) * m_cachedBarSpacing.height()) / 2.0f; + m_rowWidth = (m_cachedColumnCount * m_cachedBarSpacing.width()) / 2.0f; + m_columnDepth = (m_cachedRowCount * m_cachedBarSpacing.height()) / 2.0f; m_maxDimension = qMax(m_rowWidth, m_columnDepth); m_scaleFactor = qMin((m_cachedColumnCount * (m_maxDimension / m_maxSceneSize)), (m_cachedRowCount * (m_maxDimension / m_maxSceneSize))); @@ -1653,7 +1687,7 @@ void Bars3dRenderer::calculateSceneScalingFactors() //qDebug() << "m_rowWidth:" << m_rowWidth << "m_columnDepth:" << m_columnDepth << "m_maxDimension:" << m_maxDimension; } -void Bars3dRenderer::calculateHeightAdjustment() +void Bars3DRenderer::calculateHeightAdjustment() { m_heightNormalizer = (GLfloat)qMax(qFabs(m_axisCacheY.min()), qFabs(m_axisCacheY.max())); @@ -1666,10 +1700,10 @@ void Bars3dRenderer::calculateHeightAdjustment() //qDebug() << m_yAdjustment; } -Bars3dController::SelectionType Bars3dRenderer::isSelected(GLint row, GLint bar) +Bars3DController::SelectionType Bars3DRenderer::isSelected(GLint row, GLint bar) { //static QVector3D prevSel = m_selection; // TODO: For debugging - Bars3dController::SelectionType isSelectedType = Bars3dController::SelectionNone; + Bars3DController::SelectionType isSelectedType = Bars3DController::SelectionNone; if (m_selection == selectionSkipColor) return isSelectedType; // skip window @@ -1686,39 +1720,52 @@ Bars3dController::SelectionType Bars3dRenderer::isSelected(GLint row, GLint bar) // prevSel = selection; //} if (current == m_selection) { - isSelectedType = Bars3dController::SelectionItem; + isSelectedType = Bars3DController::SelectionItem; } - else if (current.y() == m_selection.y() && (m_cachedSelectionMode == QDataVis::ModeItemAndColumn - || m_cachedSelectionMode == QDataVis::ModeItemRowAndColumn - || m_cachedSelectionMode == QDataVis::ModeZoomColumn)) { - isSelectedType = Bars3dController::SelectionColumn; + else if (current.y() == m_selection.y() && (m_cachedSelectionMode == QDataVis::SelectionModeItemAndColumn + || m_cachedSelectionMode == QDataVis::SelectionModeItemRowAndColumn + || m_cachedSelectionMode == QDataVis::SelectionModeSliceColumn)) { + isSelectedType = Bars3DController::SelectionColumn; } - else if (current.x() == m_selection.x() && (m_cachedSelectionMode == QDataVis::ModeItemAndRow - || m_cachedSelectionMode == QDataVis::ModeItemRowAndColumn - || m_cachedSelectionMode == QDataVis::ModeZoomRow)) { - isSelectedType = Bars3dController::SelectionRow; + else if (current.x() == m_selection.x() && (m_cachedSelectionMode == QDataVis::SelectionModeItemAndRow + || m_cachedSelectionMode == QDataVis::SelectionModeItemRowAndColumn + || m_cachedSelectionMode == QDataVis::SelectionModeSliceRow)) { + isSelectedType = Bars3DController::SelectionRow; } return isSelectedType; } -void Bars3dRenderer::updateSlicingActive(bool isSlicing) +void Bars3DRenderer::updateSlicingActive(bool isSlicing) { + if (isSlicing == m_cachedIsSlicingActivated) + return; + m_cachedIsSlicingActivated = isSlicing; if (isSlicing) { m_mainViewPort = QRect(0, m_cachedBoundingRect.height() - m_cachedBoundingRect.height() / 5, m_cachedBoundingRect.width() / 5, m_cachedBoundingRect.height() / 5); + m_sliceViewPort = QRect(0, 0, m_cachedBoundingRect.width(), m_cachedBoundingRect.height()); + if (m_depthTexture) { + m_textureHelper->deleteTexture(&m_depthTexture); + m_depthTexture = 0; + } } else { m_mainViewPort = QRect(0, 0, this->m_cachedBoundingRect.width(), this->m_cachedBoundingRect.height()); + m_sliceViewPort = QRect(0, 0, 0, 0); + initSelectionBuffer(); // We need to re-init selection buffer in case there has been a resize +#if !defined(QT_OPENGL_ES_2) + updateDepthBuffer(); // Re-init depth buffer as well +#endif } } -QRect Bars3dRenderer::mainViewPort() +QRect Bars3DRenderer::mainViewPort() { return m_mainViewPort; } -void Bars3dRenderer::initShaders(const QString &vertexShader, const QString &fragmentShader) +void Bars3DRenderer::initShaders(const QString &vertexShader, const QString &fragmentShader) { if (m_barShader) delete m_barShader; @@ -1726,7 +1773,7 @@ void Bars3dRenderer::initShaders(const QString &vertexShader, const QString &fra m_barShader->initialize(); } -void Bars3dRenderer::initSelectionShader() +void Bars3DRenderer::initSelectionShader() { if (m_selectionShader) delete m_selectionShader; @@ -1735,8 +1782,11 @@ void Bars3dRenderer::initSelectionShader() m_selectionShader->initialize(); } -void Bars3dRenderer::initSelectionBuffer() +void Bars3DRenderer::initSelectionBuffer() { + if (m_cachedIsSlicingActivated) + return; + if (m_selectionTexture) m_textureHelper->deleteTexture(&m_selectionTexture); @@ -1746,7 +1796,7 @@ void Bars3dRenderer::initSelectionBuffer() } #if !defined(QT_OPENGL_ES_2) -void Bars3dRenderer::initDepthShader() +void Bars3DRenderer::initDepthShader() { if (m_depthShader) delete m_depthShader; @@ -1755,30 +1805,51 @@ void Bars3dRenderer::initDepthShader() m_depthShader->initialize(); } -void Bars3dRenderer::updateDepthBuffer() +void Bars3DRenderer::updateDepthBuffer() { + if (m_cachedIsSlicingActivated) + return; + if (m_depthTexture) { m_textureHelper->deleteTexture(&m_depthTexture); m_depthTexture = 0; } - if (m_cachedShadowQuality > QDataVis::ShadowNone) { + if (m_cachedShadowQuality > QDataVis::ShadowQualityNone) { m_depthTexture = m_textureHelper->createDepthTexture(m_mainViewPort.size(), m_depthFrameBuffer, - m_cachedShadowQuality); + m_shadowQualityMultiplier); if (!m_depthTexture) { switch (m_cachedShadowQuality) { - case QDataVis::ShadowHigh: + case QDataVis::ShadowQualityHigh: qWarning("Creating high quality shadows failed. Changing to medium quality."); - (void)m_controller->setShadowQuality(QDataVis::ShadowMedium); + (void)m_controller->setShadowQuality(QDataVis::ShadowQualityMedium); + updateShadowQuality(QDataVis::ShadowQualityMedium); break; - case QDataVis::ShadowMedium: + case QDataVis::ShadowQualityMedium: qWarning("Creating medium quality shadows failed. Changing to low quality."); - (void)m_controller->setShadowQuality(QDataVis::ShadowLow); + (void)m_controller->setShadowQuality(QDataVis::ShadowQualityLow); + updateShadowQuality(QDataVis::ShadowQualityLow); break; - case QDataVis::ShadowLow: + case QDataVis::ShadowQualityLow: qWarning("Creating low quality shadows failed. Switching shadows off."); - (void)m_controller->setShadowQuality(QDataVis::ShadowNone); + (void)m_controller->setShadowQuality(QDataVis::ShadowQualityNone); + updateShadowQuality(QDataVis::ShadowQualityNone); + break; + case QDataVis::ShadowQualitySoftHigh: + qWarning("Creating soft high quality shadows failed. Changing to soft medium quality."); + (void)m_controller->setShadowQuality(QDataVis::ShadowQualitySoftMedium); + updateShadowQuality(QDataVis::ShadowQualitySoftMedium); + break; + case QDataVis::ShadowQualitySoftMedium: + qWarning("Creating soft medium quality shadows failed. Changing to soft low quality."); + (void)m_controller->setShadowQuality(QDataVis::ShadowQualitySoftLow); + updateShadowQuality(QDataVis::ShadowQualitySoftLow); + break; + case QDataVis::ShadowQualitySoftLow: + qWarning("Creating soft low quality shadows failed. Switching shadows off."); + (void)m_controller->setShadowQuality(QDataVis::ShadowQualityNone); + updateShadowQuality(QDataVis::ShadowQualityNone); break; default: // You'll never get here @@ -1789,7 +1860,7 @@ void Bars3dRenderer::updateDepthBuffer() } #endif -void Bars3dRenderer::initBackgroundShaders(const QString &vertexShader, +void Bars3DRenderer::initBackgroundShaders(const QString &vertexShader, const QString &fragmentShader) { if (m_backgroundShader) @@ -1798,7 +1869,7 @@ void Bars3dRenderer::initBackgroundShaders(const QString &vertexShader, m_backgroundShader->initialize(); } -void Bars3dRenderer::initLabelShaders(const QString &vertexShader, const QString &fragmentShader) +void Bars3DRenderer::initLabelShaders(const QString &vertexShader, const QString &fragmentShader) { if (m_labelShader) delete m_labelShader; @@ -1806,4 +1877,4 @@ void Bars3dRenderer::initLabelShaders(const QString &vertexShader, const QString m_labelShader->initialize(); } -QT_DATAVIS3D_END_NAMESPACE +QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavis3d/engine/bars3drenderer_p.h b/src/datavisualization/engine/bars3drenderer_p.h index 93d47cf1..9b612474 100644 --- a/src/datavis3d/engine/bars3drenderer_p.h +++ b/src/datavisualization/engine/bars3drenderer_p.h @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -20,7 +20,7 @@ // W A R N I N G // ------------- // -// This file is not part of the QtDataVis3D API. It exists purely as an +// 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. // @@ -29,47 +29,30 @@ #ifndef Q3DBARSRENDERER_p_H #define Q3DBARSRENDERER_p_H -#include <QtCore/QSize> -#include <QtCore/QObject> -#include <QtGui/QOpenGLFunctions> -#include <QtGui/QFont> -#include <QTime> -#include <QWindow> -#include <QMutex> - -#include "datavis3dglobal_p.h" +#include "datavisualizationglobal_p.h" #include "bars3dcontroller_p.h" #include "abstract3drenderer_p.h" #include "qbardataproxy.h" #include "barrenderitem_p.h" -//#define DISPLAY_RENDER_SPEED - class QPoint; class QSizeF; class QOpenGLShaderProgram; -QT_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVISUALIZATION_BEGIN_NAMESPACE class ShaderHelper; class ObjectHelper; -class TextureHelper; -class Theme; -class Drawer; class LabelItem; -class CameraHelper; +class Q3DScene; -class QT_DATAVIS3D_EXPORT Bars3dRenderer : public Abstract3DRenderer +class QT_DATAVISUALIZATION_EXPORT Bars3DRenderer : public Abstract3DRenderer { Q_OBJECT private: // TODO: Filter to the set of attributes to be moved to the model object. - Bars3dController *m_controller; - - // Mutex for sharing resources between render and main threads. - // TODO this mutex needs to go, too... - QMutex m_mutex; + Bars3DController *m_controller; // Cached state based on emitted signals from the controller QSizeF m_cachedBarThickness; @@ -80,7 +63,6 @@ private: // Internal state BarRenderItem *m_selectedBar; // points to renderitem array - BarRenderItem *m_previouslySelectedBar; // points to renderitem array QList<BarRenderItem *> *m_sliceSelection; AxisRenderCache *m_sliceCache; // not owned const LabelItem *m_sliceTitleItem; // not owned @@ -99,7 +81,6 @@ private: ObjectHelper *m_backgroundObj; ObjectHelper *m_gridLineObj; ObjectHelper *m_labelObj; - TextureHelper *m_textureHelper; GLuint m_bgrTexture; GLuint m_depthTexture; GLuint m_selectionTexture; @@ -107,6 +88,7 @@ private: GLuint m_selectionFrameBuffer; GLuint m_selectionDepthBuffer; GLfloat m_shadowQualityToShader; + GLint m_shadowQualityMultiplier; GLfloat m_heightNormalizer; GLfloat m_yAdjustment; GLfloat m_rowWidth; @@ -117,63 +99,51 @@ private: GLfloat m_scaleFactor; GLfloat m_maxSceneSize; QVector3D m_selection; - - QPoint m_selectionPointRequest; - bool m_isSelectionPointRequestActive; + QVector3D m_previousSelection; bool m_hasHeightAdjustmentChanged; BarRenderItem m_dummyBarRenderItem; BarRenderItemArray m_renderItemArray; -#ifdef DISPLAY_RENDER_SPEED - bool m_isFirstFrame; - QTime m_lastFrameTime; - GLint m_numFrames; -#endif - public: - explicit Bars3dRenderer(Bars3dController *controller); - ~Bars3dRenderer(); + explicit Bars3DRenderer(Bars3DController *controller); + ~Bars3DRenderer(); void updateDataModel(QBarDataProxy *dataProxy); - void render(CameraHelper *camera, const GLuint defaultFboHandle = 0); + void updateScene(Q3DScene *scene); + void render(GLuint defaultFboHandle = 0); QRect mainViewPort(); +protected: + virtual void initializeOpenGL(); + virtual void loadMeshFile(); + public slots: - void updateBarSpecs(QSizeF thickness = QSizeF(1.0f, 1.0f), - QSizeF spacing = QSizeF(1.0f, 1.0f), + void updateBarSpecs(GLfloat thicknessRatio = 1.0f, + const QSizeF &spacing = QSizeF(1.0, 1.0), bool relative = true); void updateSelectionMode(QDataVis::SelectionMode newMode); void updateSlicingActive(bool isSlicing); - void updateSampleSpace(int rowCount, int columnCount); void updateBackgroundEnabled(bool enable); - void updateMeshFileName(const QString &objFileName); + void updateSelectedBarPos(const QPoint &position); // Overloaded from abstract renderer - virtual void updateAxisRange(QAbstractAxis::AxisOrientation orientation, qreal min, qreal max); - - // Requests that upon next render pass the column and row under the given point is inspected for selection. - // Only one request can be queued per render pass at this point. New request will override any pending requests. - // After inspection the selectionUpdated signal is emitted. - virtual void requestSelectionAtPoint(const QPoint &point); + virtual void updateAxisRange(Q3DAbstractAxis::AxisOrientation orientation, qreal min, qreal max); signals: - void selectionUpdated(QVector3D selection); + void selectedBarPosChanged(QPoint position); private: - virtual void initializeOpenGL(); virtual void initShaders(const QString &vertexShader, const QString &fragmentShader); virtual void updateShadowQuality(QDataVis::ShadowQuality quality); virtual void updateTextures(); - void drawSlicedScene(CameraHelper *camera, - const LabelItem &xLabel, const LabelItem &yLabel, const LabelItem &zLabel); - void drawScene(CameraHelper *camera, const GLuint defaultFboHandle); + void drawSlicedScene(const LabelItem &xLabel, const LabelItem &yLabel, const LabelItem &zLabel); + void drawScene(GLuint defaultFboHandle); void handleResize(); - void loadBarMesh(); void loadBackgroundMesh(); void loadGridLineMesh(); void loadLabelMesh(); @@ -189,12 +159,12 @@ private: void calculateHeightAdjustment(); Abstract3DController::SelectionType isSelected(GLint row, GLint bar); - Q_DISABLE_COPY(Bars3dRenderer) + Q_DISABLE_COPY(Bars3DRenderer) friend class BarRenderItem; }; -QT_DATAVIS3D_END_NAMESPACE +QT_DATAVISUALIZATION_END_NAMESPACE #endif diff --git a/src/datavis3d/engine/drawer.cpp b/src/datavisualization/engine/drawer.cpp index 5d524963..9d50186d 100644 --- a/src/datavis3d/engine/drawer.cpp +++ b/src/datavisualization/engine/drawer.cpp @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -16,13 +16,13 @@ ** ****************************************************************************/ -#include "qdatavis3denums.h" +#include "qdatavisualizationenums.h" #include "drawer_p.h" #include "shaderhelper_p.h" #include "objecthelper_p.h" #include "abstractobjecthelper_p.h" #include "surfaceobject_p.h" -#include "camerahelper_p.h" +#include "q3dcamera.h" #include "utils_p.h" #include "texturehelper_p.h" #include <QMatrix4x4> @@ -39,18 +39,19 @@ public: }; StaticLibInitializer staticLibInitializer; -QT_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVISUALIZATION_BEGIN_NAMESPACE -Drawer::Drawer(const Theme &theme, const QFont &font, QDataVis::LabelTransparency transparency) +Drawer::Drawer(const Theme &theme, const QFont &font, QDataVis::LabelStyle style) : m_theme(theme), m_font(font), - m_transparency(transparency), + m_style(style), m_textureHelper(0) { } Drawer::~Drawer() { + delete m_textureHelper; } void Drawer::initializeOpenGL() @@ -67,15 +68,25 @@ void Drawer::setTheme(const Theme &theme) emit drawerChanged(); } +Theme Drawer::theme() const +{ + return m_theme; +} + void Drawer::setFont(const QFont &font) { m_font = font; emit drawerChanged(); } -void Drawer::setTransparency(QDataVis::LabelTransparency transparency) +QFont Drawer::font() const +{ + return m_font; +} + +void Drawer::setStyle(QDataVis::LabelStyle style) { - m_transparency = transparency; + m_style = style; emit drawerChanged(); } @@ -175,7 +186,7 @@ void Drawer::drawLabel(const AbstractRenderItem &item, const LabelItem &labelIte const QVector3D &positionComp, const QVector3D &rotation, GLfloat itemHeight, QDataVis::SelectionMode mode, ShaderHelper *shader, ObjectHelper *object, - CameraHelper *camera, + const Q3DCamera *camera, bool useDepth, bool rotateAlong, LabelPosition position, Qt::AlignmentFlag alignment) { @@ -186,13 +197,13 @@ void Drawer::drawLabel(const AbstractRenderItem &item, const LabelItem &labelIte QSize textureSize = labelItem.size(); QMatrix4x4 modelMatrix; QMatrix4x4 MVPMatrix; - GLfloat xPosition; - GLfloat yPosition; + GLfloat xPosition = 0.0f; + GLfloat yPosition = 0.0f; GLfloat zPosition = positionComp.z(); switch (position) { case LabelBelow: { - yPosition = -1.6f; // minus maximum negative height (+ some extra for label) + yPosition = -2.6f + positionComp.y(); // minus maximum negative height (+ some extra for axis title label) break; } case LabelLow: { @@ -210,31 +221,30 @@ void Drawer::drawLabel(const AbstractRenderItem &item, const LabelItem &labelIte break; } case LabelOver: { - float mod = 0.1f; + float mod = 0.3f; if (itemHeight < 0) - mod = -0.1f; - yPosition = item.translation().y() - (positionComp.y() / 2.0f - 0.2f) - + itemHeight + mod; + mod = 0.15f; + yPosition = item.translation().y() - (positionComp.y() / 2.0f) + itemHeight + mod; break; } case LabelBottom: { - yPosition = -1.95f; // TODO: Calculate from scene + yPosition = -2.95f + positionComp.y(); xPosition = 0.0f; break; } case LabelTop: { - yPosition = 1.95f; // TODO: Calculate from scene + yPosition = 2.95f - positionComp.y(); xPosition = 0.0f; break; } case LabelLeft: { yPosition = 0.0f; - xPosition = -2.5f; // TODO: Calculate from scene + xPosition = -2.95f; break; } case LabelRight: { yPosition = 0.0f; - xPosition = 2.5f; // TODO: Calculate from scene + xPosition = 2.95f; break; } } @@ -245,6 +255,7 @@ void Drawer::drawLabel(const AbstractRenderItem &item, const LabelItem &labelIte // Apply alignment GLfloat xAlignment = 0.0f; + GLfloat yAlignment = 0.0f; GLfloat zAlignment = 0.0f; switch (alignment) { case Qt::AlignLeft: { @@ -261,6 +272,20 @@ void Drawer::drawLabel(const AbstractRenderItem &item, const LabelItem &labelIte * qFabs(qSin(qDegreesToRadians(rotation.y()))); break; } + case Qt::AlignTop: { + yAlignment = ((GLfloat)textureSize.width() * scaleFactor) + * qFabs(qCos(qDegreesToRadians(rotation.y()))); + if (itemHeight < 0) + yAlignment = -yAlignment; + break; + } + case Qt::AlignBottom: { + yAlignment = (-(GLfloat)textureSize.width() * scaleFactor) + * qFabs(qCos(qDegreesToRadians(rotation.y()))); + if (itemHeight < 0) + yAlignment = -yAlignment; + break; + } default: { break; } @@ -270,12 +295,12 @@ void Drawer::drawLabel(const AbstractRenderItem &item, const LabelItem &labelIte xPosition = item.translation().x(); if (useDepth) zPosition = item.translation().z(); - else if (QDataVis::ModeZoomColumn == mode) + else if (QDataVis::SelectionModeSliceColumn == mode) xPosition = -(item.translation().z()) + positionComp.z(); // flip first to left } // Position label - modelMatrix.translate(xPosition + xAlignment, yPosition, zPosition + zAlignment); + modelMatrix.translate(xPosition + xAlignment, yPosition + yAlignment, zPosition + zAlignment); // Rotate // TODO: We should convert rotations to use quaternions to avoid rotation order problems @@ -289,10 +314,12 @@ void Drawer::drawLabel(const AbstractRenderItem &item, const LabelItem &labelIte modelMatrix.rotate(rotation.x(), 1.0f, 0.0f, 0.0f); if (useDepth && !rotateAlong) { + qreal yComp = qreal(qRadiansToDegrees(qTan(positionComp.y() / cameraDistance))); // Apply negative camera rotations to keep labels facing camera - QPointF camRotations = camera->getCameraRotations(); - modelMatrix.rotate(-camRotations.x(), 0.0f, 1.0f, 0.0f); - modelMatrix.rotate(-camRotations.y(), 1.0f, 0.0f, 0.0f); + qreal camRotationX = camera->xRotation(); + qreal camRotationY = camera->yRotation(); + modelMatrix.rotate(-camRotationX, 0.0f, 1.0f, 0.0f); + modelMatrix.rotate(-camRotationY - yComp, 1.0f, 0.0f, 0.0f); } // Scale label based on text size @@ -309,30 +336,34 @@ void Drawer::drawLabel(const AbstractRenderItem &item, const LabelItem &labelIte drawObject(shader, object, labelItem.textureId()); } -void Drawer::generateLabelTexture(AbstractRenderItem *item) +void Drawer::generateSelectionLabelTexture(AbstractRenderItem *item) { - LabelItem &labelItem = item->labelItem(); - generateLabelItem(labelItem, item->label()); + LabelItem &labelItem = item->selectionLabelItem(); + generateLabelItem(labelItem, item->selectionLabel()); } -void Drawer::generateLabelItem(LabelItem &item, const QString &text) +void Drawer::generateLabelItem(LabelItem &item, const QString &text, int widestLabel) { initializeOpenGL(); item.clear(); - // Create labels - // Print label into a QImage using QPainter - QImage label = Utils::printTextToImage(m_font, - text, - m_theme.m_textBackgroundColor, - m_theme.m_textColor, - m_transparency); - - // Set label size - item.setSize(label.size()); - // Insert text texture into label (also deletes the old texture) - item.setTextureId(m_textureHelper->create2DTexture(label, true, true)); + if (!text.isEmpty()) { + // Create labels + // Print label into a QImage using QPainter + QImage label = Utils::printTextToImage(m_font, + text, + m_theme.m_textBackgroundColor, + m_theme.m_textColor, + m_style, + m_theme.m_labelBorders, + widestLabel); + + // Set label size + item.setSize(label.size()); + // Insert text texture into label (also deletes the old texture) + item.setTextureId(m_textureHelper->create2DTexture(label, true, true)); + } } -QT_DATAVIS3D_END_NAMESPACE +QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavis3d/engine/drawer_p.h b/src/datavisualization/engine/drawer_p.h index 3139fbe0..89a4ce8c 100644 --- a/src/datavis3d/engine/drawer_p.h +++ b/src/datavisualization/engine/drawer_p.h @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -20,7 +20,7 @@ // W A R N I N G // ------------- // -// This file is not part of the QtDataVis3D API. It exists purely as an +// 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. // @@ -29,21 +29,21 @@ #ifndef DRAWER_P_H #define DRAWER_P_H -#include "datavis3dglobal_p.h" +#include "datavisualizationglobal_p.h" #include "q3dbars.h" #include "theme_p.h" #include "labelitem_p.h" #include "abstractrenderitem_p.h" #include <QFont> -QT_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVISUALIZATION_BEGIN_NAMESPACE class ShaderHelper; class ObjectHelper; class AbstractObjectHelper; class SurfaceObject; class TextureHelper; -class CameraHelper; +class Q3DCamera; class Drawer : public QObject, public QOpenGLFunctions { @@ -63,14 +63,16 @@ public: }; public: - explicit Drawer(const Theme &theme, const QFont &font, QDataVis::LabelTransparency transparency); + explicit Drawer(const Theme &theme, const QFont &font, QDataVis::LabelStyle style); ~Drawer(); void initializeOpenGL(); void setTheme(const Theme &theme); + Theme theme() const; void setFont(const QFont &font); - void setTransparency(QDataVis::LabelTransparency transparency); + QFont font() const; + void setStyle(QDataVis::LabelStyle style); void drawObject(ShaderHelper *shader, AbstractObjectHelper *object, GLuint textureId = 0, GLuint depthTextureId = 0); @@ -79,13 +81,13 @@ public: const QMatrix4x4 &viewmatrix, const QMatrix4x4 &projectionmatrix, const QVector3D &positionComp, const QVector3D &rotation, GLfloat itemHeight, QDataVis::SelectionMode mode, ShaderHelper *shader, ObjectHelper *object, - CameraHelper *camera, + const Q3DCamera *camera, bool useDepth = false, bool rotateAlong = false, LabelPosition position = LabelOver, Qt::AlignmentFlag alignment = Qt::AlignCenter); - void generateLabelTexture(AbstractRenderItem *item); - void generateLabelItem(LabelItem &item, const QString &text); + void generateSelectionLabelTexture(AbstractRenderItem *item); + void generateLabelItem(LabelItem &item, const QString &text, int widestLabel = 0); Q_SIGNALS: void drawerChanged(); @@ -93,10 +95,10 @@ Q_SIGNALS: private: Theme m_theme; QFont m_font; - QDataVis::LabelTransparency m_transparency; + QDataVis::LabelStyle m_style; TextureHelper *m_textureHelper; }; -QT_DATAVIS3D_END_NAMESPACE +QT_DATAVISUALIZATION_END_NAMESPACE #endif diff --git a/src/datavis3d/engine/engine.pri b/src/datavisualization/engine/engine.pri index 5dc415e1..4c905fe9 100644 --- a/src/datavis3d/engine/engine.pri +++ b/src/datavisualization/engine/engine.pri @@ -2,14 +2,10 @@ HEADERS += $$PWD/q3dwindow_p.h \ $$PWD/q3dwindow.h \ $$PWD/q3dbars.h \ $$PWD/q3dbars_p.h \ - $$PWD/q3dmaps.h \ - $$PWD/q3dmaps_p.h \ $$PWD/theme_p.h \ $$PWD/drawer_p.h \ $$PWD/bars3dcontroller_p.h \ $$PWD/bars3drenderer_p.h \ - $$PWD/maps3dcontroller_p.h \ - $$PWD/maps3drenderer_p.h \ $$PWD/q3dsurface.h \ $$PWD/q3dsurface_p.h \ $$PWD/surface3dcontroller_p.h \ @@ -20,17 +16,24 @@ HEADERS += $$PWD/q3dwindow_p.h \ $$PWD/scatter3dcontroller_p.h \ $$PWD/scatter3drenderer_p.h \ $$PWD/axisrendercache_p.h \ - $$PWD/abstract3drenderer_p.h + $$PWD/abstract3drenderer_p.h \ + $$PWD/selectionpointer_p.h \ + $$PWD/q3dcamera.h \ + $$PWD/q3dcamera_p.h \ + $$PWD/q3dscene.h \ + $$PWD/q3dlight.h \ + $$PWD/q3dlight_p.h \ + $$PWD/q3dbox.h \ + $$PWD/q3dobject.h \ + $$PWD/q3dobject_p.h \ + $$PWD/q3dscene_p.h SOURCES += $$PWD/q3dwindow.cpp \ $$PWD/q3dbars.cpp \ - $$PWD/q3dmaps.cpp \ $$PWD/theme.cpp \ $$PWD/drawer.cpp \ $$PWD/bars3dcontroller.cpp \ $$PWD/bars3drenderer.cpp \ - $$PWD/maps3dcontroller.cpp \ - $$PWD/maps3drenderer.cpp \ $$PWD/q3dsurface.cpp \ $$PWD/surface3drenderer.cpp \ $$PWD/surface3dcontroller.cpp \ @@ -39,6 +42,12 @@ SOURCES += $$PWD/q3dwindow.cpp \ $$PWD/scatter3dcontroller.cpp \ $$PWD/scatter3drenderer.cpp \ $$PWD/axisrendercache.cpp \ - $$PWD/abstract3drenderer.cpp + $$PWD/abstract3drenderer.cpp \ + $$PWD/selectionpointer.cpp \ + $$PWD/q3dcamera.cpp \ + $$PWD/q3dlight.cpp \ + $$PWD/q3dbox.cpp \ + $$PWD/q3dobject.cpp \ + $$PWD/q3dscene.cpp RESOURCES += engine/engine.qrc diff --git a/src/datavis3d/engine/engine.qrc b/src/datavisualization/engine/engine.qrc index af6e899d..7420ae51 100644 --- a/src/datavis3d/engine/engine.qrc +++ b/src/datavisualization/engine/engine.qrc @@ -56,6 +56,7 @@ <file alias="vertexSurfaceGrid">shaders/surfaceGrid.vert</file> <file alias="vertexSurfaceFlat">shaders/surfaceFlat.vert</file> <file alias="fragmentSurfaceFlat">shaders/surfaceFlat.frag</file> + <file alias="fragmentSurfaceES2">shaders/surface_ES2.frag</file> </qresource> <qresource prefix="/textures"/> </RCC> diff --git a/src/datavis3d/engine/meshes/backgroudFlat.obj b/src/datavisualization/engine/meshes/backgroudFlat.obj index cf4d10a5..cf4d10a5 100644 --- a/src/datavis3d/engine/meshes/backgroudFlat.obj +++ b/src/datavisualization/engine/meshes/backgroudFlat.obj diff --git a/src/datavis3d/engine/meshes/backgroudNegatives.obj b/src/datavisualization/engine/meshes/backgroudNegatives.obj index dd4d3f05..dd4d3f05 100644 --- a/src/datavis3d/engine/meshes/backgroudNegatives.obj +++ b/src/datavisualization/engine/meshes/backgroudNegatives.obj diff --git a/src/datavis3d/engine/meshes/backgroudSmooth.obj b/src/datavisualization/engine/meshes/backgroudSmooth.obj index ad16d904..ad16d904 100644 --- a/src/datavis3d/engine/meshes/backgroudSmooth.obj +++ b/src/datavisualization/engine/meshes/backgroudSmooth.obj diff --git a/src/datavis3d/engine/meshes/barFilledFlat.obj b/src/datavisualization/engine/meshes/barFilledFlat.obj index 5f627091..5f627091 100644 --- a/src/datavis3d/engine/meshes/barFilledFlat.obj +++ b/src/datavisualization/engine/meshes/barFilledFlat.obj diff --git a/src/datavis3d/engine/meshes/barFilledSmooth.obj b/src/datavisualization/engine/meshes/barFilledSmooth.obj index efc4317a..efc4317a 100644 --- a/src/datavis3d/engine/meshes/barFilledSmooth.obj +++ b/src/datavisualization/engine/meshes/barFilledSmooth.obj diff --git a/src/datavis3d/engine/meshes/barFlat.obj b/src/datavisualization/engine/meshes/barFlat.obj index b802feab..b802feab 100644 --- a/src/datavis3d/engine/meshes/barFlat.obj +++ b/src/datavisualization/engine/meshes/barFlat.obj diff --git a/src/datavis3d/engine/meshes/barSmooth.obj b/src/datavisualization/engine/meshes/barSmooth.obj index aa4fdd92..aa4fdd92 100644 --- a/src/datavis3d/engine/meshes/barSmooth.obj +++ b/src/datavisualization/engine/meshes/barSmooth.obj diff --git a/src/datavis3d/engine/meshes/coneFilledFlat.obj b/src/datavisualization/engine/meshes/coneFilledFlat.obj index cbbffaff..cbbffaff 100644 --- a/src/datavis3d/engine/meshes/coneFilledFlat.obj +++ b/src/datavisualization/engine/meshes/coneFilledFlat.obj diff --git a/src/datavis3d/engine/meshes/coneFilledSmooth.obj b/src/datavisualization/engine/meshes/coneFilledSmooth.obj index ea3a8702..ea3a8702 100644 --- a/src/datavis3d/engine/meshes/coneFilledSmooth.obj +++ b/src/datavisualization/engine/meshes/coneFilledSmooth.obj diff --git a/src/datavis3d/engine/meshes/coneFlat.obj b/src/datavisualization/engine/meshes/coneFlat.obj index 51c3821e..51c3821e 100644 --- a/src/datavis3d/engine/meshes/coneFlat.obj +++ b/src/datavisualization/engine/meshes/coneFlat.obj diff --git a/src/datavis3d/engine/meshes/coneSmooth.obj b/src/datavisualization/engine/meshes/coneSmooth.obj index 48c48ba8..48c48ba8 100644 --- a/src/datavis3d/engine/meshes/coneSmooth.obj +++ b/src/datavisualization/engine/meshes/coneSmooth.obj diff --git a/src/datavis3d/engine/meshes/cubeFilledFlat.obj b/src/datavisualization/engine/meshes/cubeFilledFlat.obj index 108cf7ac..108cf7ac 100644 --- a/src/datavis3d/engine/meshes/cubeFilledFlat.obj +++ b/src/datavisualization/engine/meshes/cubeFilledFlat.obj diff --git a/src/datavis3d/engine/meshes/cubeFilledSmooth.obj b/src/datavisualization/engine/meshes/cubeFilledSmooth.obj index 07350f03..07350f03 100644 --- a/src/datavis3d/engine/meshes/cubeFilledSmooth.obj +++ b/src/datavisualization/engine/meshes/cubeFilledSmooth.obj diff --git a/src/datavis3d/engine/meshes/cubeFlat.obj b/src/datavisualization/engine/meshes/cubeFlat.obj index 3c8d6d0a..3c8d6d0a 100644 --- a/src/datavis3d/engine/meshes/cubeFlat.obj +++ b/src/datavisualization/engine/meshes/cubeFlat.obj diff --git a/src/datavis3d/engine/meshes/cubeSmooth.obj b/src/datavisualization/engine/meshes/cubeSmooth.obj index 9d147bfd..9d147bfd 100644 --- a/src/datavis3d/engine/meshes/cubeSmooth.obj +++ b/src/datavisualization/engine/meshes/cubeSmooth.obj diff --git a/src/datavis3d/engine/meshes/cylinderFilledFlat.obj b/src/datavisualization/engine/meshes/cylinderFilledFlat.obj index 16c2ef36..16c2ef36 100644 --- a/src/datavis3d/engine/meshes/cylinderFilledFlat.obj +++ b/src/datavisualization/engine/meshes/cylinderFilledFlat.obj diff --git a/src/datavis3d/engine/meshes/cylinderFilledSmooth.obj b/src/datavisualization/engine/meshes/cylinderFilledSmooth.obj index 90db7d63..90db7d63 100644 --- a/src/datavis3d/engine/meshes/cylinderFilledSmooth.obj +++ b/src/datavisualization/engine/meshes/cylinderFilledSmooth.obj diff --git a/src/datavis3d/engine/meshes/cylinderFlat.obj b/src/datavisualization/engine/meshes/cylinderFlat.obj index 2b7e3e5e..2b7e3e5e 100644 --- a/src/datavis3d/engine/meshes/cylinderFlat.obj +++ b/src/datavisualization/engine/meshes/cylinderFlat.obj diff --git a/src/datavis3d/engine/meshes/cylinderSmooth.obj b/src/datavisualization/engine/meshes/cylinderSmooth.obj index 6ccbb286..6ccbb286 100644 --- a/src/datavis3d/engine/meshes/cylinderSmooth.obj +++ b/src/datavisualization/engine/meshes/cylinderSmooth.obj diff --git a/src/datavis3d/engine/meshes/plane.obj b/src/datavisualization/engine/meshes/plane.obj index 96ac0dd7..96ac0dd7 100644 --- a/src/datavis3d/engine/meshes/plane.obj +++ b/src/datavisualization/engine/meshes/plane.obj diff --git a/src/datavis3d/engine/meshes/pyramidFilledFlat.obj b/src/datavisualization/engine/meshes/pyramidFilledFlat.obj index 0cf73bbe..0cf73bbe 100644 --- a/src/datavis3d/engine/meshes/pyramidFilledFlat.obj +++ b/src/datavisualization/engine/meshes/pyramidFilledFlat.obj diff --git a/src/datavis3d/engine/meshes/pyramidFilledSmooth.obj b/src/datavisualization/engine/meshes/pyramidFilledSmooth.obj index 306bda58..306bda58 100644 --- a/src/datavis3d/engine/meshes/pyramidFilledSmooth.obj +++ b/src/datavisualization/engine/meshes/pyramidFilledSmooth.obj diff --git a/src/datavis3d/engine/meshes/pyramidFlat.obj b/src/datavisualization/engine/meshes/pyramidFlat.obj index 35edb477..35edb477 100644 --- a/src/datavis3d/engine/meshes/pyramidFlat.obj +++ b/src/datavisualization/engine/meshes/pyramidFlat.obj diff --git a/src/datavis3d/engine/meshes/pyramidSmooth.obj b/src/datavisualization/engine/meshes/pyramidSmooth.obj index b11c8750..b11c8750 100644 --- a/src/datavis3d/engine/meshes/pyramidSmooth.obj +++ b/src/datavisualization/engine/meshes/pyramidSmooth.obj diff --git a/src/datavis3d/engine/meshes/scatterdot.obj b/src/datavisualization/engine/meshes/scatterdot.obj index d994a80f..d994a80f 100644 --- a/src/datavis3d/engine/meshes/scatterdot.obj +++ b/src/datavisualization/engine/meshes/scatterdot.obj diff --git a/src/datavis3d/engine/meshes/scatterdotFlat.obj b/src/datavisualization/engine/meshes/scatterdotFlat.obj index 4052738d..4052738d 100644 --- a/src/datavis3d/engine/meshes/scatterdotFlat.obj +++ b/src/datavisualization/engine/meshes/scatterdotFlat.obj diff --git a/src/datavis3d/engine/meshes/sphere.obj b/src/datavisualization/engine/meshes/sphere.obj index 671a7bcc..671a7bcc 100644 --- a/src/datavis3d/engine/meshes/sphere.obj +++ b/src/datavisualization/engine/meshes/sphere.obj diff --git a/src/datavis3d/engine/meshes/sphereSmooth.obj b/src/datavisualization/engine/meshes/sphereSmooth.obj index 3c5b1299..3c5b1299 100644 --- a/src/datavis3d/engine/meshes/sphereSmooth.obj +++ b/src/datavisualization/engine/meshes/sphereSmooth.obj diff --git a/src/datavisualization/engine/q3dbars.cpp b/src/datavisualization/engine/q3dbars.cpp new file mode 100644 index 00000000..0a543d54 --- /dev/null +++ b/src/datavisualization/engine/q3dbars.cpp @@ -0,0 +1,620 @@ +/**************************************************************************** +** +** 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 "q3dbars.h" +#include "q3dbars_p.h" +#include "bars3dcontroller_p.h" +#include "q3dvalueaxis.h" +#include "q3dcategoryaxis.h" +#include "qbardataproxy.h" +#include "q3dcamera.h" + +#include <QMouseEvent> + +#include <QDebug> + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +/*! + * \class Q3DBars + * \inmodule QtDataVisualization + * \brief The Q3DBars class provides methods for rendering 3D bar graphs. + * \since 1.0.0 + * + * This class enables developers to render bar graphs in 3D and to view them by rotating the scene + * freely. Rotation is done by holding down the right mouse button and moving the mouse. Zooming + * is done by mouse wheel. Selection, if enabled, is done by left mouse button. The scene can be + * reset to default camera view by clicking mouse wheel. In touch devices rotation is done + * by tap-and-move, selection by tap-and-hold and zoom by pinch. + * + * If no axes are explicitly set to Q3DBars, temporary default axes with no labels are created. + * These default axes can be modified via axis accessors, but as soon any axis is explicitly + * set for the orientation, the default axis for that orientation is destroyed. + * + * Data proxies work similarly: If no data proxy is explicitly set, Q3DBars creates a default + * proxy. If any other proxy is set as active data proxy later, the default proxy and all data + * added to it is destroyed. + * + * Methods are provided for changing bar types, themes, bar selection modes and so on. See the + * methods for more detailed descriptions. + * + * \section1 How to construct a minimal Q3DBars graph + * + * First, construct an instance of Q3DBars: + * + * \snippet doc_src_q3dbars_construction.cpp 4 + * + * After constructing Q3DBars, you can set the data window by changing the range on the row and + * column axes. It is not mandatory, as data window will default to showing all of the data in + * the data proxy. If the amount of data is large, it is usually preferable to show just a + * portion of it. For the example, let's set the data window to show first five rows and columns: + * + * \snippet doc_src_q3dbars_construction.cpp 0 + * + * Now Q3DBars is ready to receive data to be rendered. Add one row of 5 qreals into the data + * set: + * + * \snippet doc_src_q3dbars_construction.cpp 1 + * + * \note We set the data window to 5 x 5, but we are inserting only one row of data. This is ok, + * the rest of the rows will just be blank. + * + * Finally you will need to set it visible: + * + * \snippet doc_src_q3dbars_construction.cpp 2 + * + * The complete code needed to create and display this graph is: + * + * \snippet doc_src_q3dbars_construction.cpp 3 + * + * And this is what those few lines of code produce: + * + * \image q3dbars-minimal.png + * + * The scene can be rotated, zoomed into, and a bar can be selected to view it's value, + * but no other interaction is included in this minimal code example. You can learn more by + * familiarizing yourself with the examples provided, like the \l{Bars Example} or + * the \l{Custom Proxy Example}. + * + * \sa Q3DScatter, Q3DSurface, {Qt Data Visualization C++ Classes} + */ + +/*! + * Constructs a new 3D bar window. + */ +Q3DBars::Q3DBars() + : d_ptr(new Q3DBarsPrivate(this, geometry())) +{ + setVisualController(d_ptr->m_shared); + d_ptr->m_shared->initializeOpenGL(); + QObject::connect(d_ptr->m_shared, &Bars3DController::selectedBarPosChanged, this, + &Q3DBars::selectedBarPosChanged); + QObject::connect(d_ptr->m_shared, &Abstract3DController::needRender, this, + &Q3DWindow::renderLater); +} + +/*! + * Destroys the 3D bar window. + */ +Q3DBars::~Q3DBars() +{ +} + +/*! + * \internal + */ +void Q3DBars::mouseDoubleClickEvent(QMouseEvent *event) +{ + d_ptr->m_shared->mouseDoubleClickEvent(event); +} + +/*! + * \internal + */ +void Q3DBars::touchEvent(QTouchEvent *event) +{ + d_ptr->m_shared->touchEvent(event); +} + +/*! + * \internal + */ +void Q3DBars::mousePressEvent(QMouseEvent *event) +{ + d_ptr->m_shared->mousePressEvent(event, event->pos()); +} + +/*! + * \internal + */ +void Q3DBars::mouseReleaseEvent(QMouseEvent *event) +{ + d_ptr->m_shared->mouseReleaseEvent(event, event->pos()); +} + +/*! + * \internal + */ +void Q3DBars::mouseMoveEvent(QMouseEvent *event) +{ + d_ptr->m_shared->mouseMoveEvent(event, event->pos()); +} + +/*! + * \internal + */ +void Q3DBars::wheelEvent(QWheelEvent *event) +{ + d_ptr->m_shared->wheelEvent(event); +} + +/*! + * \internal + */ +void Q3DBars::resizeEvent(QResizeEvent *event) +{ + Q_UNUSED(event); + d_ptr->m_shared->setSize(width(), height()); +} + +/*! + * Sets window \a width. + */ +void Q3DBars::setWidth(const int width) +{ + d_ptr->m_shared->setWidth(width); + QWindow::setWidth(width); +} + +/*! + * Sets window \a height. + */ +void Q3DBars::setHeight(const int height) +{ + d_ptr->m_shared->setHeight(height); + QWindow::setHeight(height); +} + +/*! + * \property Q3DBars::barThickness + * + * Bar thickness ratio between X and Z dimensions. 1.0 means bars are as wide as they are deep, 0.5 + * makes them twice as deep as they are wide. It is preset to \c 1.0 by default. + */ +void Q3DBars::setBarThickness(qreal thicknessRatio) +{ + d_ptr->m_shared->setBarSpecs(GLfloat(thicknessRatio), barSpacing(), isBarSpacingRelative()); +} + +qreal Q3DBars::barThickness() +{ + return d_ptr->m_shared->barThickness(); +} + +/*! + * \property Q3DBars::barSpacing + * + * Bar spacing, ie. the empty space between bars, in X and Z dimensions. It is preset to + * \c {(1.0, 1.0)} by default. Spacing is affected by barSpacingRelative -property. + * + * \sa barSpacingRelative + */ +void Q3DBars::setBarSpacing(QSizeF spacing) +{ + d_ptr->m_shared->setBarSpecs(GLfloat(barThickness()), spacing, isBarSpacingRelative()); +} + +QSizeF Q3DBars::barSpacing() +{ + return d_ptr->m_shared->barSpacing(); +} + +/*! + * \property Q3DBars::barSpacingRelative + * + * This is used to indicate if spacing is meant to be absolute or relative to bar thickness. + * If it is true, value of 0.0 means the bars are side-to-side and for example 1.0 means + * there is one thickness in between the bars. It is preset to \c true. + */ +void Q3DBars::setBarSpacingRelative(bool relative) +{ + d_ptr->m_shared->setBarSpecs(GLfloat(barThickness()), barSpacing(), relative); +} + +bool Q3DBars::isBarSpacingRelative() +{ + return d_ptr->m_shared->isBarSpecRelative(); +} + +/*! + * Sets the bar \a style to one of the values in \c QDataVis::MeshStyle. It is preset to + * \c QDataVis::MeshStyleBars by default. A \a smooth flag can be used to set shading to smooth. + * It is \c false by default. + * + * \sa setMeshFileName() + */ +void Q3DBars::setBarType(QDataVis::MeshStyle style, bool smooth) +{ + d_ptr->m_shared->setBarType(style, smooth); +} + +/*! + * Sets a predefined \a theme from \c QDataVis::Theme. It is preset to \c QDataVis::ThemeQt by + * default. Theme affects bar colors, label colors, text color, background color, window color and + * grid color. Lighting is also adjusted by themes. + * + * \sa setBarColor() + * + * \warning This method is subject to change. + */ +void Q3DBars::setTheme(QDataVis::Theme theme) +{ + d_ptr->m_shared->setTheme(theme); +} + +/*! + * Set bar color using your own color. \a baseColor sets the base color of a bar. The \a uniform + * -flag is used to define if color needs to be uniform throughout bar's length, or will the colors + * be applied by height, starting with dark at the bottom. It is \c true by default. + * + * Calling this method overrides colors from theme. + * + * \sa setTheme() + * + * \warning This method is subject to change. + */ +void Q3DBars::setBarColor(const QColor &baseColor, bool uniform) +{ + d_ptr->m_shared->setObjectColor(baseColor, uniform); +} + +/*! + * \return bar color in use. + */ +QColor Q3DBars::barColor() const +{ + return d_ptr->m_shared->objectColor(); +} + +/*! + * \property Q3DBars::selectionMode + * + * Sets bar selection \a mode to one of \c QDataVis::SelectionMode. It is preset to + * \c QDataVis::SelectionModeItem by default. + */ +void Q3DBars::setSelectionMode(QDataVis::SelectionMode mode) +{ + d_ptr->m_shared->setSelectionMode(mode); +} + +QDataVis::SelectionMode Q3DBars::selectionMode() const +{ + return d_ptr->m_shared->selectionMode(); +} + +/*! + * \property Q3DBars::meshFileName + * + * Override bar type with a mesh object located in \a objFileName. + * \note Object needs to be in Wavefront obj format and include vertices, normals and UVs. + * It also needs to be in triangles. + * + * \sa setBarType() + */ +void Q3DBars::setMeshFileName(const QString &objFileName) +{ + d_ptr->m_shared->setMeshFileName(objFileName); +} + +QString Q3DBars::meshFileName() const +{ + return d_ptr->m_shared->meshFileName(); +} + +/*! + * \property Q3DBars::font + * + * Sets the \a font for labels. It is preset to \c Arial by default. + */ +void Q3DBars::setFont(const QFont &font) +{ + d_ptr->m_shared->setFont(font); +} + +QFont Q3DBars::font() const +{ + return d_ptr->m_shared->font(); +} + +/*! + * \property Q3DBars::scene + * + * This property contains the read only Q3DScene that can be used to access e.g. camera object. + */ +Q3DScene *Q3DBars::scene() const +{ + return d_ptr->m_shared->scene(); +} + +/*! + * \property Q3DBars::labelStyle + * + * Sets label \a style to one of \c QDataVis::LabelStyle. It is preset to + * \c QDataVis::LabelStyleFromTheme by default. + */ +void Q3DBars::setLabelStyle(QDataVis::LabelStyle style) +{ + d_ptr->m_shared->setLabelStyle(style); +} + +QDataVis::LabelStyle Q3DBars::labelStyle() const +{ + return d_ptr->m_shared->labelStyle(); +} + +/*! + * \property Q3DBars::gridVisible + * + * Sets grid visibility to \a visible. It is preset to \c true by default. + */ +void Q3DBars::setGridVisible(bool visible) +{ + d_ptr->m_shared->setGridEnabled(visible); +} + +bool Q3DBars::isGridVisible() const +{ + return d_ptr->m_shared->gridEnabled(); +} + +/*! + * \property Q3DBars::backgroundVisible + * + * Sets background visibility to \a visible. It is preset to \c true by default. + */ +void Q3DBars::setBackgroundVisible(bool visible) +{ + d_ptr->m_shared->setBackgroundEnabled(visible); +} + +bool Q3DBars::isBackgroundVisible() const +{ + return d_ptr->m_shared->backgroundEnabled(); +} + +/*! + * \property Q3DBars::selectedBarPos + * + * Selects a bar in a \a position. The position is the position in data window. + * Only one bar can be selected at a time. + * To clear selection, specify an illegal \a position, e.g. (-1, -1). + */ +void Q3DBars::setSelectedBarPos(const QPoint &position) +{ + d_ptr->m_shared->setSelectedBarPos(position); +} + +QPoint Q3DBars::selectedBarPos() const +{ + return d_ptr->m_shared->selectedBarPos(); +} + +/*! + * \property Q3DBars::shadowQuality + * + * Sets shadow \a quality to one of \c QDataVis::ShadowQuality. It is preset to + * \c QDataVis::ShadowQualityMedium by default. + * + * \note If setting QDataVis::ShadowQuality of a certain level fails, a level is lowered + * until it is successful and shadowQualityChanged signal is emitted for each time the change is + * done. + */ +void Q3DBars::setShadowQuality(QDataVis::ShadowQuality quality) +{ + d_ptr->m_shared->setShadowQuality(quality); +} + +QDataVis::ShadowQuality Q3DBars::shadowQuality() const +{ + return d_ptr->m_shared->shadowQuality(); +} + +/*! + * Sets a user-defined row \a axis. Implicitly calls addAxis() to transfer ownership of + * the \a axis to this graph. + * + * If the \a axis is null, a temporary default axis with no labels is created. + * This temporary axis is destroyed if another \a axis is explicitly set to same orientation. + * + * \sa addAxis(), releaseAxis() + */ +void Q3DBars::setRowAxis(Q3DCategoryAxis *axis) +{ + d_ptr->m_shared->setAxisX(axis); +} + +/*! + * \return category axis for rows. + */ +Q3DCategoryAxis *Q3DBars::rowAxis() const +{ + return static_cast<Q3DCategoryAxis *>(d_ptr->m_shared->axisX()); +} + +/*! + * Sets a user-defined column \a axis. Implicitly calls addAxis() to transfer ownership of + * the \a axis to this graph. + * + * If the \a axis is null, a temporary default axis with no labels is created. + * This temporary axis is destroyed if another \a axis is explicitly set to same orientation. + * + * \sa addAxis(), releaseAxis() + */ +void Q3DBars::setColumnAxis(Q3DCategoryAxis *axis) +{ + d_ptr->m_shared->setAxisZ(axis); +} + +/*! + * \return category axis for columns. + */ +Q3DCategoryAxis *Q3DBars::columnAxis() const +{ + return static_cast<Q3DCategoryAxis *>(d_ptr->m_shared->axisZ()); +} + +/*! + * Sets a user-defined value \a axis (the Y-axis). Implicitly calls addAxis() to transfer ownership + * of the \a axis to this graph. + * + * If the \a axis is null, a temporary default axis with no labels and automatically adjusting + * range is created. + * This temporary axis is destroyed if another \a axis is explicitly set to same orientation. + * + * \sa addAxis(), releaseAxis() + */ +void Q3DBars::setValueAxis(Q3DValueAxis *axis) +{ + d_ptr->m_shared->setAxisY(axis); +} + +/*! + * \return used value axis (Y-axis). + */ +Q3DValueAxis *Q3DBars::valueAxis() const +{ + return static_cast<Q3DValueAxis *>(d_ptr->m_shared->axisY()); +} + +/*! + * Adds \a axis to the graph. The axes added via addAxis are not yet taken to use, + * addAxis is simply used to give the ownership of the \a axis to the graph. + * The \a axis must not be null or added to another graph. + * + * \sa releaseAxis(), setValueAxis(), setRowAxis(), setColumnAxis() + */ +void Q3DBars::addAxis(Q3DAbstractAxis *axis) +{ + d_ptr->m_shared->addAxis(axis); +} + +/*! + * Releases the ownership of the \a axis back to the caller, if it is added to this graph. + * If the released \a axis is in use, a new default axis will be created and set active. + * + * If the default axis is released and added back later, it behaves as any other axis would. + * + * \sa addAxis(), setValueAxis(), setRowAxis(), setColumnAxis() + */ +void Q3DBars::releaseAxis(Q3DAbstractAxis *axis) +{ + d_ptr->m_shared->releaseAxis(axis); +} + +/*! + * \return list of all added axes. + * + * \sa addAxis() + */ +QList<Q3DAbstractAxis *> Q3DBars::axes() const +{ + return d_ptr->m_shared->axes(); +} + +/*! + * Sets the active data \a proxy. Implicitly calls addDataProxy() to transfer ownership of + * the \a proxy to this graph. + * + * If the \a proxy is null, a temporary default proxy is created and activated. + * This temporary proxy is destroyed if another \a proxy is explicitly set active via this method. + * + * \sa addDataProxy(), releaseDataProxy() + */ +void Q3DBars::setActiveDataProxy(QBarDataProxy *proxy) +{ + d_ptr->m_shared->setActiveDataProxy(proxy); +} + +/*! + * \return active data proxy. + */ +QBarDataProxy *Q3DBars::activeDataProxy() const +{ + return static_cast<QBarDataProxy *>(d_ptr->m_shared->activeDataProxy()); +} + +/*! + * Adds data \a proxy to the graph. The proxies added via addDataProxy are not yet taken to use, + * addDataProxy is simply used to give the ownership of the data \a proxy to the graph. + * The \a proxy must not be null or added to another graph. + * + * \sa releaseDataProxy(), setActiveDataProxy() + */ +void Q3DBars::addDataProxy(QBarDataProxy *proxy) +{ + d_ptr->m_shared->addDataProxy(proxy); +} + +/*! + * Releases the ownership of the data \a proxy back to the caller, if it is added to this graph. + * If the released \a proxy is in use, a new empty default proxy is created and taken to use. + * + * If the default \a proxy is released and added back later, it behaves as any other proxy would. + * + * \sa addDataProxy(), setActiveDataProxy() + */ +void Q3DBars::releaseDataProxy(QBarDataProxy *proxy) +{ + d_ptr->m_shared->releaseDataProxy(proxy); +} + +/*! + * \return list of all added data proxies. + * + * \sa addDataProxy() + */ +QList<QBarDataProxy *> Q3DBars::dataProxies() const +{ + QList<QBarDataProxy *> retList; + QList<QAbstractDataProxy *> abstractList = d_ptr->m_shared->dataProxies(); + foreach (QAbstractDataProxy *proxy, abstractList) + retList.append(static_cast<QBarDataProxy *>(proxy)); + + return retList; +} + +Q3DBarsPrivate::Q3DBarsPrivate(Q3DBars *q, QRect rect) + : q_ptr(q), + m_shared(new Bars3DController(rect)) +{ + QObject::connect(m_shared, &Abstract3DController::shadowQualityChanged, this, + &Q3DBarsPrivate::handleShadowQualityUpdate); +} + +Q3DBarsPrivate::~Q3DBarsPrivate() +{ + qDebug() << "Destroying Q3DBarsPrivate"; + delete m_shared; +} + +void Q3DBarsPrivate::handleShadowQualityUpdate(QDataVis::ShadowQuality quality) +{ + emit q_ptr->shadowQualityChanged(quality); +} + +QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavisualization/engine/q3dbars.h b/src/datavisualization/engine/q3dbars.h new file mode 100644 index 00000000..d0ddf3fb --- /dev/null +++ b/src/datavisualization/engine/q3dbars.h @@ -0,0 +1,142 @@ +/**************************************************************************** +** +** 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 Q3DBARS_H +#define Q3DBARS_H + +#include <QtDataVisualization/qdatavisualizationenums.h> +#include <QtDataVisualization/q3dwindow.h> +#include <QFont> + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +class Q3DBarsPrivate; +class Q3DAbstractAxis; +class Q3DCategoryAxis; +class Q3DValueAxis; +class QBarDataProxy; +class Q3DScene; + +class QT_DATAVISUALIZATION_EXPORT Q3DBars : public Q3DWindow +{ + Q_OBJECT + Q_PROPERTY(QtDataVisualization::QDataVis::SelectionMode selectionMode READ selectionMode WRITE setSelectionMode) + Q_PROPERTY(QtDataVisualization::QDataVis::LabelStyle labelStyle READ labelStyle WRITE setLabelStyle) + Q_PROPERTY(QtDataVisualization::QDataVis::ShadowQuality shadowQuality READ shadowQuality WRITE setShadowQuality NOTIFY shadowQualityChanged) + Q_PROPERTY(qreal barThickness READ barThickness WRITE setBarThickness) + Q_PROPERTY(QSizeF barSpacing READ barSpacing WRITE setBarSpacing) + Q_PROPERTY(bool barSpacingRelative READ isBarSpacingRelative WRITE setBarSpacingRelative) + Q_PROPERTY(QString meshFileName READ meshFileName WRITE setMeshFileName) + Q_PROPERTY(QFont font READ font WRITE setFont) + Q_PROPERTY(bool gridVisible READ isGridVisible WRITE setGridVisible) + Q_PROPERTY(bool backgroundVisible READ isBackgroundVisible WRITE setBackgroundVisible) + Q_PROPERTY(QPoint selectedBarPos READ selectedBarPos WRITE setSelectedBarPos NOTIFY selectedBarPosChanged) + Q_PROPERTY(Q3DScene* scene READ scene) + + Q_ENUMS(QtDataVisualization::QDataVis::SelectionMode) + Q_ENUMS(QtDataVisualization::QDataVis::ShadowQuality) + Q_ENUMS(QtDataVisualization::QDataVis::LabelStyle) + Q_ENUMS(QtDataVisualization::QDataVis::CameraPreset) + +public: + explicit Q3DBars(); + ~Q3DBars(); + + void setBarType(QDataVis::MeshStyle style, bool smooth = false); + + void setTheme(QDataVis::Theme theme); + + void setBarThickness(qreal thicknessRatio); + qreal barThickness(); + + void setBarSpacing(QSizeF spacing); + QSizeF barSpacing(); + + void setBarSpacingRelative(bool relative); + bool isBarSpacingRelative(); + + void setBarColor(const QColor &baseColor, bool uniform = true); + QColor barColor() const; + + void setMeshFileName(const QString &objFileName); + QString meshFileName() const; + + void setSelectionMode(QDataVis::SelectionMode mode); + QDataVis::SelectionMode selectionMode() const; + + void setFont(const QFont &font); + QFont font() const; + + Q3DScene *scene() const; + + void setLabelStyle(QDataVis::LabelStyle style); + QDataVis::LabelStyle labelStyle() const; + + void setGridVisible(bool visible); + bool isGridVisible() const; + + void setWidth(const int width); + void setHeight(const int height); + + void setBackgroundVisible(bool visible); + bool isBackgroundVisible() const; + + void setSelectedBarPos(const QPoint &position); + QPoint selectedBarPos() const; + + void setShadowQuality(QDataVis::ShadowQuality quality); + QDataVis::ShadowQuality shadowQuality() const; + + void setRowAxis(Q3DCategoryAxis *axis); + Q3DCategoryAxis *rowAxis() const; + void setColumnAxis(Q3DCategoryAxis *axis); + Q3DCategoryAxis *columnAxis() const; + void setValueAxis(Q3DValueAxis *axis); + Q3DValueAxis *valueAxis() const; + void addAxis(Q3DAbstractAxis *axis); + void releaseAxis(Q3DAbstractAxis *axis); + QList<Q3DAbstractAxis *> axes() const; + + void setActiveDataProxy(QBarDataProxy *proxy); + QBarDataProxy *activeDataProxy() const; + void addDataProxy(QBarDataProxy *proxy); + void releaseDataProxy(QBarDataProxy *proxy); + QList<QBarDataProxy *> dataProxies() const; + +signals: + void shadowQualityChanged(QDataVis::ShadowQuality quality); + void selectedBarPosChanged(QPoint position); + +protected: + + void mouseDoubleClickEvent(QMouseEvent *event); + void touchEvent(QTouchEvent *event); + void mousePressEvent(QMouseEvent *event); + void mouseReleaseEvent(QMouseEvent *event); + void mouseMoveEvent(QMouseEvent *event); + void wheelEvent(QWheelEvent *event); + void resizeEvent(QResizeEvent *event); + +private: + QScopedPointer<Q3DBarsPrivate> d_ptr; + Q_DISABLE_COPY(Q3DBars) +}; + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif diff --git a/src/datavis3d/engine/q3dbars_p.h b/src/datavisualization/engine/q3dbars_p.h index 9eed8162..653db606 100644 --- a/src/datavis3d/engine/q3dbars_p.h +++ b/src/datavisualization/engine/q3dbars_p.h @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -20,7 +20,7 @@ // W A R N I N G // ------------- // -// This file is not part of the QtDataVis3D API. It exists purely as an +// 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. // @@ -30,9 +30,9 @@ #define Q3DBARS_p_H #include "bars3dcontroller_p.h" -#include "qdatavis3denums.h" +#include "qdatavisualizationenums.h" -QT_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVISUALIZATION_BEGIN_NAMESPACE class Q3DBars; @@ -42,10 +42,13 @@ public: Q3DBarsPrivate(Q3DBars *q, QRect rect); ~Q3DBarsPrivate(); + // Used to detect when shadow quality changes autonomously due to e.g. resizing. + void handleShadowQualityUpdate(QDataVis::ShadowQuality quality); + Q3DBars *q_ptr; - Bars3dController *m_shared; + Bars3DController *m_shared; }; -QT_DATAVIS3D_END_NAMESPACE +QT_DATAVISUALIZATION_END_NAMESPACE #endif diff --git a/src/datavisualization/engine/q3dbox.cpp b/src/datavisualization/engine/q3dbox.cpp new file mode 100644 index 00000000..43f3e90e --- /dev/null +++ b/src/datavisualization/engine/q3dbox.cpp @@ -0,0 +1,481 @@ +/**************************************************************************** +** +** 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 "datavisualizationglobal_p.h" +#include "q3dbox.h" +#include <QtCore/QList> + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +/*! + \class Q3DBox + \inmodule QtDataVisualization + \brief The Q3DBox class represents an axis-aligned box in 3D space. + \since 1.0.0 + + Q3DBox can be used to represent the bounding box of objects in a 3D + scene so that they can be easily culled if they are out of view. + + The sides of the box are always aligned with the x, y, and z axes of + the world co-ordinate system. Transforming a box with transformed() + will result in the smallest axis-aligned bounding box that contains + the transformed box. + + Boxes may be null, finite, or infinite. A null box does not occupy + any space and does not intersect with any other box. A finite + box consists of a minimum() and maximum() extent in 3D space. + An infinite box encompasses all points in 3D space. + + The extents of a finite box are also included within the box. + A box with minimum() and maximum() set to the same value + contains a single point. +*/ + +/*! + \fn Q3DBox::Q3DBox() + + Constructs a null box in 3D space. + + \sa isNull() +*/ + +/*! + \fn Q3DBox::Q3DBox(const QVector3D& corner1, const QVector3D& corner2) + + Constructs a finite box in 3D space from \a corner1 to \a corner2. + The minimum() and maximum() co-ordinates of the new box are set + to the minimum and maximum x, y, and z values from \a corner1 and + \a corner2. The \a corner1 and \a corner2 values can be any two + opposite corners that define the box. + + \sa isFinite(), minimum(), maximum() +*/ + +/*! + \fn bool Q3DBox::isNull() const + + Returns true if this box is null; false otherwise. + + \sa isFinite(), isInfinite(), setToNull() +*/ + +/*! + \fn bool Q3DBox::isFinite() const + + Returns true if this box is finite in size; false otherwise. + + \sa isNull(), isInfinite(), setExtents() +*/ + +/*! + \fn bool Q3DBox::isInfinite() const + + Returns true if this box is infinite in size; false otherwise. + + \sa isNull(), isFinite(), setToInfinite() +*/ + +/*! + \fn QVector3D Q3DBox::minimum() const + + Returns the minimum corner of this box. + + \sa maximum(), setExtents() +*/ + +/*! + \fn QVector3D Q3DBox::maximum() const + + Returns the maximum corner of this box. + + \sa minimum(), setExtents() +*/ + +/*! + \fn void Q3DBox::setExtents(const QVector3D& corner1, const QVector3D& corner2) + + Sets the extents of this box to a finite region from \a corner1 to + \a corner2. The minimum() and maximum() co-ordinates of the box are + set to the minimum and maximum x, y, and z values from \a corner1 and + \a corner2. The \a corner1 and \a corner2 values can be any two + opposite corners that define the box. + + \sa minimum(), maximum() +*/ + +/*! + \fn void Q3DBox::setToNull() + + Sets this box to null. + + \sa isNull() +*/ + +/*! + \fn void Q3DBox::setToInfinite() + + Sets this box to be infinite in size. + + \sa isInfinite() +*/ + +/*! + \fn QVector3D Q3DBox::size() const + + Returns the finite size of this box. If this box is null or + infinite, the returned value will be zero. + + \sa center(), isNull(), isInfinite() +*/ + +/*! + \fn QVector3D Q3DBox::center() const + + Returns the finite center of this box. If this box is null + or infinite, the returned value will be zero. + + \sa size(), isNull(), isInfinite() +*/ + +/*! + \fn bool Q3DBox::contains(const QVector3D& point) const + + Returns true if this box contains \a point; false otherwise. + Null boxes do not contain any points and infinite boxes contain + all points. + + Containment is not a strict test: the point is contained if it + lies on one of the faces of the box. + + \sa intersects() +*/ + +/*! + \fn bool Q3DBox::contains(const Q3DBox& box) const + + Returns true if this box completely contains \a box. If this box + is null, then it will not contain \a box. If this box is infinite, + and \a box is not null, then \a box will be contained within this box. + If \a box is infinite, then this box must also be infinite to contain it. + + \sa intersects() +*/ + +/*! + Returns true if \a box intersects this box; false otherwise. + + \sa intersect(), intersected(), contains() +*/ +bool Q3DBox::intersects(const Q3DBox& box) const +{ + if (boxtype == Null) + return false; + else if (boxtype == Infinite) + return box.boxtype != Null; + else if (box.boxtype == Null) + return false; + else if (box.boxtype == Infinite) + return true; + + if (maxcorner.x() < box.mincorner.x()) + return false; + if (mincorner.x() > box.maxcorner.x()) + return false; + + if (maxcorner.y() < box.mincorner.y()) + return false; + if (mincorner.y() > box.maxcorner.y()) + return false; + + if (maxcorner.z() < box.mincorner.z()) + return false; + if (mincorner.z() > box.maxcorner.z()) + return false; + + return true; +} + +/*! + Intersects this box with \a box. + + \sa intersected(), intersects(), unite() +*/ +void Q3DBox::intersect(const Q3DBox& box) +{ + // Handle the simple cases first. + if (boxtype == Null) { + // Null intersected with anything is null. + return; + } else if (boxtype == Infinite) { + // Infinity intersected with a box is that box. + *this = box; + return; + } else if (box.boxtype == Null) { + // Anything intersected with null is null. + setToNull(); + return; + } else if (box.boxtype == Infinite) { + // Box intersected with infinity is the box. + return; + } + + // Intersect two finite boxes. + QVector3D min1 = mincorner; + QVector3D max1 = maxcorner; + QVector3D min2 = box.mincorner; + QVector3D max2 = box.maxcorner; + if (min2.x() > min1.x()) + min1.setX(min2.x()); + if (min2.y() > min1.y()) + min1.setY(min2.y()); + if (min2.z() > min1.z()) + min1.setZ(min2.z()); + if (max2.x() < max1.x()) + max1.setX(max2.x()); + if (max2.y() < max1.y()) + max1.setY(max2.y()); + if (max2.z() < max1.z()) + max1.setZ(max2.z()); + if (min1.x() > max1.x() || min1.y() > max1.y() || min1.z() > max1.z()) { + setToNull(); + } else { + mincorner = min1; + maxcorner = max1; + } +} + +/*! + Returns a new box which is the intersection of this box with \a box. + + \sa intersect(), intersects(), united() +*/ +Q3DBox Q3DBox::intersected(const Q3DBox& box) const +{ + Q3DBox result(*this); + result.intersect(box); + return result; +} + +/*! + Unites this box with \a point by expanding it to encompass \a point. + If \a point is already contained within this box, then this box + will be unchanged. + + \sa united(), intersect() +*/ +void Q3DBox::unite(const QVector3D& point) +{ + if (boxtype == Finite) { + if (point.x() < mincorner.x()) + mincorner.setX(point.x()); + else if (point.x() > maxcorner.x()) + maxcorner.setX(point.x()); + if (point.y() < mincorner.y()) + mincorner.setY(point.y()); + else if (point.y() > maxcorner.y()) + maxcorner.setY(point.y()); + if (point.z() < mincorner.z()) + mincorner.setZ(point.z()); + else if (point.z() > maxcorner.z()) + maxcorner.setZ(point.z()); + } else if (boxtype == Null) { + boxtype = Finite; + mincorner = point; + maxcorner = point; + } +} + +/*! + Unites this box with \a box by expanding this box to encompass the + region defined by \a box. If \a box is already contained within + this box, then this box will be unchanged. + + \sa united(), intersect() +*/ +void Q3DBox::unite(const Q3DBox& box) +{ + if (box.boxtype == Finite) { + unite(box.minimum()); + unite(box.maximum()); + } else if (box.boxtype == Infinite) { + setToInfinite(); + } +} + +/*! + Returns a new box which unites this box with \a point. The returned + value will be the smallest box that contains both this box and \a point. + + \sa unite(), intersected() +*/ +Q3DBox Q3DBox::united(const QVector3D& point) const +{ + if (boxtype == Finite) { + Q3DBox result(*this); + result.unite(point); + return result; + } else if (boxtype == Null) { + return Q3DBox(point, point); + } else { + return *this; + } +} + +/*! + Returns a new box which unites this box with \a box. The returned value + will be the smallest box that contains both this box and \a box. + + \sa unite(), intersected() +*/ +Q3DBox Q3DBox::united(const Q3DBox& box) const +{ + if (boxtype == Finite) { + Q3DBox result(*this); + result.unite(box); + return result; + } else if (boxtype == Null) { + return box; + } else { + return *this; + } +} + +/*! + Transforms this box according to \a matrix. Each of the 8 box + corners are transformed and then a new box that encompasses all + of the transformed corner values is created. + + \sa transformed() +*/ +void Q3DBox::transform(const QMatrix4x4& matrix) +{ + *this = transformed(matrix); +} + +/*! + Returns this box transformed by \a matrix. Each of the 8 box + corners are transformed and then a new box that encompasses all + of the transformed corner values is returned. + + \sa transform() +*/ +Q3DBox Q3DBox::transformed(const QMatrix4x4& matrix) const +{ + if (boxtype != Finite) + return *this; + Q3DBox result; + result.unite(matrix * mincorner); + result.unite(matrix * QVector3D(mincorner.x(), mincorner.y(), maxcorner.z())); + result.unite(matrix * QVector3D(mincorner.x(), maxcorner.y(), maxcorner.z())); + result.unite(matrix * QVector3D(mincorner.x(), maxcorner.y(), mincorner.z())); + result.unite(matrix * QVector3D(maxcorner.x(), mincorner.y(), mincorner.z())); + result.unite(matrix * QVector3D(maxcorner.x(), maxcorner.y(), mincorner.z())); + result.unite(matrix * QVector3D(maxcorner.x(), mincorner.y(), maxcorner.z())); + result.unite(matrix * maxcorner); + return result; +} + +/*! + \fn bool Q3DBox::operator==(const Q3DBox& box) const + + Returns true if this box is identical to \a box. +*/ + +/*! + \fn bool Q3DBox::operator!=(const Q3DBox& box) const + + Returns true if this box is not identical to \a box. +*/ + +/*! + \fn bool qFuzzyCompare(const Q3DBox& box1, const Q3DBox& box2) + \relates Q3DBox + + Returns true if \a box1 and \a box2 are almost equal; false otherwise. +*/ + +#ifndef QT_NO_DEBUG_STREAM + +QDebug operator<<(QDebug dbg, const Q3DBox &box) +{ + if (box.isFinite()) { + dbg.nospace() << "Q3DBox((" + << box.minimum().x() << ", " << box.minimum().y() << ", " + << box.minimum().z() << ") - (" + << box.maximum().x() << ", " << box.maximum().y() << ", " + << box.maximum().z() << "))"; + return dbg.space(); + } else if (box.isNull()) { + dbg << "Q3DBox(null)"; + return dbg; + } else { + dbg << "Q3DBox(infinite)"; + return dbg; + } +} + +#endif + +#ifndef QT_NO_DATASTREAM + +/*! + \relates Q3DBox + + Writes the given \a box to the given \a stream and returns a + reference to the stream. +*/ +QDataStream &operator<<(QDataStream &stream, const Q3DBox &box) +{ + if (box.isNull()) { + stream << int(0); + } else if (box.isInfinite()) { + stream << int(2); + } else { + stream << int(1); + stream << box.minimum(); + stream << box.maximum(); + } + return stream; +} + +/*! + \relates Q3DBox + + Reads a 3D box from the given \a stream into the given \a box + and returns a reference to the stream. +*/ +QDataStream &operator>>(QDataStream &stream, Q3DBox &box) +{ + int type; + stream >> type; + if (type == 1) { + QVector3D minimum, maximum; + stream >> minimum; + stream >> maximum; + box = Q3DBox(minimum, maximum); + } else if (type == 2) { + box.setToInfinite(); + } else { + box.setToNull(); + } + return stream; +} + +#endif // QT_NO_DATASTREAM + +QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavisualization/engine/q3dbox.h b/src/datavisualization/engine/q3dbox.h new file mode 100644 index 00000000..aa63ec39 --- /dev/null +++ b/src/datavisualization/engine/q3dbox.h @@ -0,0 +1,184 @@ +/**************************************************************************** +** +** 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 Q3DBOX_H +#define Q3DBOX_H + +#include <QtDataVisualization/qdatavisualizationenums.h> +#include <QtGui/QMatrix4x4> +#include <QtGui/QVector3D> + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +class Q3DBox; // Needed to circumvent an issue with qdoc. If this line is removed, make docs will not work for this. + +class QT_DATAVISUALIZATION_EXPORT Q3DBox +{ +public: + Q3DBox(); + Q3DBox(const QVector3D& corner1, const QVector3D& corner2); + + bool isNull() const; + bool isFinite() const; + bool isInfinite() const; + + QVector3D minimum() const; + QVector3D maximum() const; + void setExtents(const QVector3D& corner1, const QVector3D& corner2); + + void setToNull(); + void setToInfinite(); + + QVector3D size() const; + QVector3D center() const; + + bool contains(const QVector3D& point) const; + bool contains(const Q3DBox& box) const; + + bool intersects(const Q3DBox& box) const; + void intersect(const Q3DBox& box); + Q3DBox intersected(const Q3DBox& box) const; + + void unite(const QVector3D& point); + void unite(const Q3DBox& box); + + Q3DBox united(const QVector3D& point) const; + Q3DBox united(const Q3DBox& box) const; + + void transform(const QMatrix4x4& matrix); + Q3DBox transformed(const QMatrix4x4& matrix) const; + + bool operator==(const Q3DBox& box) const; + bool operator!=(const Q3DBox& box) const; + + friend bool qFuzzyCompare(const Q3DBox& box1, const Q3DBox& box2); + +private: + enum Type + { + Null, + Finite, + Infinite + }; + + Q3DBox::Type boxtype; + QVector3D mincorner, maxcorner; +}; + +inline Q3DBox::Q3DBox() : boxtype(Null), mincorner(0, 0, 0), maxcorner(0, 0, 0) {} + +inline Q3DBox::Q3DBox(const QVector3D& corner1, const QVector3D& corner2) + : boxtype(Finite), + mincorner(qMin(corner1.x(), corner2.x()), + qMin(corner1.y(), corner2.y()), + qMin(corner1.z(), corner2.z())), + maxcorner(qMax(corner1.x(), corner2.x()), + qMax(corner1.y(), corner2.y()), + qMax(corner1.z(), corner2.z())) {} + +inline bool Q3DBox::isNull() const { return (boxtype == Null); } +inline bool Q3DBox::isFinite() const { return (boxtype == Finite); } +inline bool Q3DBox::isInfinite() const { return (boxtype == Infinite); } + +inline QVector3D Q3DBox::minimum() const { return mincorner; } +inline QVector3D Q3DBox::maximum() const { return maxcorner; } + +inline void Q3DBox::setExtents(const QVector3D& corner1, const QVector3D& corner2) +{ + boxtype = Finite; + mincorner = QVector3D(qMin(corner1.x(), corner2.x()), + qMin(corner1.y(), corner2.y()), + qMin(corner1.z(), corner2.z())); + maxcorner = QVector3D(qMax(corner1.x(), corner2.x()), + qMax(corner1.y(), corner2.y()), + qMax(corner1.z(), corner2.z())); +} + +inline void Q3DBox::setToNull() +{ + boxtype = Null; + mincorner = QVector3D(0, 0, 0); + maxcorner = QVector3D(0, 0, 0); +} + +inline void Q3DBox::setToInfinite() +{ + boxtype = Infinite; + mincorner = QVector3D(0, 0, 0); + maxcorner = QVector3D(0, 0, 0); +} + +inline QVector3D Q3DBox::size() const { return maxcorner - mincorner; } +inline QVector3D Q3DBox::center() const { return (mincorner + maxcorner) * 0.5f; } + +inline bool Q3DBox::contains(const QVector3D& point) const +{ + if (boxtype == Finite) { + return (point.x() >= mincorner.x() && point.x() <= maxcorner.x() && + point.y() >= mincorner.y() && point.y() <= maxcorner.y() && + point.z() >= mincorner.z() && point.z() <= maxcorner.z()); + } else if (boxtype == Infinite) { + return true; + } else { + return false; + } +} + +inline bool Q3DBox::contains(const Q3DBox& box) const +{ + if (box.boxtype == Finite) + return contains(box.mincorner) && contains(box.maxcorner); + else if (box.boxtype == Infinite) + return (boxtype == Infinite); + else + return false; +} + +inline bool Q3DBox::operator==(const Q3DBox& box) const +{ + return (boxtype == box.boxtype && + mincorner == box.mincorner && + maxcorner == box.maxcorner); +} + +inline bool Q3DBox::operator!=(const Q3DBox& box) const +{ + return (boxtype != box.boxtype || + mincorner != box.mincorner || + maxcorner != box.maxcorner); +} + +inline bool qFuzzyCompare(const Q3DBox& box1, const Q3DBox& box2) +{ + return box1.boxtype == box2.boxtype && + qFuzzyCompare(box1.mincorner, box2.mincorner) && + qFuzzyCompare(box1.maxcorner, box2.maxcorner); +} + +#ifndef QT_NO_DEBUG_STREAM +QT_DATAVISUALIZATION_EXPORT QDebug operator<<(QDebug dbg, const Q3DBox &box); +#endif + +#ifndef QT_NO_DATASTREAM +QT_DATAVISUALIZATION_EXPORT QDataStream &operator<<(QDataStream &stream, const Q3DBox &box); +QT_DATAVISUALIZATION_EXPORT QDataStream &operator>>(QDataStream &stream, Q3DBox &box); +#endif + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif diff --git a/src/datavisualization/engine/q3dcamera.cpp b/src/datavisualization/engine/q3dcamera.cpp new file mode 100644 index 00000000..571af1d7 --- /dev/null +++ b/src/datavisualization/engine/q3dcamera.cpp @@ -0,0 +1,698 @@ +/**************************************************************************** +** +** 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 "q3dcamera.h" +#include "q3dcamera_p.h" +#include "q3dscene.h" +#include "q3dbox.h" +#include "q3dobject.h" +#include "utils_p.h" + +#include <qmath.h> +#include <QVector3D> + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +/*! + \class Q3DCamera + \inmodule QtDataVisualization + \brief Representation of a camera in 3D space. + \since 1.0.0 + + Q3DCamera represents a basic orbit around centerpoint 3D camera that is used when rendering the data visualization. + The class offers simple methods for setting the orbit point in rotations, but allows also setting the 4x4 viewmatrix + directly in case a more customized camera behavior is needed. +*/ + +/*! + * Constructs a new 3D camera with position set to origo, up direction facing towards the Y-axis and looking at origo by default. An + * optional \a parent parameter can be given and is then passed to QObject constructor. + */ +Q3DCamera::Q3DCamera(QObject *parent) : + Q3DObject(parent), + d_ptr(new Q3DCameraPrivate(this)) +{ +} + +/*! + * Destroys the camera object. + */ +Q3DCamera::~Q3DCamera() +{ +} + +/*! + * Copies the 3D camera's properties from the given source camera. + * Values are copied from the \a source to this object. + */ +void Q3DCamera::copyValuesFrom(const Q3DCamera &source) +{ + Q3DObject::copyValuesFrom(source); + + d_ptr->m_target.setX(source.d_ptr->m_target.x()); + d_ptr->m_target.setY(source.d_ptr->m_target.y()); + d_ptr->m_target.setZ(source.d_ptr->m_target.z()); + + d_ptr->m_up.setX(source.d_ptr->m_up.x()); + d_ptr->m_up.setY(source.d_ptr->m_up.y()); + d_ptr->m_up.setZ(source.d_ptr->m_up.z()); + + float *values = new float[16]; + source.d_ptr->m_viewMatrix.copyDataTo(values); + d_ptr->m_viewMatrix = QMatrix4x4(values); + delete[] values; + + d_ptr->m_xRotation = source.d_ptr->m_xRotation; + d_ptr->m_yRotation = source.d_ptr->m_yRotation; + + d_ptr->m_minXRotation = source.d_ptr->m_minXRotation; + d_ptr->m_minYRotation = source.d_ptr->m_minYRotation; + d_ptr->m_maxXRotation = source.d_ptr->m_maxXRotation; + d_ptr->m_maxYRotation = source.d_ptr->m_maxYRotation; + + d_ptr->m_wrapXRotation = source.d_ptr->m_wrapXRotation; + d_ptr->m_wrapYRotation = source.d_ptr->m_wrapYRotation; + + d_ptr->m_zoomLevel = source.d_ptr->m_zoomLevel; + d_ptr->m_activePreset = source.d_ptr->m_activePreset; +} + +/*! + * \property Q3DCamera::xRotation + * + * This property contains the X-rotation angle of the camera around the target point in degrees starting from + * the current base position set by the setBaseOrientation() methods. + */ +qreal Q3DCamera::xRotation() const { + return d_ptr->m_xRotation; +} + +void Q3DCamera::setXRotation(qreal rotation) +{ + if (d_ptr->m_wrapXRotation) + rotation = Utils::wrapValue(rotation, d_ptr->m_minXRotation, d_ptr->m_maxXRotation); + else + rotation = qBound(qreal(d_ptr->m_minXRotation), qreal(rotation), qreal(d_ptr->m_maxXRotation)); + + if (d_ptr->m_xRotation != rotation) { + d_ptr->setXRotation(rotation); + if (d_ptr->m_activePreset != QDataVis::CameraPresetNone) { + d_ptr->m_activePreset = QDataVis::CameraPresetNone; + setDirty(true); + } + + emit xRotationChanged(d_ptr->m_xRotation); + } +} + +/*! + * \property Q3DCamera::yRotation + * + * This property contains the Y-rotation angle of the camera around the target point in degrees starting from + * the current base position set by the setBaseOrientation() methods. + */ +qreal Q3DCamera::yRotation() const { + return d_ptr->m_yRotation; +} + +void Q3DCamera::setYRotation(qreal rotation) +{ + if (d_ptr->m_wrapYRotation) + rotation = Utils::wrapValue(rotation, d_ptr->m_minYRotation, d_ptr->m_maxYRotation); + else + rotation = qBound(qreal(d_ptr->m_minYRotation), qreal(rotation), qreal(d_ptr->m_maxYRotation)); + + if (d_ptr->m_yRotation != rotation) { + d_ptr->setYRotation(rotation); + if (d_ptr->m_activePreset != QDataVis::CameraPresetNone) { + d_ptr->m_activePreset = QDataVis::CameraPresetNone; + setDirty(true); + } + + emit yRotationChanged(d_ptr->m_yRotation); + } +} + +/*! + * \property Q3DCamera::minXRotation + * + * This property contains the current minimum X-rotation for the camera. + * The full circle range is [-180,180] and the minimum value is limited to -180. + * Also the value can't be higher than maximum, and is adjusted if necessary. + * + * \sa wrapXRotation, maxXRotation + */ +qreal Q3DCamera::minXRotation() const +{ + return d_ptr->m_minXRotation; +} + +/*! + * \internal + */ +void Q3DCamera::setMinXRotation(qreal minRotation) +{ + minRotation = qBound(-180.0, minRotation, 180.0); + if (minRotation > d_ptr->m_maxXRotation) + minRotation = d_ptr->m_maxXRotation; + + if (d_ptr->m_minXRotation != minRotation) { + d_ptr->m_minXRotation = minRotation; + emit minXRotationChanged(minRotation); + + if (d_ptr->m_xRotation < d_ptr->m_minXRotation) + setXRotation(d_ptr->m_xRotation); + } +} + +/*! + * \property Q3DCamera::minYRotation + * + * This property contains the current minimum Y-rotation for the camera. + * The full Y angle range is [-90,90] and the minimum value is limited to -90. + * Also the value can't be higher than maximum, and is adjusted if necessary. + * + * \sa wrapYRotation, maxYRotation + */ +qreal Q3DCamera::minYRotation() const +{ + return d_ptr->m_minYRotation; +} + +/*! + * \internal + */ +void Q3DCamera::setMinYRotation(qreal minRotation) +{ + minRotation = qBound(-90.0, minRotation, 90.0); + if (minRotation > d_ptr->m_maxYRotation) + minRotation = d_ptr->m_maxYRotation; + + if (d_ptr->m_minYRotation != minRotation) { + d_ptr->m_minYRotation = minRotation; + emit minYRotationChanged(minRotation); + + if (d_ptr->m_yRotation < d_ptr->m_minYRotation) + setYRotation(d_ptr->m_yRotation); + } +} + +/*! + * \property Q3DCamera::maxXRotation + * + * This property contains the current maximum X-rotation for the camera. + * The full circle range is [-180,180] and the maximum value is limited to 180. + * Also the value can't be lower than minimum, and is adjusted if necessary. + * + * \sa wrapXRotation, minXRotation + */ +qreal Q3DCamera::maxXRotation() const +{ + return d_ptr->m_maxXRotation; +} + +/*! + * \internal + */ +void Q3DCamera::setMaxXRotation(qreal maxRotation) +{ + maxRotation = qBound(-180.0, maxRotation, 180.0); + + if (maxRotation < d_ptr->m_minXRotation) + maxRotation = d_ptr->m_minXRotation; + + if (d_ptr->m_maxXRotation != maxRotation) { + d_ptr->m_maxXRotation = maxRotation; + emit maxXRotationChanged(maxRotation); + + if (d_ptr->m_xRotation > d_ptr->m_maxXRotation) + setXRotation(d_ptr->m_xRotation); + } +} + +/*! + * \property Q3DCamera::maxYRotation + * + * This property contains the current maximum Y-rotation for the camera. + * The full Y angle range is [-90,90] and the maximum value is limited to 90. + * Also the value can't be lower than minimum, and is adjusted if necessary. + * + * \sa wrapYRotation, minYRotation + */ +qreal Q3DCamera::maxYRotation() const +{ + return d_ptr->m_maxYRotation; +} + +/*! + * \internal + */ +void Q3DCamera::setMaxYRotation(qreal maxRotation) +{ + maxRotation = qBound(-90.0, maxRotation, 90.0); + + if (maxRotation < d_ptr->m_minYRotation) + maxRotation = d_ptr->m_minYRotation; + + if (d_ptr->m_maxYRotation != maxRotation) { + d_ptr->m_maxYRotation = maxRotation; + emit maxYRotationChanged(maxRotation); + + if (d_ptr->m_yRotation > d_ptr->m_maxYRotation) + setYRotation(d_ptr->m_yRotation); + } +} + +/*! + * Sets the base values for the camera that are used when calculating the camera position using the rotation values. + * The base position of the camera is defined by \a basePosition, expectation is that the x and y values are 0. + * Look at target point is defined by \a target and the camera rotates around it. Up direction for the camera is + * defined by \a baseUp, normally this is a vector with only y values set to 1. + */ +void Q3DCamera::setBaseOrientation(const QVector3D &basePosition, + const QVector3D &target, + const QVector3D &baseUp) +{ + if (position() != basePosition + || d_ptr->m_target != target + || d_ptr->m_up != baseUp) { + setPosition(basePosition); + d_ptr->m_target = target; + d_ptr->m_up = baseUp; + setDirty(true); + } +} + +/*! + * \property Q3DCamera::viewMatrix + * + * This property contains the view matrix used in the 3D calculations. When the default orbiting camera behavior is sufficient + * there is no need to touch this property. But if the default behavior is insufficient the view matrix can be set directly. + * When setting the view matrix directly remember to set Q3DCamera::viewMatrixAutoUpdateEnabled to false. + */ +QMatrix4x4 Q3DCamera::viewMatrix() const +{ + return d_ptr->m_viewMatrix; +} + +void Q3DCamera::setViewMatrix(const QMatrix4x4 &viewMatrix) +{ + if (d_ptr->m_viewMatrix != viewMatrix) { + d_ptr->m_viewMatrix = viewMatrix; + setDirty(true); + emit viewMatrixChanged(d_ptr->m_viewMatrix); + } +} + +/*! + * \property Q3DCamera::viewMatrixAutoUpdateEnabled + * + * This property determines if view matrix is automatically updated each render cycle using the current base orientation and + * rotations. If set to false, no automatic recalculation is done and the view matrix can be set using the + * Q3DMatrix::viewMatrix property. + */ +bool Q3DCamera::isViewMatrixAutoUpdateEnabled() +{ + return d_ptr->m_isViewMatrixUpdateActive; +} + +void Q3DCamera::setViewMatrixAutoUpdateEnabled(bool isEnabled) +{ + d_ptr->m_isViewMatrixUpdateActive = isEnabled; + emit viewMatrixAutoUpdateChanged(isEnabled); +} + +/*! + * \property Q3DCamera::cameraPreset + * + * This property contains the currently active camera preset, + * if no preset is active the value is QDataVis::CameraPresetNone. + * \note The base camera orientation set by setBaseOrientation() will affect + * the presets as all calculations are based on those values. + */ +QDataVis::CameraPreset Q3DCamera::cameraPreset() +{ + return d_ptr->m_activePreset; +} + +void Q3DCamera::setCameraPreset(QDataVis::CameraPreset preset) +{ + switch (preset) { + case QDataVis::CameraPresetFrontLow: { + setXRotation(0.0); + setYRotation(0.0); + break; + } + case QDataVis::CameraPresetFront: { + setXRotation(0.0); + setYRotation(22.5); + break; + } + case QDataVis::CameraPresetFrontHigh: { + setXRotation(0.0); + setYRotation(45.0); + break; + } + case QDataVis::CameraPresetLeftLow: { + setXRotation(90.0); + setYRotation(0.0); + break; + } + case QDataVis::CameraPresetLeft: { + setXRotation(90.0); + setYRotation(22.5); + break; + } + case QDataVis::CameraPresetLeftHigh: { + setXRotation(90.0); + setYRotation(45.0); + break; + } + case QDataVis::CameraPresetRightLow: { + setXRotation(-90.0); + setYRotation(0.0); + break; + } + case QDataVis::CameraPresetRight: { + setXRotation(-90.0); + setYRotation(22.5); + break; + } + case QDataVis::CameraPresetRightHigh: { + setXRotation(-90.0); + setYRotation(45.0); + break; + } + case QDataVis::CameraPresetBehindLow: { + setXRotation(180.0); + setYRotation(0.0); + break; + } + case QDataVis::CameraPresetBehind: { + setXRotation(180.0); + setYRotation(22.5); + break; + } + case QDataVis::CameraPresetBehindHigh: { + setXRotation(180.0); + setYRotation(45.0); + break; + } + case QDataVis::CameraPresetIsometricLeft: { + setXRotation(45.0); + setYRotation(22.5); + break; + } + case QDataVis::CameraPresetIsometricLeftHigh: { + setXRotation(45.0); + setYRotation(45.0); + break; + } + case QDataVis::CameraPresetIsometricRight: { + setXRotation(-45.0); + setYRotation(22.5); + break; + } + case QDataVis::CameraPresetIsometricRightHigh: { + setXRotation(-45.0); + setYRotation(45.0); + break; + } + case QDataVis::CameraPresetDirectlyAbove: { + setXRotation(0.0); + setYRotation(90.0); + break; + } + case QDataVis::CameraPresetDirectlyAboveCW45: { + setXRotation(-45.0); + setYRotation(90.0); + break; + } + case QDataVis::CameraPresetDirectlyAboveCCW45: { + setXRotation(45.0); + setYRotation(90.0); + break; + } + case QDataVis::CameraPresetFrontBelow: { + setXRotation(0.0); + setYRotation(-45.0); + break; + } + case QDataVis::CameraPresetLeftBelow: { + setXRotation(90.0); + setYRotation(-45.0); + break; + } + case QDataVis::CameraPresetRightBelow: { + setXRotation(-90.0); + setYRotation(-45.0); + break; + } + case QDataVis::CameraPresetBehindBelow: { + setXRotation(180.0); + setYRotation(-45.0); + break; + } + case QDataVis::CameraPresetDirectlyBelow: { + setXRotation(0.0); + setYRotation(-90.0); + break; + } + default: + preset = QDataVis::CameraPresetNone; + break; + } + + if (d_ptr->m_activePreset != preset) { + d_ptr->m_activePreset = preset; + setDirty(true); + emit cameraPresetChanged(preset); + } +} + +/*! + * \property Q3DCamera::zoomLevel + * + * This property contains the the camera zoom level in percentages. + * 100% means there is no zoom in or out set in the camera. + */ +int Q3DCamera::zoomLevel() +{ + return d_ptr->m_zoomLevel; +} + +void Q3DCamera::setZoomLevel(int zoomLevel) +{ + if (d_ptr->m_zoomLevel != zoomLevel) { + d_ptr->m_zoomLevel = zoomLevel; + setDirty(true); + emit zoomLevelChanged(zoomLevel); + } +} + +/*! + * Calculates and returns a position relative to the camera using the given parameters + * and the current camera viewMatrix property. + * \a relativePosition defines the relative 3D offset to the current camera position. + * \a fixedRotation is optional, if given fixes rotation of the calculated point around the data visualization area to the given value in degrees. + * \a distanceModifier is also optional, if given modifies the distance of the calculated point from the data visualization. + * \return Calculated position relative to this camera's position. + */ +QVector3D Q3DCamera::calculatePositionRelativeToCamera(const QVector3D &relativePosition, + qreal fixedRotation, + qreal distanceModifier) const +{ + // Move the position with camera + GLfloat radiusFactor = relativePosition.z() * (1.5f + distanceModifier); + GLfloat xAngle; + GLfloat yAngle; + if (!fixedRotation) { + xAngle = qDegreesToRadians(d_ptr->m_xRotation); + yAngle = qDegreesToRadians(d_ptr->m_yRotation); + } else { + xAngle = qDegreesToRadians(fixedRotation); + yAngle = 0; + } + GLfloat radius = (radiusFactor + relativePosition.y()); // set radius to match the highest height of the position + GLfloat zPos = radius * qCos(xAngle) * qCos(yAngle); + GLfloat xPos = radius * qSin(xAngle) * qCos(yAngle); + GLfloat yPos = (radiusFactor + relativePosition.y()) * qSin(yAngle); + // Keep in the set position in relation to camera + return QVector3D(-xPos + relativePosition.x(), + yPos + relativePosition.y(), + zPos + relativePosition.z()); +} + +/*! + * \property Q3DCamera::wrapXRotation + * + * This property determines the behavior of the minimum and maximum limits in the X-rotation. + * By default the X-rotation wraps from minimum value to maximum and from maximum to minimum. + * + * If set to true the X-rotation of the camera is wrapped from minimum to maximum and from maximum to minimum. + * If set to false the X-rotation of the camera is limited to the sector determined by minimum and maximum values. + */ +bool Q3DCamera::wrapXRotation() const +{ + return d_ptr->m_wrapXRotation; +} + +void Q3DCamera::setWrapXRotation(bool isEnabled) +{ + d_ptr->m_wrapXRotation = isEnabled; +} + +/*! + * \property Q3DCamera::wrapYRotation + * + * This property determines the behavior of the minimum and maximum limits in the Y-rotation. + * By default the Y-rotation is limited between the minimum and maximum values without any wrapping. + * + * If true the Y-rotation of the camera is wrapped from minimum to maximum and from maximum to minimum. + * If false the Y-rotation of the camera is limited to the sector determined by minimum and maximum values. + */ +bool Q3DCamera::wrapYRotation() const +{ + return d_ptr->m_wrapYRotation; +} + +void Q3DCamera::setWrapYRotation(bool isEnabled) +{ + d_ptr->m_wrapYRotation = isEnabled; +} + +/*! + * Utility function that sets the camera rotations and distance.\a horizontal and \a vertical define the camera rotations to be used. + * Optional \a zoom parameter can be given to set the zoom of the camera in range of 10-500%. + */ +void Q3DCamera::setCameraPosition(qreal horizontal, qreal vertical, qreal zoom) +{ + setZoomLevel(qBound(10.0, zoom, 500.0)); + setXRotation(horizontal); + setYRotation(vertical); +} + +Q3DCameraPrivate::Q3DCameraPrivate(Q3DCamera *q) : + q_ptr(q), + m_isViewMatrixUpdateActive(true), + m_xRotation(0.0), + m_yRotation(0.0), + m_minXRotation(-180.0), + m_minYRotation(0.0), + m_maxXRotation(180.0), + m_maxYRotation(90.0), + m_wrapXRotation(true), + m_wrapYRotation(false), + m_zoomLevel(100), + m_activePreset(QDataVis::CameraPresetNone) +{ +} + +Q3DCameraPrivate::~Q3DCameraPrivate() +{ +} + +// Copies changed values from this camera to the other camera. If the other camera had same changes, +// those changes are discarded. +void Q3DCameraPrivate::sync(Q3DCamera &other) +{ + if (q_ptr->isDirty()) { + other.copyValuesFrom(*q_ptr); + q_ptr->setDirty(false); + other.setDirty(false); + } +} + +void Q3DCameraPrivate::setXRotation(const qreal rotation) +{ + if (m_xRotation != rotation) { + m_xRotation = rotation; + q_ptr->setDirty(true); + } +} + +void Q3DCameraPrivate::setYRotation(const qreal rotation) +{ + if (m_yRotation != rotation) { + m_yRotation = rotation; + q_ptr->setDirty(true); + } +} + +void Q3DCameraPrivate::setMinXRotation(const qreal rotation) +{ + if (m_minXRotation != rotation) { + m_minXRotation = rotation; + q_ptr->setDirty(true); + } +} + +void Q3DCameraPrivate::setMinYRotation(const qreal rotation) +{ + if (m_minYRotation != rotation) { + m_minYRotation = rotation; + q_ptr->setDirty(true); + } +} + +void Q3DCameraPrivate::setMaxXRotation(const qreal rotation) +{ + if (m_maxXRotation != rotation) { + m_maxXRotation = rotation; + q_ptr->setDirty(true); + } +} + +void Q3DCameraPrivate::setMaxYRotation(const qreal rotation) +{ + if (m_maxYRotation != rotation) { + m_maxYRotation = rotation; + q_ptr->setDirty(true); + } +} + +// Recalculates the view matrix based on the currently set base orientation, rotation and zoom level values. +// zoomAdjustment is adjustment to ensure that the 3D visualization stays inside the view area in the 100% zoom. +void Q3DCameraPrivate::updateViewMatrix(qreal zoomAdjustment) +{ + if (!m_isViewMatrixUpdateActive) + return; + + int zoom = m_zoomLevel * zoomAdjustment; + QMatrix4x4 viewMatrix; + + // Apply to view matrix + viewMatrix.lookAt(q_ptr->position(), m_target, m_up); + // Compensate for translation (if d_ptr->m_target is off origin) + viewMatrix.translate(m_target.x(), m_target.y(), m_target.z()); + // Apply rotations + // Handle x and z rotation when y -angle is other than 0 + viewMatrix.rotate(m_xRotation, 0, qCos(qDegreesToRadians(m_yRotation)), + qSin(qDegreesToRadians(m_yRotation))); + // y rotation is always "clean" + viewMatrix.rotate(m_yRotation, 1.0f, 0.0f, 0.0f); + // handle zoom by scaling + viewMatrix.scale((GLfloat)zoom / 100.0f); + // Compensate for translation (if d_ptr->m_target is off origin) + viewMatrix.translate(-m_target.x(), -m_target.y(), -m_target.z()); + + q_ptr->setViewMatrix(viewMatrix); +} + + +QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavisualization/engine/q3dcamera.h b/src/datavisualization/engine/q3dcamera.h new file mode 100644 index 00000000..ee750cec --- /dev/null +++ b/src/datavisualization/engine/q3dcamera.h @@ -0,0 +1,131 @@ +/**************************************************************************** +** +** 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 Q3DCAMERA_H +#define Q3DCAMERA_H + +#include <QtDataVisualization/q3dobject.h> +#include <QMatrix4x4> + +class QVector3D; +class QPoint; + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +class Q3DCameraPrivate; + +class QT_DATAVISUALIZATION_EXPORT Q3DCamera : public Q3DObject +{ + Q_OBJECT + Q_PROPERTY(qreal xRotation READ xRotation WRITE setXRotation NOTIFY xRotationChanged) + Q_PROPERTY(qreal yRotation READ yRotation WRITE setYRotation NOTIFY yRotationChanged) + Q_PROPERTY(qreal minXRotation READ minXRotation NOTIFY minXRotationChanged) + Q_PROPERTY(qreal minYRotation READ minYRotation NOTIFY minYRotationChanged) + Q_PROPERTY(qreal maxXRotation READ maxXRotation NOTIFY maxXRotationChanged) + Q_PROPERTY(qreal maxYRotation READ maxYRotation NOTIFY maxYRotationChanged) + Q_PROPERTY(int zoomLevel READ zoomLevel WRITE setZoomLevel NOTIFY zoomLevelChanged) + Q_PROPERTY(QMatrix4x4 viewMatrix READ viewMatrix WRITE setViewMatrix NOTIFY viewMatrixChanged) + Q_PROPERTY(QtDataVisualization::QDataVis::CameraPreset cameraPreset READ cameraPreset WRITE setCameraPreset NOTIFY cameraPresetChanged) + Q_PROPERTY(bool viewMatrixAutoUpdateEnabled READ isViewMatrixAutoUpdateEnabled WRITE setViewMatrixAutoUpdateEnabled NOTIFY viewMatrixAutoUpdateChanged) + Q_PROPERTY(bool wrapXRotation READ wrapXRotation WRITE setWrapXRotation NOTIFY wrapXRotationChanged ) + Q_PROPERTY(bool wrapYRotation READ wrapYRotation WRITE setWrapYRotation NOTIFY wrapYRotationChanged ) + Q_ENUMS(QtDataVisualization::QDataVis::CameraPreset) + +public: + Q3DCamera(QObject *parent = 0); + virtual ~Q3DCamera(); + + qreal xRotation() const; + void setXRotation(qreal rotation); + qreal yRotation() const; + void setYRotation(qreal rotation); + + qreal minXRotation() const; + qreal maxXRotation() const; + + qreal minYRotation() const; + qreal maxYRotation() const; + + bool wrapXRotation() const; + void setWrapXRotation(bool isEnabled); + + bool wrapYRotation() const; + void setWrapYRotation(bool isEnabled); + + void copyValuesFrom(const Q3DCamera &source); + + QMatrix4x4 viewMatrix() const; + void setViewMatrix(const QMatrix4x4 &viewMatrix); + + bool isViewMatrixAutoUpdateEnabled(); + void setViewMatrixAutoUpdateEnabled(bool isEnabled); + + QDataVis::CameraPreset cameraPreset(); + void setCameraPreset(QDataVis::CameraPreset preset); + + int zoomLevel(); + void setZoomLevel(int zoomLevel); + + void setBaseOrientation(const QVector3D &defaultPosition, + const QVector3D &defaultTarget, + const QVector3D &defaultUp); + + QVector3D calculatePositionRelativeToCamera(const QVector3D &relativePosition, + qreal fixedRotation, + qreal distanceModifier) const; + void setCameraPosition(qreal horizontal, qreal vertical, qreal distance = 100.0); + +signals: + void xRotationChanged(qreal rotation); + void yRotationChanged(qreal rotation); + void minXRotationChanged(qreal rotation); + void minYRotationChanged(qreal rotation); + void maxXRotationChanged(qreal rotation); + void maxYRotationChanged(qreal rotation); + void zoomLevelChanged(int zoomLevel); + void viewMatrixChanged(QMatrix4x4 viewMatrix); + void cameraPresetChanged(QDataVis::CameraPreset preset); + void viewMatrixAutoUpdateChanged(bool enabled); + void wrapXRotationChanged(bool isEnabled); + void wrapYRotationChanged(bool isEnabled); + +protected: + void setMinXRotation(qreal rotation); + void setMinYRotation(qreal rotation); + void setMaxXRotation(qreal rotation); + void setMaxYRotation(qreal rotation); + +private: + QScopedPointer<Q3DCameraPrivate> d_ptr; + + Q_DISABLE_COPY(Q3DCamera) + + friend class Q3DCameraPrivate; + friend class Q3DScenePrivate; + friend class Bars3DRenderer; + friend class Surface3DRenderer; + friend class Scatter3DRenderer; + friend class SelectionPointer; + friend class Q3DInputHandler; + friend class QTouch3DInputHandlerPrivate; + friend class QMac3DInputHandler; +}; + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif // Q3DCAMERA_H diff --git a/src/datavisualization/engine/q3dcamera_p.h b/src/datavisualization/engine/q3dcamera_p.h new file mode 100644 index 00000000..e0528dcc --- /dev/null +++ b/src/datavisualization/engine/q3dcamera_p.h @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** 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 Q3DCAMERA_P_H +#define Q3DCAMERA_P_H + +#include "datavisualizationglobal_p.h" +#include "q3dcamera.h" + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +class Q3DCamera; + +class Q3DCameraPrivate +{ +public: + Q3DCameraPrivate(Q3DCamera *q); + ~Q3DCameraPrivate(); + + void sync(Q3DCamera &other); + + void setXRotation(qreal rotation); + void setYRotation(qreal rotation); + void setMinXRotation(qreal rotation); + void setMinYRotation(qreal rotation); + void setMaxXRotation(qreal rotation); + void setMaxYRotation(qreal rotation); + + void updateViewMatrix(qreal zoomAdjustment); + +public: + Q3DCamera *q_ptr; + + QVector3D m_target; + QVector3D m_up; + + QMatrix4x4 m_viewMatrix; + bool m_isViewMatrixUpdateActive; + + GLfloat m_xRotation; + GLfloat m_yRotation; + GLfloat m_minXRotation; + GLfloat m_minYRotation; + GLfloat m_maxXRotation; + GLfloat m_maxYRotation; + bool m_wrapXRotation; + bool m_wrapYRotation; + int m_zoomLevel; + QDataVis::CameraPreset m_activePreset; + + friend class Bars3DRenderer; + friend class Surface3DRenderer; + friend class Scatter3DRenderer; + friend class SelectionPointer; + friend class Q3DInputHandler; + friend class QTouch3DInputHandler; + friend class QMac3DInputHandler; +}; + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif // Q3DCAMERA_P_H diff --git a/src/datavisualization/engine/q3dlight.cpp b/src/datavisualization/engine/q3dlight.cpp new file mode 100644 index 00000000..c482e62a --- /dev/null +++ b/src/datavisualization/engine/q3dlight.cpp @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** 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 "q3dlight.h" +#include "q3dscene.h" +#include "q3dlight_p.h" + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +/*! + \class Q3DLight + \inmodule QtDataVisualization + \brief Representation of a light source in 3D space. + \since 1.0.0 + + Q3DLight represents a monochrome non variable light source in 3D space. +*/ + +/*! + * Constructs a new 3D light located at origo. An optional \a parent parameter can be given + * and is then passed to QObject constructor. + */ +Q3DLight::Q3DLight(QObject *parent) : + Q3DObject(parent), + d_ptr(new Q3DLightPrivate(this)) +{ +} + +/*! + * Copies the properties of the 3D light from the given source \a source light to this light instance. + */ +void Q3DLight::copyValuesFrom(const Q3DLight &source) +{ + Q3DObject::copyValuesFrom(source); +} + +/*! + * Destroys the light object. + */ +Q3DLight::~Q3DLight() +{ +} + +Q3DLightPrivate::Q3DLightPrivate(Q3DLight *q) : + q_ptr(q) +{ +} + +Q3DLightPrivate::~Q3DLightPrivate() +{ +} + +void Q3DLightPrivate::sync(Q3DLight &other) +{ + // Copies changed values from this light to the other light. If the other light had same changes, + // those changes are discarded. + if (q_ptr->isDirty()) { + other.copyValuesFrom(*q_ptr); + q_ptr->setDirty(false); + other.setDirty(false); + } +} + +QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavisualization/engine/q3dlight.h b/src/datavisualization/engine/q3dlight.h new file mode 100644 index 00000000..0a4ba174 --- /dev/null +++ b/src/datavisualization/engine/q3dlight.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 +** +****************************************************************************/ + +#ifndef Q3DLIGHT_H +#define Q3DLIGHT_H + +#include <QtDataVisualization/q3dobject.h> + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +class Q3DLightPrivate; +class Q3DScene; + +class QT_DATAVISUALIZATION_EXPORT Q3DLight : public Q3DObject +{ + Q_OBJECT + +public: + Q3DLight(QObject *parent = 0); + virtual ~Q3DLight(); + + void copyValuesFrom(const Q3DLight &source); + +private: + QScopedPointer<Q3DLightPrivate> d_ptr; + + Q_DISABLE_COPY(Q3DLight) + + friend class Q3DLightPrivate; + friend class Q3DScenePrivate; +}; + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif // Q3DLIGHT_H diff --git a/src/datavisualization/engine/q3dlight_p.h b/src/datavisualization/engine/q3dlight_p.h new file mode 100644 index 00000000..dad6d670 --- /dev/null +++ b/src/datavisualization/engine/q3dlight_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 Q3DLIGHT_P_H +#define Q3DLIGHT_P_H + +#include "datavisualizationglobal_p.h" +#include "q3dlight.h" + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +class Q3DScene; +class Q3DLight; + +class Q3DLightPrivate +{ +public: + Q3DLightPrivate(Q3DLight *q); + ~Q3DLightPrivate(); + + void sync(Q3DLight &other); + +public: + Q3DLight *q_ptr; +}; + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif // Q3DLIGHT_P_H + + + + + diff --git a/src/datavisualization/engine/q3dobject.cpp b/src/datavisualization/engine/q3dobject.cpp new file mode 100644 index 00000000..ae13af7d --- /dev/null +++ b/src/datavisualization/engine/q3dobject.cpp @@ -0,0 +1,121 @@ +/**************************************************************************** +** +** 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 "q3dobject.h" +#include "q3dobject_p.h" +#include "q3dscene.h" + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +/*! + \class Q3DObject + \inmodule QtDataVisualization + \brief Simple baseclass for all the objects in the 3D scene. + \since 1.0.0 + + Q3DObject is a baseclass that contains only position information for an object in 3D scene. + The object is considered to be a single point in the coordinate space without dimensions. +*/ + +/*! + * Constructs a new 3D object with position set to origo by default. An + * optional \a parent parameter can be given and is then passed to QObject constructor. + */ +Q3DObject::Q3DObject(QObject *parent) : + QObject(parent), + d_ptr(new Q3DObjectPrivate(this)) +{ +} + +/*! + * Destroys the 3D object. + */ +Q3DObject::~Q3DObject() +{ +} + +/*! + * Copies the 3D object position from the given \a source 3D object to this 3D object instance. + */ +void Q3DObject::copyValuesFrom(const Q3DObject &source) +{ + d_ptr->m_position.setX(source.d_ptr->m_position.x()); + d_ptr->m_position.setY(source.d_ptr->m_position.y()); + d_ptr->m_position.setZ(source.d_ptr->m_position.z()); + setDirty(true); +} + +/*! + * \property Q3DObject::parentScene + * + * This property contains the parent scene as read only value. + * If the object has no parent scene the value is 0. + */ +Q3DScene *Q3DObject::parentScene() +{ + return qobject_cast<Q3DScene *>(parent()); +} + +/*! + * \property Q3DObject::position + * + * This property contains the 3D position of the object. + */ +QVector3D Q3DObject::position() const +{ + return d_ptr->m_position; +} + +void Q3DObject::setPosition(const QVector3D &position) +{ + if (d_ptr->m_position != position) { + d_ptr->m_position = position; + setDirty(true); + emit positionChanged(d_ptr->m_position); + } +} + +/*! + * Sets and clears the \a dirty flag that is used to track + * when the 3D object has changed since last update. + */ +void Q3DObject::setDirty(bool dirty) +{ + d_ptr->m_isDirty = dirty; +} + +/*! + * \return flag that indicates if the 3D object has changed. + */ +bool Q3DObject::isDirty() const +{ + return d_ptr->m_isDirty; +} + +Q3DObjectPrivate::Q3DObjectPrivate(Q3DObject *q) : + q_ptr(q), + m_isDirty(true) +{ +} + +Q3DObjectPrivate::~Q3DObjectPrivate() +{ + +} + +QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavisualization/engine/q3dobject.h b/src/datavisualization/engine/q3dobject.h new file mode 100644 index 00000000..930bb022 --- /dev/null +++ b/src/datavisualization/engine/q3dobject.h @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** 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 Q3DOBJECT_H +#define Q3DOBJECT_H + +#include <QtDataVisualization/qdatavisualizationenums.h> +#include <QtDataVisualization/q3dscene.h> + +#include <QObject> +#include <QVector3D> + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE +class Q3DObjectPrivate; + +class Q3DObject : public QObject +{ + Q_OBJECT + Q_PROPERTY(Q3DScene* parentScene READ parentScene) + Q_PROPERTY(QVector3D position READ position WRITE setPosition NOTIFY positionChanged) + +public: + Q3DObject(QObject *parent = 0); + virtual ~Q3DObject(); + + void copyValuesFrom(const Q3DObject &source); + + Q3DScene *parentScene(); + + QVector3D position() const; + void setPosition(const QVector3D &position); + +signals: + void positionChanged(QVector3D position); + +protected: + void setDirty(bool dirty); + bool isDirty() const; + +private: + QScopedPointer<Q3DObjectPrivate> d_ptr; + + Q_DISABLE_COPY(Q3DObject) + + friend class Q3DScenePrivate; +}; + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif // Q3DOBJECT_H diff --git a/src/datavisualization/engine/q3dobject_p.h b/src/datavisualization/engine/q3dobject_p.h new file mode 100644 index 00000000..bac18cfe --- /dev/null +++ b/src/datavisualization/engine/q3dobject_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 Q3DOBJECT_P_H +#define Q3DOBJECT_P_H + +#include "datavisualizationglobal_p.h" + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +class Q3DObject; +class Q3DScene; + +class Q3DObjectPrivate +{ +public: + Q3DObjectPrivate(Q3DObject *q); + ~Q3DObjectPrivate(); + +public: + Q3DObject *q_ptr; + QVector3D m_position; + bool m_isDirty; +}; + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif // Q3DOBJECT_P_H diff --git a/src/datavisualization/engine/q3dscatter.cpp b/src/datavisualization/engine/q3dscatter.cpp new file mode 100644 index 00000000..a5053bf3 --- /dev/null +++ b/src/datavisualization/engine/q3dscatter.cpp @@ -0,0 +1,568 @@ +/**************************************************************************** +** +** 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 "q3dscatter.h" +#include "q3dscatter_p.h" +#include "scatter3dcontroller_p.h" +#include "q3dvalueaxis.h" +#include "qscatterdataproxy.h" +#include "q3dcamera.h" + +#include <QMouseEvent> +#include <QDebug> + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +/*! + * \class Q3DScatter + * \inmodule QtDataVisualization + * \brief The Q3DScatter class provides methods for rendering 3D scatter graphs. + * \since 1.0.0 + * + * This class enables developers to render scatter graphs in 3D and to view them by rotating the scene + * freely. Rotation is done by holding down the right mouse button and moving the mouse. Zooming + * is done by mouse wheel. Selection, if enabled, is done by left mouse button. The scene can be + * reset to default camera view by clicking mouse wheel. In touch devices rotation is done + * by tap-and-move, selection by tap-and-hold and zoom by pinch. + * + * If no axes are explicitly set to Q3DScatter, temporary default axes with no labels are created. + * These default axes can be modified via axis accessors, but as soon any axis is explicitly + * set for the orientation, the default axis for that orientation is destroyed. + * + * Data proxies work similarly: If no data proxy is explicitly set, Q3DScatter creates a default + * proxy. If any other proxy is set as active data proxy later, the default proxy and all data + * added to it is destroyed. + * + * Methods are provided for changing item styles, themes, item selection modes and so on. See the + * methods for more detailed descriptions. + * + * \section1 How to construct a minimal Q3DScatter graph + * + * First, construct Q3DScatter: + * + * \snippet doc_src_q3dscatter_construction.cpp 0 + * + * Now Q3DScatter is ready to receive data to be rendered. Add one set of 3 QVector3D items: + * + * \snippet doc_src_q3dscatter_construction.cpp 1 + * + * Finally you will need to set it visible: + * + * \snippet doc_src_q3dscatter_construction.cpp 2 + * + * The complete code needed to create and display this graph is: + * + * \snippet doc_src_q3dscatter_construction.cpp 3 + * + * And this is what those few lines of code produce: + * + * \image q3dscatter-minimal.png + * + * The scene can be rotated and zoomed into, but no other interaction is included in this minimal + * code example. You can learn more by familiarizing yourself with the examples provided, like + * the \l{Scatter Example}. + * + * \sa Q3DBars, Q3DSurface, {Qt Data Visualization C++ Classes} + */ + +/*! + * Constructs a new 3D scatter window. + */ +Q3DScatter::Q3DScatter() + : d_ptr(new Q3DScatterPrivate(this, geometry())) +{ + setVisualController(d_ptr->m_shared); + d_ptr->m_shared->initializeOpenGL(); + QObject::connect(d_ptr->m_shared, &Scatter3DController::selectedItemIndexChanged, this, + &Q3DScatter::selectedItemIndexChanged); + QObject::connect(d_ptr->m_shared, &Abstract3DController::needRender, this, + &Q3DWindow::renderLater); +} + +/*! + * Destroys the 3D scatter window. + */ +Q3DScatter::~Q3DScatter() +{ +} + +/*! + * \internal + */ +void Q3DScatter::mouseDoubleClickEvent(QMouseEvent *event) +{ + d_ptr->m_shared->mouseDoubleClickEvent(event); +} + +/*! + * \internal + */ +void Q3DScatter::touchEvent(QTouchEvent *event) +{ + d_ptr->m_shared->touchEvent(event); +} + +/*! + * \internal + */ +void Q3DScatter::mousePressEvent(QMouseEvent *event) +{ + d_ptr->m_shared->mousePressEvent(event, event->pos()); +} + +/*! + * \internal + */ +void Q3DScatter::mouseReleaseEvent(QMouseEvent *event) +{ + d_ptr->m_shared->mouseReleaseEvent(event, event->pos()); +} + +/*! + * \internal + */ +void Q3DScatter::mouseMoveEvent(QMouseEvent *event) +{ + d_ptr->m_shared->mouseMoveEvent(event, event->pos()); +} + +/*! + * \internal + */ +void Q3DScatter::wheelEvent(QWheelEvent *event) +{ + d_ptr->m_shared->wheelEvent(event); +} + +/*! + * \internal + */ +void Q3DScatter::resizeEvent(QResizeEvent *event) +{ + Q_UNUSED(event); + d_ptr->m_shared->setSize(width(), height()); +} + +/*! + * Sets window \a width. + */ +void Q3DScatter::setWidth(const int width) +{ + d_ptr->m_shared->setWidth(width); + QWindow::setWidth(width); +} + +/*! + * Sets window \a height. + */ +void Q3DScatter::setHeight(const int height) +{ + d_ptr->m_shared->setHeight(height); + QWindow::setHeight(height); +} + +/*! + * Sets the item \a style to one of the values in \c QDataVis::MeshStyle. It is preset to + * \c QDataVis::MeshStyleSpheres by default. A \a smooth flag can be used to set shading to smooth. + * It is \c false by default. + * + * \sa setMeshFileName() + */ +void Q3DScatter::setObjectType(QDataVis::MeshStyle style, bool smooth) +{ + d_ptr->m_shared->setObjectType(style, smooth); +} + +/*! + * Sets a predefined \a theme from \c QDataVis::Theme. It is preset to \c QDataVis::ThemeQt by + * default. Theme affects bar colors, label colors, text color, background color, window color and + * grid color. Lighting is also adjusted by themes. + * + * \sa setObjectColor() + * + * \warning This method is subject to change. + */ +void Q3DScatter::setTheme(QDataVis::Theme theme) +{ + d_ptr->m_shared->setTheme(theme); +} + +/*! + * Set item color using your own colors. \a baseColor sets the base color of a item. The \a uniform + * -flag is used to define if color needs to be uniform throughout item's length, or will the colors + * be applied by height. It is \c true by default. + * + * Calling this method overrides colors from theme. + * + * \sa setTheme() + * + * \warning This method is subject to change. + */ +void Q3DScatter::setObjectColor(const QColor &baseColor, bool uniform) +{ + d_ptr->m_shared->setObjectColor(baseColor, uniform); +} + +/*! + * \return item color in use. + */ +QColor Q3DScatter::objectColor() const +{ + return d_ptr->m_shared->objectColor(); +} + +/*! + * \property Q3DScatter::selectionMode + * + * Sets item selection \a mode to one of \c QDataVis::SelectionMode. It is preset to + * \c QDataVis::SelectionModeItem by default. + */ +void Q3DScatter::setSelectionMode(QDataVis::SelectionMode mode) +{ + d_ptr->m_shared->setSelectionMode(mode); +} + +QDataVis::SelectionMode Q3DScatter::selectionMode() const +{ + return d_ptr->m_shared->selectionMode(); +} + +/*! + * \property Q3DScatter::meshFileName + * + * Override item type with a mesh object located in \a objFileName. + * \note Object needs to be in Wavefront obj format and include vertices, normals and UVs. + * It also needs to be in triangles. + * + * \sa setObjectType() + */ +void Q3DScatter::setMeshFileName(const QString &objFileName) +{ + d_ptr->m_shared->setMeshFileName(objFileName); +} + +QString Q3DScatter::meshFileName() const +{ + return d_ptr->m_shared->meshFileName(); +} + +/*! + * \property Q3DScatter::font + * + * Sets the \a font for labels. It is preset to \c Arial by default. + */ +void Q3DScatter::setFont(const QFont &font) +{ + d_ptr->m_shared->setFont(font); +} + +QFont Q3DScatter::font() const +{ + return d_ptr->m_shared->font(); +} + +/*! + * \property Q3DScatter::scene + * + * This property contains the read only Q3DScene that can be used to access e.g. camera object. + */ +Q3DScene *Q3DScatter::scene() const +{ + return d_ptr->m_shared->scene(); +} + +/*! + * \property Q3DScatter::labelStyle + * + * Sets label \a style to one of \c QDataVis::LabelStyle. It is preset to + * \c QDataVis::LabelStyleFromTheme by default. + */ +void Q3DScatter::setLabelStyle(QDataVis::LabelStyle style) +{ + d_ptr->m_shared->setLabelStyle(style); +} + +QDataVis::LabelStyle Q3DScatter::labelStyle() const +{ + return d_ptr->m_shared->labelStyle(); +} + +/*! + * \property Q3DScatter::gridVisible + * + * Sets grid visibility to \a visible. It is preset to \c true by default. + */ +void Q3DScatter::setGridVisible(bool visible) +{ + d_ptr->m_shared->setGridEnabled(visible); +} + +bool Q3DScatter::isGridVisible() const +{ + return d_ptr->m_shared->gridEnabled(); +} + +/*! + * \property Q3DScatter::backgroundVisible + * + * Sets background visibility to \a visible. It is preset to \c true by default. + */ +void Q3DScatter::setBackgroundVisible(bool visible) +{ + d_ptr->m_shared->setBackgroundEnabled(visible); +} + +bool Q3DScatter::isBackgroundVisible() const +{ + return d_ptr->m_shared->backgroundEnabled(); +} + +/*! + * \property Q3DScatter::selectedItemIndex + * + * Selects an item in the \a index. Only one item can be selected at a time. + * To clear selection, specify an illegal \a index, e.g. -1. + */ +void Q3DScatter::setSelectedItemIndex(int index) +{ + d_ptr->m_shared->setSelectedItemIndex(index); +} + +int Q3DScatter::selectedItemIndex() const +{ + return d_ptr->m_shared->selectedItemIndex(); +} + +/*! + * \property Q3DScatter::shadowQuality + * + * Sets shadow \a quality to one of \c QDataVis::ShadowQuality. It is preset to + * \c QDataVis::ShadowQualityMedium by default. + * + * \note If setting QDataVis::ShadowQuality of a certain level fails, a level is lowered + * until it is successful and shadowQualityChanged signal is emitted for each time the change is + * done. + */ +void Q3DScatter::setShadowQuality(QDataVis::ShadowQuality quality) +{ + return d_ptr->m_shared->setShadowQuality(quality); +} + +QDataVis::ShadowQuality Q3DScatter::shadowQuality() const +{ + return d_ptr->m_shared->shadowQuality(); +} + +/*! + * Sets a user-defined X-axis. Implicitly calls addAxis() to transfer ownership + * of the \a axis to this graph. + * + * If the \a axis is null, a temporary default axis with no labels and automatically adjusting + * range is created. + * This temporary axis is destroyed if another \a axis is explicitly set to same orientation. + * + * \sa addAxis(), releaseAxis() + */ +void Q3DScatter::setAxisX(Q3DValueAxis *axis) +{ + d_ptr->m_shared->setAxisX(axis); +} + +/*! + * \return used X-axis. + */ +Q3DValueAxis *Q3DScatter::axisX() const +{ + return static_cast<Q3DValueAxis *>(d_ptr->m_shared->axisX()); +} + +/*! + * Sets a user-defined Y-axis. Implicitly calls addAxis() to transfer ownership + * of the \a axis to this graph. + * + * If the \a axis is null, a temporary default axis with no labels and automatically adjusting + * range is created. + * This temporary axis is destroyed if another \a axis is explicitly set to same orientation. + * + * \sa addAxis(), releaseAxis() + */ +void Q3DScatter::setAxisY(Q3DValueAxis *axis) +{ + d_ptr->m_shared->setAxisY(axis); +} + +/*! + * \return used Y-axis. + */ +Q3DValueAxis *Q3DScatter::axisY() const +{ + return static_cast<Q3DValueAxis *>(d_ptr->m_shared->axisY()); +} + +/*! + * Sets a user-defined Z-axis. Implicitly calls addAxis() to transfer ownership + * of the \a axis to this graph. + * + * If the \a axis is null, a temporary default axis with no labels and automatically adjusting + * range is created. + * This temporary axis is destroyed if another \a axis is explicitly set to same orientation. + * + * \sa addAxis(), releaseAxis() + */ +void Q3DScatter::setAxisZ(Q3DValueAxis *axis) +{ + d_ptr->m_shared->setAxisZ(axis); +} + +/*! + * \return used Z-axis. + */ +Q3DValueAxis *Q3DScatter::axisZ() const +{ + return static_cast<Q3DValueAxis *>(d_ptr->m_shared->axisZ()); +} + +/*! + * Adds \a axis to the graph. The axes added via addAxis are not yet taken to use, + * addAxis is simply used to give the ownership of the \a axis to the graph. + * The \a axis must not be null or added to another graph. + * + * \sa releaseAxis(), setAxisX(), setAxisY(), setAxisZ() + */ +void Q3DScatter::addAxis(Q3DValueAxis *axis) +{ + d_ptr->m_shared->addAxis(axis); +} + +/*! + * Releases the ownership of the \a axis back to the caller, if it is added to this graph. + * If the released \a axis is in use, a new default axis will be created and set active. + * + * If the default axis is released and added back later, it behaves as any other axis would. + * + * \sa addAxis(), setAxisX(), setAxisY(), setAxisZ() + */ +void Q3DScatter::releaseAxis(Q3DValueAxis *axis) +{ + d_ptr->m_shared->releaseAxis(axis); +} + +/*! + * \return list of all added axes. + * + * \sa addAxis() + */ +QList<Q3DValueAxis *> Q3DScatter::axes() const +{ + QList<Q3DAbstractAxis *> abstractAxes = d_ptr->m_shared->axes(); + QList<Q3DValueAxis *> retList; + foreach (Q3DAbstractAxis *axis, abstractAxes) + retList.append(static_cast<Q3DValueAxis *>(axis)); + + return retList; +} + +/*! + * Sets the active data \a proxy. Implicitly calls addDataProxy() to transfer ownership of + * the \a proxy to this graph. + * + * If the \a proxy is null, a temporary default proxy is created and activated. + * This temporary proxy is destroyed if another \a proxy is explicitly set active via this method. + * + * \sa addDataProxy(), releaseDataProxy() + */ +void Q3DScatter::setActiveDataProxy(QScatterDataProxy *proxy) +{ + d_ptr->m_shared->setActiveDataProxy(proxy); +} + +/*! + * \return active data proxy. + */ +QScatterDataProxy *Q3DScatter::activeDataProxy() const +{ + return static_cast<QScatterDataProxy *>(d_ptr->m_shared->activeDataProxy()); +} + +/*! + * Adds data \a proxy to the graph. The proxies added via addDataProxy are not yet taken to use, + * addDataProxy is simply used to give the ownership of the data \a proxy to the graph. + * The \a proxy must not be null or added to another graph. + * + * \sa releaseDataProxy(), setActiveDataProxy() + */ +void Q3DScatter::addDataProxy(QScatterDataProxy *proxy) +{ + d_ptr->m_shared->addDataProxy(proxy); +} + +/*! + * Releases the ownership of the data \a proxy back to the caller, if it is added to this graph. + * If the released \a proxy is in use, a new empty default proxy is created and taken to use. + * + * If the default \a proxy is released and added back later, it behaves as any other proxy would. + * + * \sa addDataProxy(), setActiveDataProxy() + */ +void Q3DScatter::releaseDataProxy(QScatterDataProxy *proxy) +{ + d_ptr->m_shared->releaseDataProxy(proxy); +} + +/*! + * \return list of all added data proxies. + * + * \sa addDataProxy() + */ +QList<QScatterDataProxy *> Q3DScatter::dataProxies() const +{ + QList<QScatterDataProxy *> retList; + QList<QAbstractDataProxy *> abstractList = d_ptr->m_shared->dataProxies(); + foreach (QAbstractDataProxy *proxy, abstractList) + retList.append(static_cast<QScatterDataProxy *>(proxy)); + + return retList; +} + +/*! + * \fn void Q3DScatter::shadowQualityChanged(QDataVis::ShadowQuality quality) + * + * This signal is emitted when shadow \a quality changes. + */ + +Q3DScatterPrivate::Q3DScatterPrivate(Q3DScatter *q, QRect rect) + : q_ptr(q), + m_shared(new Scatter3DController(rect)) +{ + QObject::connect(m_shared, &Abstract3DController::shadowQualityChanged, this, + &Q3DScatterPrivate::handleShadowQualityUpdate); +} + +Q3DScatterPrivate::~Q3DScatterPrivate() +{ + qDebug() << "Destroying Q3DScatterPrivate"; + delete m_shared; +} + +void Q3DScatterPrivate::handleShadowQualityUpdate(QDataVis::ShadowQuality quality) +{ + emit q_ptr->shadowQualityChanged(quality); +} + +QT_DATAVISUALIZATION_END_NAMESPACE + diff --git a/src/datavisualization/engine/q3dscatter.h b/src/datavisualization/engine/q3dscatter.h new file mode 100644 index 00000000..fdea604e --- /dev/null +++ b/src/datavisualization/engine/q3dscatter.h @@ -0,0 +1,128 @@ +/**************************************************************************** +** +** 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 Q3DSCATTER_H +#define Q3DSCATTER_H + +#include <QtDataVisualization/qdatavisualizationenums.h> +#include <QtDataVisualization/q3dwindow.h> +#include <QtDataVisualization/q3dscene.h> +#include <QFont> + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +class Q3DScatterPrivate; +class LabelItem; +class Q3DValueAxis; +class Q3DCategoryAxis; +class QScatterDataProxy; + +class QT_DATAVISUALIZATION_EXPORT Q3DScatter : public Q3DWindow +{ + Q_OBJECT + Q_PROPERTY(QtDataVisualization::QDataVis::SelectionMode selectionMode READ selectionMode WRITE setSelectionMode) + Q_PROPERTY(QtDataVisualization::QDataVis::LabelStyle labelStyle READ labelStyle WRITE setLabelStyle) + Q_PROPERTY(QtDataVisualization::QDataVis::ShadowQuality shadowQuality READ shadowQuality WRITE setShadowQuality) + Q_PROPERTY(QString meshFileName READ meshFileName WRITE setMeshFileName) + Q_PROPERTY(QFont font READ font WRITE setFont) + Q_PROPERTY(bool gridVisible READ isGridVisible WRITE setGridVisible) + Q_PROPERTY(bool backgroundVisible READ isBackgroundVisible WRITE setBackgroundVisible) + Q_PROPERTY(int selectedItemIndex READ selectedItemIndex WRITE setSelectedItemIndex NOTIFY selectedItemIndexChanged) + Q_PROPERTY(Q3DScene* scene READ scene) + Q_ENUMS(QtDataVisualization::QDataVis::SelectionMode) + Q_ENUMS(QtDataVisualization::QDataVis::ShadowQuality) + Q_ENUMS(QtDataVisualization::QDataVis::LabelStyle) + Q_ENUMS(QtDataVisualization::QDataVis::CameraPreset) + +public: + explicit Q3DScatter(); + ~Q3DScatter(); + + void setObjectType(QDataVis::MeshStyle style, bool smooth = false); + + void setTheme(QDataVis::Theme theme); + + void setObjectColor(const QColor &baseColor, bool uniform = true); + QColor objectColor() const; + + void setMeshFileName(const QString &objFileName); + QString meshFileName() const; + + void setSelectionMode(QDataVis::SelectionMode mode); + QDataVis::SelectionMode selectionMode() const; + + void setFont(const QFont &font); + QFont font() const; + + Q3DScene *scene() const; + + void setLabelStyle(QDataVis::LabelStyle style); + QDataVis::LabelStyle labelStyle() const; + + void setGridVisible(bool visible); + bool isGridVisible() const; + + void setWidth(const int width); + void setHeight(const int height); + + void setBackgroundVisible(bool visible); + bool isBackgroundVisible() const; + + void setSelectedItemIndex(int index); + int selectedItemIndex() const; + + void setShadowQuality(QDataVis::ShadowQuality quality); + QDataVis::ShadowQuality shadowQuality() const; + + void setAxisX(Q3DValueAxis *axis); + Q3DValueAxis *axisX() const; + void setAxisY(Q3DValueAxis *axis); + Q3DValueAxis *axisY() const; + void setAxisZ(Q3DValueAxis *axis); + Q3DValueAxis *axisZ() const; + void addAxis(Q3DValueAxis *axis); + void releaseAxis(Q3DValueAxis *axis); + QList<Q3DValueAxis *> axes() const; + + void setActiveDataProxy(QScatterDataProxy *proxy); + QScatterDataProxy *activeDataProxy() const; + void addDataProxy(QScatterDataProxy *proxy); + void releaseDataProxy(QScatterDataProxy *proxy); + QList<QScatterDataProxy *> dataProxies() const; + +signals: + void shadowQualityChanged(QDataVis::ShadowQuality quality); + void selectedItemIndexChanged(int index); + +protected: + void mouseDoubleClickEvent(QMouseEvent *event); + void touchEvent(QTouchEvent *event); + void mousePressEvent(QMouseEvent *event); + void mouseReleaseEvent(QMouseEvent *event); + void mouseMoveEvent(QMouseEvent *event); + void wheelEvent(QWheelEvent *event); + void resizeEvent(QResizeEvent *event); + +private: + QScopedPointer<Q3DScatterPrivate> d_ptr; + Q_DISABLE_COPY(Q3DScatter) +}; + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif diff --git a/src/datavis3d/engine/q3dscatter_p.h b/src/datavisualization/engine/q3dscatter_p.h index ab2e2b06..775344d0 100644 --- a/src/datavis3d/engine/q3dscatter_p.h +++ b/src/datavisualization/engine/q3dscatter_p.h @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -20,7 +20,7 @@ // W A R N I N G // ------------- // -// This file is not part of the QtDataVis3D API. It exists purely as an +// 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. // @@ -30,9 +30,9 @@ #define Q3DSCATTER_p_H #include "scatter3dcontroller_p.h" -#include "qdatavis3denums.h" +#include "qdatavisualizationenums.h" -QT_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVISUALIZATION_BEGIN_NAMESPACE class Q3DScatter; @@ -42,10 +42,13 @@ public: Q3DScatterPrivate(Q3DScatter *q, QRect rect); ~Q3DScatterPrivate(); + // Used to detect when shadow quality changes autonomously due to e.g. resizing. + void handleShadowQualityUpdate(QDataVis::ShadowQuality quality); + Q3DScatter *q_ptr; Scatter3DController *m_shared; }; -QT_DATAVIS3D_END_NAMESPACE +QT_DATAVISUALIZATION_END_NAMESPACE #endif diff --git a/src/datavisualization/engine/q3dscene.cpp b/src/datavisualization/engine/q3dscene.cpp new file mode 100644 index 00000000..4908bde4 --- /dev/null +++ b/src/datavisualization/engine/q3dscene.cpp @@ -0,0 +1,375 @@ +/**************************************************************************** +** +** 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 <qmath.h> + +#include "datavisualizationglobal_p.h" + +#include "q3dscene.h" +#include "q3dscene_p.h" +#include "q3dcamera_p.h" +#include "q3dlight_p.h" + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE +/*! + * \class Q3DScene + * \inmodule QtDataVisualization + * \brief Q3DScene class provides description of the 3D scene being visualized. + * \since 1.0.0 + * + * The 3D scene contains a single active camera and a single active light source. + * Visualized data is assumed to be at a fixed location. + * + * The 3D scene also keeps track of the viewport in which visualization rendering is done, + * the primary subviewport inside the viewport where the main 3D data visualization view resides + * and the secondary subviewport where the 2D sliced view of the data resides. + * + * Also the scene has flag for tracking if the secondary 2D slicing view is currently active or not. + * \note Not all visualizations support the secondary 2D slicing view. + */ + +/*! + * Constructs a basic scene with one light and one camera in it. An + * optional \a parent parameter can be given and is then passed to QObject constructor. + */ +Q3DScene::Q3DScene(QObject *parent) : + QObject(parent), + d_ptr(new Q3DScenePrivate(this)) +{ + setActiveCamera(new Q3DCamera(0)); + setActiveLight(new Q3DLight(0)); +} + +/*! + * Destroys the 3D scene and all the objects contained within it. + */ +Q3DScene::~Q3DScene() +{ +} + +/*! + * \property Q3DScene::viewport + * + * This property contains the current viewport rectangle where all 3D rendering + * is targeted. + */ +QRect Q3DScene::viewport() const +{ + return d_ptr->m_viewport; +} + +void Q3DScene::setViewport(const QRect &viewport) +{ + if (d_ptr->m_viewport.width() != viewport.width() + || d_ptr->m_viewport.height() != viewport.height()) { + d_ptr->m_viewport = viewport; + d_ptr->m_viewport.setX(0); + d_ptr->m_viewport.setY(0); + d_ptr->m_changeTracker.viewportChanged = true; + emit viewportChanged(viewport); + } +} + +/*! + * Sets the \a width and \a height of the viewport only, without changing its location. + */ +void Q3DScene::setViewportSize(int width, int height) +{ + if (d_ptr->m_viewport.width() != width + || d_ptr->m_viewport.height() != height) { + d_ptr->m_viewport.setWidth(width); + d_ptr->m_viewport.setHeight(height); + d_ptr->m_changeTracker.viewportChanged = true; + emit viewportChanged(d_ptr->m_viewport); + } +} + +/*! + * \property Q3DScene::primarySubViewport + * + * This property contains the current main viewport rectangle inside the viewport where the + * primary view of the data visualization is targeted to. + */ +QRect Q3DScene::primarySubViewport() const +{ + return d_ptr->m_primarySubViewport; +} + +void Q3DScene::setPrimarySubViewport(const QRect &primarySubViewport) +{ + if (d_ptr->m_primarySubViewport != primarySubViewport) { + d_ptr->m_primarySubViewport = primarySubViewport; + d_ptr->m_changeTracker.primarySubViewportChanged = true; + emit primarySubViewportChanged(primarySubViewport); + } +} + +/*! + * Returns whether the given \a point resides inside the primary subview or not. + * The method takes care of correctly mapping between OpenGL coordinates used in the + * viewport definitions and the Qt event coordinate system used in the input system. + * \return true if the point is inside the primary subview. + */ +bool Q3DScene::isPointInPrimarySubView(const QPoint &point) +{ + // TODO: Needs fixing. Doesn't respect whether slice or main view is on top or if slicing is even activated currently. + int x = point.x(); + int y = point.y(); + int areaMinX = d_ptr->m_primarySubViewport.x(); + int areaMaxX = d_ptr->m_primarySubViewport.x() + d_ptr->m_primarySubViewport.width(); + int areaMaxY = d_ptr->m_viewport.height() - d_ptr->m_primarySubViewport.y(); + int areaMinY = d_ptr->m_viewport.height() - (d_ptr->m_primarySubViewport.y() + d_ptr->m_primarySubViewport.height()); + + return ( x > areaMinX && x < areaMaxX && y > areaMinY && y < areaMaxY ); +} + +/*! + * Returns whether the given \a point resides inside the secondary subview or not. + * The method takes care of correctly mapping between OpenGL coordinates used in the + * viewport definitions and the Qt event coordinate system used in the input system. + * \return true if the point is inside the secondary subview. + */ +bool Q3DScene::isPointInSecondarySubView(const QPoint &point) +{ + // TODO: Needs fixing. Doesn't respect whether slice or main view is on top or if slicing is even activated currently. + int x = point.x(); + int y = point.y(); + int areaMinX = d_ptr->m_secondarySubViewport.x(); + int areaMaxX = d_ptr->m_secondarySubViewport.x() + d_ptr->m_secondarySubViewport.width(); + int areaMaxY = d_ptr->m_viewport.height() - d_ptr->m_secondarySubViewport.y(); + int areaMinY = d_ptr->m_viewport.height() - (d_ptr->m_secondarySubViewport.y() + d_ptr->m_secondarySubViewport.height()); + + return ( x > areaMinX && x < areaMaxX && y > areaMinY && y < areaMaxY ); +} + +/*! + * \property Q3DScene::secondarySubViewport + * + * This property contains the secondary viewport rectangle inside the viewport. The secondary + * viewport is used for drawing the 2D slice view in some visualizations. + */ +QRect Q3DScene::secondarySubViewport() const +{ + return d_ptr->m_secondarySubViewport; +} + +void Q3DScene::setSecondarySubViewport(const QRect &secondarySubViewport) +{ + if (d_ptr->m_secondarySubViewport != secondarySubViewport) { + d_ptr->m_secondarySubViewport = secondarySubViewport; + d_ptr->m_changeTracker.secondarySubViewportChanged = true; + emit secondarySubViewportChanged(secondarySubViewport); + } +} + +/*! + * \property Q3DScene::slicingActive + * + * This property contains whether 2D slicing view is currently active or not. + * \note Not all visualizations support the 2D slicing view. + */ +bool Q3DScene::isSlicingActive() const +{ + return d_ptr->m_isSlicingActive; +} + +void Q3DScene::setSlicingActive(bool isSlicing) +{ + if (d_ptr->m_isSlicingActive != isSlicing) { + d_ptr->m_isSlicingActive = isSlicing; + d_ptr->m_changeTracker.slicingActivatedChanged = true; + emit slicingActiveChanged(isSlicing); + emitNeedRender(); + } +} + +/*! + * \property Q3DScene::activeCamera + * + * This property contains the currently active camera in the 3D scene. + * When a new Q3DCamera objects is set in the property it gets automatically added as child of the scene. + */ +Q3DCamera *Q3DScene::activeCamera() const +{ + return d_ptr->m_camera; +} + +void Q3DScene::setActiveCamera(Q3DCamera *camera) +{ + Q_ASSERT(camera); + + // Add new camera as child of the scene + if (camera->parent() != this) + camera->setParent(this); + + if (camera != d_ptr->m_camera) { + if (d_ptr->m_camera) { + disconnect(d_ptr->m_camera, &Q3DCamera::xRotationChanged, this, + &Q3DScene::emitNeedRender); + disconnect(d_ptr->m_camera, &Q3DCamera::yRotationChanged, this, + &Q3DScene::emitNeedRender); + } + + d_ptr->m_camera = camera; + d_ptr->m_changeTracker.cameraChanged = true; + + if (camera) { + connect(camera, &Q3DCamera::xRotationChanged, this, + &Q3DScene::emitNeedRender); + connect(camera, &Q3DCamera::yRotationChanged, this, + &Q3DScene::emitNeedRender); + } + + emit activeCameraChanged(camera); + emitNeedRender(); + } +} + +void Q3DScene::emitNeedRender() +{ + emit needRender(); +} + +/*! + * \property Q3DScene::activeLight + * + * This property contains the currently active light in the 3D scene. + * When a new Q3DLight objects is set in the property it gets automatically added as child of the scene. + */ +Q3DLight *Q3DScene::activeLight() const +{ + return d_ptr->m_light; +} + +void Q3DScene::setActiveLight(Q3DLight *light) +{ + Q_ASSERT(light); + + // Add new light as child of the scene + if (light->parent() != this) + light->setParent(this); + + if (light != d_ptr->m_light) { + d_ptr->m_light = light; + d_ptr->m_changeTracker.lightChanged = true; + emit activeLightChanged(light); + } +} + +/*! + * \property Q3DScene::devicePixelRatio + * + * This property contains the current device pixel ratio that is used when mapping input + * coordinates to pixel coordinates. + */ +qreal Q3DScene::devicePixelRatio() const +{ + return d_ptr->m_devicePixelRatio; +} + +void Q3DScene::setDevicePixelRatio(qreal pixelRatio) +{ + if (d_ptr->m_devicePixelRatio != pixelRatio) { + d_ptr->m_devicePixelRatio = pixelRatio; + emit devicePixelRatioChanged(pixelRatio); + } +} + +/*! + * Calculates and sets the light position relative to the currently active camera using the given parameters. + * \a relativePosition defines the relative 3D offset to the current camera position. + * Optional \a fixedRotation fixes the light rotation around the data visualization area to the given value in degrees. + * Optional \a distanceModifier modifies the distance of the light from the data visualization. + */ +void Q3DScene::setLightPositionRelativeToCamera(const QVector3D &relativePosition, + qreal fixedRotation, qreal distanceModifier) +{ + d_ptr->m_light->setPosition( + d_ptr->m_camera->calculatePositionRelativeToCamera(relativePosition, + fixedRotation, + distanceModifier)); +} + +/*! + * \fn Q3DScene::needRender() + * \internal + */ + +Q3DScenePrivate::Q3DScenePrivate(Q3DScene *q) : + q_ptr(q), + m_devicePixelRatio(1.f), + m_camera(), + m_light(), + m_isUnderSideCameraEnabled(false), + m_isSlicingActive(false) +{ +} + +Q3DScenePrivate::~Q3DScenePrivate() +{ + delete m_camera; + delete m_light; +} + +// Copies changed values from this scene to the other scene. If the other scene had same changes, +// those changes are discarded. +void Q3DScenePrivate::sync(Q3DScenePrivate &other) +{ + if (m_changeTracker.viewportChanged) { + other.q_ptr->setViewport(q_ptr->viewport()); + m_changeTracker.viewportChanged = false; + other.m_changeTracker.viewportChanged = false; + } + if (m_changeTracker.primarySubViewportChanged) { + other.q_ptr->setPrimarySubViewport(q_ptr->primarySubViewport()); + m_changeTracker.primarySubViewportChanged = false; + other.m_changeTracker.primarySubViewportChanged = false; + } + if (m_changeTracker.secondarySubViewportChanged) { + other.q_ptr->setSecondarySubViewport(q_ptr->secondarySubViewport()); + m_changeTracker.secondarySubViewportChanged = false; + other.m_changeTracker.secondarySubViewportChanged = false; + } + if (m_changeTracker.cameraChanged) { + m_camera->setDirty(true); + m_changeTracker.cameraChanged = false; + other.m_changeTracker.cameraChanged = false; + } + m_camera->d_ptr->sync(*other.m_camera); + + if (m_changeTracker.lightChanged) { + m_light->setDirty(true); + m_changeTracker.lightChanged = false; + other.m_changeTracker.lightChanged = false; + } + m_light->d_ptr->sync(*other.m_light); + + if (m_changeTracker.slicingActivatedChanged) { + other.q_ptr->setSlicingActive(q_ptr->isSlicingActive()); + m_changeTracker.slicingActivatedChanged = false; + other.m_changeTracker.slicingActivatedChanged = false; + } + + if (m_changeTracker.devicePixelRatioChanged) { + other.q_ptr->setDevicePixelRatio(q_ptr->devicePixelRatio()); + m_changeTracker.devicePixelRatioChanged = false; + other.m_changeTracker.devicePixelRatioChanged = false; + } +} + +QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavisualization/engine/q3dscene.h b/src/datavisualization/engine/q3dscene.h new file mode 100644 index 00000000..745cef72 --- /dev/null +++ b/src/datavisualization/engine/q3dscene.h @@ -0,0 +1,103 @@ +/**************************************************************************** +** +** 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 Q3DSCENE_H +#define Q3DSCENE_H + +#include <QtDataVisualization/qdatavisualizationenums.h> +#include <QObject> +#include <QRect> + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +class Q3DCamera; +class Q3DBox; +class Q3DLight; +class Q3DScenePrivate; + +class QT_DATAVISUALIZATION_EXPORT Q3DScene : public QObject +{ + Q_OBJECT + Q_PROPERTY(QRect viewport READ viewport WRITE setViewport NOTIFY viewportChanged) + Q_PROPERTY(QRect primarySubViewport READ primarySubViewport WRITE setPrimarySubViewport NOTIFY primarySubViewportChanged) + Q_PROPERTY(QRect secondarySubViewport READ secondarySubViewport WRITE setSecondarySubViewport NOTIFY secondarySubViewportChanged) + Q_PROPERTY(bool slicingActive READ isSlicingActive WRITE setSlicingActive NOTIFY slicingActiveChanged) + Q_PROPERTY(Q3DCamera* activeCamera READ activeCamera WRITE setActiveCamera NOTIFY activeCameraChanged) + Q_PROPERTY(Q3DLight* activeLight READ activeLight WRITE setActiveLight NOTIFY activeLightChanged) + Q_PROPERTY(qreal devicePixelRatio READ devicePixelRatio WRITE setDevicePixelRatio NOTIFY devicePixelRatioChanged) + +public: + Q3DScene(QObject *parent = 0); + ~Q3DScene(); + + QRect viewport() const; + void setViewport(const QRect &viewport); + void setViewportSize(int width, int height); + + QRect primarySubViewport() const; + void setPrimarySubViewport(const QRect &primarySubViewport); + bool isPointInPrimarySubView(const QPoint &point); + + QRect secondarySubViewport() const; + void setSecondarySubViewport(const QRect &secondarySubViewport); + bool isPointInSecondarySubView(const QPoint &point); + + void setSlicingActive(bool isSlicing); + bool isSlicingActive() const; + + Q3DCamera *activeCamera() const; + void setActiveCamera(Q3DCamera *camera); + + Q3DLight *activeLight() const; + void setActiveLight(Q3DLight *light); + + qreal devicePixelRatio() const; + void setDevicePixelRatio(qreal pixelRatio); + + void setLightPositionRelativeToCamera(const QVector3D &relativePosition, + qreal fixedRotation = 0.0, + qreal distanceModifier = 0.0); +private: + void emitNeedRender(); + +signals: + void viewportChanged(QRect viewport); + void primarySubViewportChanged(QRect subViewport); + void secondarySubViewportChanged(QRect subViewport); + void slicingActiveChanged(bool isSlicingActive); + void activeCameraChanged(const Q3DCamera *camera); + void activeLightChanged(const Q3DLight *light); + void devicePixelRatioChanged(qreal pixelRatio); + void needRender(); + +private: + QScopedPointer<Q3DScenePrivate> d_ptr; + + Q_DISABLE_COPY(Q3DScene) + + friend class Q3DScenePrivate; + friend class Abstract3DRenderer; + friend class Bars3DRenderer; + friend class Surface3DRenderer; + friend class Scatter3DRenderer; + friend class Q3DCameraPrivate; +}; + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif // Q3DSCENE_H diff --git a/src/datavisualization/engine/q3dscene_p.h b/src/datavisualization/engine/q3dscene_p.h new file mode 100644 index 00000000..b28baaae --- /dev/null +++ b/src/datavisualization/engine/q3dscene_p.h @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** 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 Q3DSCENE_P_H +#define Q3DSCENE_P_H + +#include "datavisualizationglobal_p.h" +#include <QRect> + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +class Q3DCamera; +class Q3DLight; +class Q3DScene; + +struct Q3DSceneChangeBitField { + bool viewportChanged : 1; + bool primarySubViewportChanged : 1; + bool secondarySubViewportChanged : 1; + bool cameraChanged : 1; + bool lightChanged : 1; + bool slicingActivatedChanged : 1; + bool devicePixelRatioChanged : 1; + + Q3DSceneChangeBitField() + : viewportChanged(true), + primarySubViewportChanged(true), + secondarySubViewportChanged(true), + cameraChanged(true), + lightChanged(true), + slicingActivatedChanged(true), + devicePixelRatioChanged(true) + { + } +}; + +class Q3DScenePrivate +{ +public: + Q3DScenePrivate(Q3DScene *q); + ~Q3DScenePrivate(); + + void sync(Q3DScenePrivate &other); + + Q3DScene *q_ptr; + Q3DSceneChangeBitField m_changeTracker; + + QRect m_viewport; + QRect m_primarySubViewport; + QRect m_secondarySubViewport; + qreal m_devicePixelRatio; + Q3DCamera *m_camera; + Q3DLight *m_light; + bool m_isUnderSideCameraEnabled; + bool m_isSlicingActive; +}; + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif // Q3DSCENE_P_H diff --git a/src/datavisualization/engine/q3dsurface.cpp b/src/datavisualization/engine/q3dsurface.cpp new file mode 100644 index 00000000..7990f362 --- /dev/null +++ b/src/datavisualization/engine/q3dsurface.cpp @@ -0,0 +1,542 @@ +/**************************************************************************** +** +** 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 "q3dsurface.h" +#include "q3dsurface_p.h" +#include "q3dvalueaxis.h" +#include "qsurfacedataproxy.h" +#include "q3dcamera.h" + +#include <QMouseEvent> + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +/*! + * \class Q3DSurface + * \inmodule QtDataVisualization + * \brief The Q3DSurface class provides methods for rendering 3D surface plots. + * \since 1.0.0 + * + * This class enables developers to render 3D surface plots and to view them by rotating the scene + * freely. The class provides configurable gradient texture to illustrate the height on the data. The + * surface plotting includes also gridline that can be set on or off. The visual appearance of the + * surface can be changed by controlling the smooth status. + * + * The Q3DSurface supports selection by showing a highlighted ball on the data point where the user has clicked + * with left mouse button (when default input handler is in use). The selection pointer is accompanied with + * a label which in default case shows the value of the data point and the coordinates of the point. + * + * The value range and the label format shown on the axis can be controlled through Q3DValueAxis. + * The Q3DSurface supports only a grid with fixed steps, so when setting ranges set a value that matches + * the grid step. To calculate the steps divide the whole data range with the number of segments. + * + * To rotate the graph, hold down the right mouse button and move the mouse. Zooming is done using mouse + * wheel. Both assume the default input handler is in use. + * + * If no axes are explicitly set to Q3DSurface, temporary default axes with no labels are created. + * These default axes can be modified via axis accessors, but as soon any axis is explicitly + * set for the orientation, the default axis for that orientation is destroyed. + * + * Data proxies work similarly: If no data proxy is explicitly set, Q3DSurface creates a default + * proxy. If any other proxy is set as active data proxy later, the default proxy and all data + * added to it is destroyed. + * + * \section1 How to construct a minimal Q3DSurface graph + * + * First, construct Q3DSurface: + * + * \snippet doc_src_q3dsurface_construction.cpp 0 + * + * Now Q3DSurface is ready to receive data to be rendered. Create data elements to receive values: + * + * \snippet doc_src_q3dsurface_construction.cpp 1 + * + * First feed the data to the row element and then add it's pointer to the data element: + * + * \snippet doc_src_q3dsurface_construction.cpp 2 + * + * For the active data proxy set pointer of the data element: + * + * \snippet doc_src_q3dsurface_construction.cpp 3 + * + * Finally you will need to set it visible: + * + * \snippet doc_src_q3dsurface_construction.cpp 4 + * + * The complete code needed to create and display this graph is: + * + * \snippet doc_src_q3dsurface_construction.cpp 5 + * + * And this is what those few lines of code produce: + * + * \image q3dsurface-minimal.png + * + * The scene can be rotated and zoomed into, but no other interaction is included in this minimal + * code example. + * + * + * \sa Q3DBars, Q3DScatter, {Qt Data Visualization C++ Classes} + */ + +/*! + * Constructs a new 3D surface window. + */ +Q3DSurface::Q3DSurface() + : d_ptr(new Q3DSurfacePrivate(this, geometry())) +{ + setVisualController(d_ptr->m_shared); + d_ptr->m_shared->initializeOpenGL(); + QObject::connect(d_ptr->m_shared, &Abstract3DController::needRender, this, + &Q3DWindow::renderLater); +} + +/*! + * Destroys the 3D surface window. + */ +Q3DSurface::~Q3DSurface() +{ +} + +/*! + * \internal + */ +void Q3DSurface::mouseDoubleClickEvent(QMouseEvent *event) +{ + d_ptr->m_shared->mouseDoubleClickEvent(event); +} + +/*! + * \internal + */ +void Q3DSurface::touchEvent(QTouchEvent *event) +{ + d_ptr->m_shared->touchEvent(event); +} + +/*! + * \internal + */ +void Q3DSurface::mousePressEvent(QMouseEvent *event) +{ + d_ptr->m_shared->mousePressEvent(event, event->pos()); +} + +/*! + * \internal + */ +void Q3DSurface::mouseReleaseEvent(QMouseEvent *event) +{ + d_ptr->m_shared->mouseReleaseEvent(event, event->pos()); +} + +/*! + * \internal + */ +void Q3DSurface::mouseMoveEvent(QMouseEvent *event) +{ + d_ptr->m_shared->mouseMoveEvent(event, event->pos()); +} + +/*! + * \internal + */ +void Q3DSurface::wheelEvent(QWheelEvent *event) +{ + d_ptr->m_shared->wheelEvent(event); +} + +/*! + * \internal + */ +void Q3DSurface::resizeEvent(QResizeEvent *event) +{ + Q_UNUSED(event); + d_ptr->m_shared->setWidth(width()); + d_ptr->m_shared->setHeight(height()); +} + +/*! + * \property Q3DSurface::gridVisible + * + * Sets grid visibility to \a visible. It is preset to \c true by default. + */ +void Q3DSurface::setGridVisible(bool visible) +{ + d_ptr->m_shared->setGridEnabled(visible); +} + +bool Q3DSurface::isGridVisible() const +{ + return d_ptr->m_shared->gridEnabled(); +} + +/*! + * \property Q3DSurface::backgroundVisible + * + * Sets background visibility to \a visible. It is preset to \c true by default. + */ +void Q3DSurface::setBackgroundVisible(bool visible) +{ + d_ptr->m_shared->setBackgroundEnabled(visible); +} + +bool Q3DSurface::isBackgroundVisible() const +{ + return d_ptr->m_shared->backgroundEnabled(); +} + +/*! + * \property Q3DSurface::theme + * + * A predefined \a theme from \c QDataVis::Theme. It is preset to \c QDataVis::ThemeQt by + * default. Theme affects label colors, text color, background color, window color and + * grid color. Lighting is also adjusted by themes. + * + * \warning This property is subject to change. + */ +void Q3DSurface::setTheme(QDataVis::Theme theme) +{ + d_ptr->m_shared->setTheme(theme); +} + +QDataVis::Theme Q3DSurface::theme() const +{ + return d_ptr->m_shared->theme().theme(); +} + +/*! + * \property Q3DSurface::shadowQuality + * + * Sets shadow \a quality to one of \c QDataVis::ShadowQuality. It is preset to + * \c QDataVis::ShadowQualityMedium by default. + * + * \note If setting QDataVis::ShadowQuality of a certain level fails, a level is lowered + * until it is successful and shadowQualityChanged signal is emitted for each time the change is + * done. + */ +void Q3DSurface::setShadowQuality(QDataVis::ShadowQuality quality) +{ + return d_ptr->m_shared->setShadowQuality(quality); +} + +QDataVis::ShadowQuality Q3DSurface::shadowQuality() const +{ + return d_ptr->m_shared->shadowQuality(); +} + +/*! + * \property Q3DSurface::smoothSurfaceEnabled + * + * Sets surface smoothing to \a enabled. It is preset to \c false by default. + * When enabled the normals on the surface are interpolated making edges looking round. If turned + * off the normals are kept same on a triangle making the color of the triangle solid. This makes + * the data more readable from the model. + */ +void Q3DSurface::setSmoothSurfaceEnabled(bool enabled) +{ + d_ptr->m_shared->setSmoothSurface(enabled); +} + +bool Q3DSurface::isSmoothSurfaceEnabled() const +{ + return d_ptr->m_shared->smoothSurface(); +} + +/*! + * \property Q3DSurface::selectionMode + * + * Sets point selection \a mode to one of \c QDataVis::SelectionMode. Surface supports SelectionModeItem, + * SelectionModeSliceRow and SelectionModeSliceColumn. It is preset to \c QDataVis::SelectionModeItem by default. + */ +void Q3DSurface::setSelectionMode(QDataVis::SelectionMode mode) +{ + d_ptr->m_shared->setSelectionMode(mode); +} + +QDataVis::SelectionMode Q3DSurface::selectionMode() const +{ + return d_ptr->m_shared->selectionMode(); +} + + +/*! + * \property Q3DSurface::surfaceGridEnabled + * + * Sets surface grid to \a enabled. It is preset to \c true by default. + */ +void Q3DSurface::setSurfaceGridEnabled(bool enabled) +{ + d_ptr->m_shared->setSurfaceGrid(enabled); +} + +bool Q3DSurface::isSurfaceGridEnabled() const +{ + return d_ptr->m_shared->surfaceGrid(); +} + +/*! + * \property Q3DSurface::gradient + * + * The current surface gradient. Setting this property replaces the previous gradient with + * the given \a gradient. + */ +void Q3DSurface::setGradient(const QLinearGradient &gradient) +{ + d_ptr->m_shared->setGradient(gradient); +} + +QLinearGradient Q3DSurface::gradient() const +{ + return d_ptr->m_shared->gradient(); +} + +/*! + * \property Q3DSurface::font + * + * Sets the \a font for labels. It is preset to \c Arial by default. + */ +void Q3DSurface::setFont(const QFont &font) +{ + d_ptr->m_shared->setFont(font); +} + +QFont Q3DSurface::font() const +{ + return d_ptr->m_shared->font(); +} + +/*! + * \property Q3DSurface::scene + * + * This property contains the read only Q3DScene that can be used to access e.g. camera object. + */ +Q3DScene *Q3DSurface::scene() const +{ + return d_ptr->m_shared->scene(); +} + +/*! + * \property Q3DSurface::labelStyle + * + * Sets label \a style to one of \c QDataVis::LabelStyle. It is preset to + * \c QDataVis::LabelStyleFromTheme by default. + */ +void Q3DSurface::setLabelStyle(QDataVis::LabelStyle style) +{ + d_ptr->m_shared->setLabelStyle(style); +} + +QDataVis::LabelStyle Q3DSurface::labelStyle() const +{ + return d_ptr->m_shared->labelStyle(); +} + +/*! + * Sets a user-defined X-axis. Implicitly calls addAxis() to transfer ownership + * of the \a axis to this graph. + * + * If the \a axis is null, a temporary default axis with no labels and automatically adjusting + * range is created. + * This temporary axis is destroyed if another \a axis is explicitly set to same orientation. + * + * \sa addAxis(), releaseAxis() + */ +void Q3DSurface::setAxisX(Q3DValueAxis *axis) +{ + d_ptr->m_shared->setAxisX(axis); +} + +/*! + * \return used X-axis. + */ +Q3DValueAxis *Q3DSurface::axisX() const +{ + return static_cast<Q3DValueAxis *>(d_ptr->m_shared->axisX()); +} + +/*! + * Sets a user-defined Y-axis. Implicitly calls addAxis() to transfer ownership + * of the \a axis to this graph. + * + * If the \a axis is null, a temporary default axis with no labels and automatically adjusting + * range is created. + * This temporary axis is destroyed if another \a axis is explicitly set to same orientation. + * + * \sa addAxis(), releaseAxis() + */ +void Q3DSurface::setAxisY(Q3DValueAxis *axis) +{ + d_ptr->m_shared->setAxisY(axis); +} + +/*! + * \return used Y-axis. + */ +Q3DValueAxis *Q3DSurface::axisY() const +{ + return static_cast<Q3DValueAxis *>(d_ptr->m_shared->axisY()); +} + +/*! + * Sets a user-defined Z-axis. Implicitly calls addAxis() to transfer ownership + * of the \a axis to this graph. + * + * If the \a axis is null, a temporary default axis with no labels and automatically adjusting + * range is created. + * This temporary axis is destroyed if another \a axis is explicitly set to same orientation. + * + * \sa addAxis(), releaseAxis() + */ +void Q3DSurface::setAxisZ(Q3DValueAxis *axis) +{ + d_ptr->m_shared->setAxisZ(axis); +} + +/*! + * \return used Z-axis. + */ +Q3DValueAxis *Q3DSurface::axisZ() const +{ + return static_cast<Q3DValueAxis *>(d_ptr->m_shared->axisZ()); +} + +/*! + * Adds \a axis to the graph. The axes added via addAxis are not yet taken to use, + * addAxis is simply used to give the ownership of the \a axis to the graph. + * The \a axis must not be null or added to another graph. + * + * \sa releaseAxis(), setAxisX(), setAxisY(), setAxisZ() + */ +void Q3DSurface::addAxis(Q3DValueAxis *axis) +{ + d_ptr->m_shared->addAxis(axis); +} + +/*! + * Releases the ownership of the \a axis back to the caller, if it is added to this graph. + * If the released \a axis is in use, a new default axis will be created and set active. + * + * If the default axis is released and added back later, it behaves as any other axis would. + * + * \sa addAxis(), setAxisX(), setAxisY(), setAxisZ() + */ +void Q3DSurface::releaseAxis(Q3DValueAxis *axis) +{ + d_ptr->m_shared->releaseAxis(axis); +} + +/*! + * \return list of all added axes. + * + * \sa addAxis() + */ +QList<Q3DValueAxis *> Q3DSurface::axes() const +{ + QList<Q3DAbstractAxis *> abstractAxes = d_ptr->m_shared->axes(); + QList<Q3DValueAxis *> retList; + foreach (Q3DAbstractAxis *axis, abstractAxes) + retList.append(static_cast<Q3DValueAxis *>(axis)); + + return retList; +} + +/*! + * Sets the active data \a proxy. Implicitly calls addDataProxy() to transfer ownership of + * the \a proxy to this graph. + * + * If the \a proxy is null, a temporary default proxy is created and activated. + * This temporary proxy is destroyed if another \a proxy is explicitly set active via this method. + * + * \sa addDataProxy(), releaseDataProxy() + */ +void Q3DSurface::setActiveDataProxy(QSurfaceDataProxy *proxy) +{ + d_ptr->m_shared->setActiveDataProxy(proxy); +} + +/*! + * \return active data proxy. + */ +QSurfaceDataProxy *Q3DSurface::activeDataProxy() const +{ + return static_cast<QSurfaceDataProxy *>(d_ptr->m_shared->activeDataProxy()); +} + +/*! + * Adds data \a proxy to the graph. The proxies added via addDataProxy are not yet taken to use, + * addDataProxy is simply used to give the ownership of the data \a proxy to the graph. + * The \a proxy must not be null or added to another graph. + * + * \sa releaseDataProxy(), setActiveDataProxy() + */ +void Q3DSurface::addDataProxy(QSurfaceDataProxy *proxy) +{ + d_ptr->m_shared->addDataProxy(proxy); +} + +/*! + * Releases the ownership of the data \a proxy back to the caller, if it is added to this graph. + * If the released \a proxy is in use, a new empty default proxy is created and taken to use. + * + * If the default \a proxy is released and added back later, it behaves as any other proxy would. + * + * \sa addDataProxy(), setActiveDataProxy() + */ +void Q3DSurface::releaseDataProxy(QSurfaceDataProxy *proxy) +{ + d_ptr->m_shared->releaseDataProxy(proxy); +} + +/*! + * \return list of all added data proxies. + * + * \sa addDataProxy() + */ +QList<QSurfaceDataProxy *> Q3DSurface::dataProxies() const +{ + QList<QSurfaceDataProxy *> retList; + QList<QAbstractDataProxy *> abstractList = d_ptr->m_shared->dataProxies(); + foreach (QAbstractDataProxy *proxy, abstractList) + retList.append(static_cast<QSurfaceDataProxy *>(proxy)); + + return retList; +} + + +/*! + * Modifies the current surface gradient. Sets gradient color to \a color at \a pos. + */ +void Q3DSurface::setGradientColorAt(qreal pos, const QColor &color) +{ + d_ptr->m_shared->setGradientColorAt(pos, color); +} + +/////////////////// PRIVATE /////////////////////////////////// + +Q3DSurfacePrivate::Q3DSurfacePrivate(Q3DSurface *q, QRect rect) + : q_ptr(q), + m_shared(new Surface3DController(rect)) +{ +} + +Q3DSurfacePrivate::~Q3DSurfacePrivate() +{ + delete m_shared; +} + +QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavisualization/engine/q3dsurface.h b/src/datavisualization/engine/q3dsurface.h new file mode 100644 index 00000000..1b572a36 --- /dev/null +++ b/src/datavisualization/engine/q3dsurface.h @@ -0,0 +1,123 @@ +/**************************************************************************** +** +** 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 Q3DSURFACE_H +#define Q3DSURFACE_H + +#include <QtDataVisualization/qdatavisualizationenums.h> +#include <QtDataVisualization/q3dwindow.h> +#include <QtDataVisualization/q3dscene.h> +#include <QFont> +#include <QLinearGradient> + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +class Q3DSurfacePrivate; +class Q3DValueAxis; +class QSurfaceDataProxy; + +class QT_DATAVISUALIZATION_EXPORT Q3DSurface : public Q3DWindow +{ + Q_OBJECT + Q_PROPERTY(QtDataVisualization::QDataVis::SelectionMode selectionMode READ selectionMode WRITE setSelectionMode) + Q_PROPERTY(QtDataVisualization::QDataVis::LabelStyle labelStyle READ labelStyle WRITE setLabelStyle) + Q_PROPERTY(QtDataVisualization::QDataVis::Theme theme READ theme WRITE setTheme) + Q_PROPERTY(QtDataVisualization::QDataVis::ShadowQuality shadowQuality READ shadowQuality WRITE setShadowQuality) + Q_PROPERTY(bool gridVisible READ isGridVisible WRITE setGridVisible) + Q_PROPERTY(bool backgroundVisible READ isBackgroundVisible WRITE setBackgroundVisible) + Q_PROPERTY(bool smoothSurfaceEnabled READ isSmoothSurfaceEnabled WRITE setSmoothSurfaceEnabled) + Q_PROPERTY(bool surfaceGridEnabled READ isSurfaceGridEnabled WRITE setSurfaceGridEnabled) + Q_PROPERTY(QLinearGradient gradient READ gradient WRITE setGradient) + Q_PROPERTY(QFont font READ font WRITE setFont) + Q_PROPERTY(Q3DScene* scene READ scene) + Q_ENUMS(QtDataVisualization::QDataVis::SelectionMode) + Q_ENUMS(QtDataVisualization::QDataVis::ShadowQuality) + Q_ENUMS(QtDataVisualization::QDataVis::LabelStyle) + Q_ENUMS(QtDataVisualization::QDataVis::CameraPreset) + +public: + explicit Q3DSurface(); + ~Q3DSurface(); + + void setGridVisible(bool visible); + bool isGridVisible() const; + + void setBackgroundVisible(bool visible); + bool isBackgroundVisible() const; + + void setTheme(QDataVis::Theme theme); + QDataVis::Theme theme() const; + + void setShadowQuality(QDataVis::ShadowQuality quality); + QDataVis::ShadowQuality shadowQuality() const; + + void setSmoothSurfaceEnabled(bool enabled); + bool isSmoothSurfaceEnabled() const; + + void setSelectionMode(QDataVis::SelectionMode mode); + QDataVis::SelectionMode selectionMode() const; + void setSurfaceGridEnabled(bool enabled); + bool isSurfaceGridEnabled() const; + + void setGradient(const QLinearGradient &gradient); + QLinearGradient gradient() const; + + void setGradientColorAt(qreal pos, const QColor &color); + + // Axes + void setAxisX(Q3DValueAxis *axis); + Q3DValueAxis *axisX() const; + void setAxisY(Q3DValueAxis *axis); + Q3DValueAxis *axisY() const; + void setAxisZ(Q3DValueAxis *axis); + Q3DValueAxis *axisZ() const; + void addAxis(Q3DValueAxis *axis); + void releaseAxis(Q3DValueAxis *axis); + QList<Q3DValueAxis *> axes() const; + + void setActiveDataProxy(QSurfaceDataProxy *proxy); + QSurfaceDataProxy *activeDataProxy() const; + void addDataProxy(QSurfaceDataProxy *proxy); + void releaseDataProxy(QSurfaceDataProxy *proxy); + QList<QSurfaceDataProxy *> dataProxies() const; + + void setFont(const QFont &font); + QFont font() const; + + Q3DScene *scene() const; + + void setLabelStyle(QDataVis::LabelStyle style); + QDataVis::LabelStyle labelStyle() const; + +protected: + void mouseDoubleClickEvent(QMouseEvent *event); + void touchEvent(QTouchEvent *event); + void mousePressEvent(QMouseEvent *event); + void mouseReleaseEvent(QMouseEvent *event); + void mouseMoveEvent(QMouseEvent *event); + void wheelEvent(QWheelEvent *event); + void resizeEvent(QResizeEvent *event); + +private: + QScopedPointer<Q3DSurfacePrivate> d_ptr; + Q_DISABLE_COPY(Q3DSurface) +}; + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif // Q3DSURFACE_H diff --git a/src/datavis3d/engine/q3dsurface_p.h b/src/datavisualization/engine/q3dsurface_p.h index 1e132416..7c70d08c 100644 --- a/src/datavis3d/engine/q3dsurface_p.h +++ b/src/datavisualization/engine/q3dsurface_p.h @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -20,7 +20,7 @@ // W A R N I N G // ------------- // -// This file is not part of the QtDataVis3D API. It exists purely as an +// 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. // @@ -30,11 +30,11 @@ #define Q3DSURFACE_P_H #include "surface3dcontroller_p.h" -#include "qdatavis3denums.h" +#include "qdatavisualizationenums.h" #include <QList> -QT_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVISUALIZATION_BEGIN_NAMESPACE class Q3DSurface; @@ -44,19 +44,10 @@ public: Q3DSurfacePrivate(Q3DSurface *q, QRect rect); ~Q3DSurfacePrivate(); - // TODO - void appendSeries(QList<qreal> series); - QList<qreal> seriesAt(int i); - int numOfSeries(); - // TODO - - Surface3dController *m_shared; - -private: Q3DSurface *q_ptr; - QList<QList<qreal> > m_seriesList; // Temp to be replaced by dataset + Surface3DController *m_shared; }; -QT_DATAVIS3D_END_NAMESPACE +QT_DATAVISUALIZATION_END_NAMESPACE #endif // Q3DSURFACE_P_H diff --git a/src/datavis3d/engine/q3dwindow.cpp b/src/datavisualization/engine/q3dwindow.cpp index 5b2b70ab..9b607e1d 100644 --- a/src/datavis3d/engine/q3dwindow.cpp +++ b/src/datavisualization/engine/q3dwindow.cpp @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -18,7 +18,7 @@ #include "q3dwindow.h" #include "q3dwindow_p.h" - +#include "abstract3dcontroller_p.h" #include <QGuiApplication> #include <QOpenGLContext> @@ -27,25 +27,23 @@ #include <QDebug> -QT_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVISUALIZATION_BEGIN_NAMESPACE /*! * \class Q3DWindow - * \inmodule QtDataVis3D + * \inmodule QtDataVisualization * \brief The Q3DWindow class provides a window and render loop. * \since 1.0.0 * * This class creates a QWindow and provides render loop for visualization types inheriting it. * \warning This class is not intended to be used directly by developers. * - * \sa Q3DBars, Q3DMaps, {Qt Data Visualization 3D C++ Classes} + * \sa Q3DBars, Q3DScatter, Q3DSurface, {Qt Data Visualization C++ Classes} */ /*! - * \a parent A QWindow parent. - * - * Constructs Q3DWindow. It creates a QWindow and an OpenGL context. It also sets surface - * format and initializes OpenGL functions for use. + * Constructs Q3DWindow with \a parent. It creates a QWindow and an OpenGL context. It also sets + * surface format and initializes OpenGL functions for use. */ Q3DWindow::Q3DWindow(QWindow *parent) : QWindow(parent), @@ -82,7 +80,7 @@ Q3DWindow::Q3DWindow(QWindow *parent) if (splitversionstr[0].toFloat() < 1.2) qFatal("GLSL version must be 1.20 or higher. Try installing latest display drivers."); #endif - setAnimating(true); + renderLater(); } /*! @@ -95,8 +93,33 @@ Q3DWindow::~Q3DWindow() /*! * \internal */ +void Q3DWindow::setVisualController(Abstract3DController *controller) +{ + d_ptr->m_visualController = controller; +} + +/*! + * \internal + */ +void Q3DWindow::handleDevicePixelRatioChange() +{ + if (QWindow::devicePixelRatio() == d_ptr->m_devicePixelRatio || !d_ptr->m_visualController) + return; + + // Device pixel ratio changed, resize accordingly and inform the scene + d_ptr->m_devicePixelRatio = QWindow::devicePixelRatio(); + d_ptr->m_visualController->updateDevicePixelRatio(d_ptr->m_devicePixelRatio); + +} + +/*! + * \internal + */ void Q3DWindow::render() { + handleDevicePixelRatioChange(); + d_ptr->m_visualController->synchDataToRenderer(); + d_ptr->m_visualController->render(); } /*! @@ -119,6 +142,12 @@ bool Q3DWindow::event(QEvent *event) case QEvent::UpdateRequest: renderNow(); return true; + case QEvent::TouchBegin: + case QEvent::TouchCancel: + case QEvent::TouchUpdate: + case QEvent::TouchEnd: + d_ptr->m_visualController->touchEvent(static_cast<QTouchEvent *>(event)); + return true; default: return QWindow::event(event); } @@ -150,27 +179,14 @@ void Q3DWindow::renderNow() render(); d_ptr->m_context->swapBuffers(this); - - if (d_ptr->m_animating) - renderLater(); -} - -/*! - * \internal - */ -void Q3DWindow::setAnimating(bool animating) -{ - d_ptr->m_animating = animating; - - if (animating) - renderLater(); } Q3DWindowPrivate::Q3DWindowPrivate(Q3DWindow *q) : q_ptr(q), m_updatePending(false), - m_animating(false), - m_context(new QOpenGLContext(q)) + m_context(new QOpenGLContext(q)), + m_visualController(0), + m_devicePixelRatio(1.f) { } @@ -178,4 +194,4 @@ Q3DWindowPrivate::~Q3DWindowPrivate() { } -QT_DATAVIS3D_END_NAMESPACE +QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavis3d/engine/q3dwindow.h b/src/datavisualization/engine/q3dwindow.h index e9f8fe1d..1848ff29 100644 --- a/src/datavis3d/engine/q3dwindow.h +++ b/src/datavisualization/engine/q3dwindow.h @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -19,43 +19,47 @@ #ifndef Q3DWINDOW_H #define Q3DWINDOW_H -#include <QtDataVis3D/qdatavis3denums.h> +#include <QtDataVisualization/qdatavisualizationenums.h> #include <QWindow> #include <QOpenGLFunctions> +#include <QScreen> class QPainter; -QT_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVISUALIZATION_BEGIN_NAMESPACE class Q3DWindowPrivate; +class Abstract3DController; -class QT_DATAVIS3D_EXPORT Q3DWindow : public QWindow, protected QOpenGLFunctions +class QT_DATAVISUALIZATION_EXPORT Q3DWindow : public QWindow, protected QOpenGLFunctions { Q_OBJECT public: explicit Q3DWindow(QWindow *parent = 0); - ~Q3DWindow(); + virtual ~Q3DWindow(); -private slots: +protected slots: void renderLater(); void renderNow(); protected: virtual void render(); - void setAnimating(bool animating); bool event(QEvent *event); void exposeEvent(QExposeEvent *event); + void setVisualController(Abstract3DController *controller); + void handleDevicePixelRatioChange(); private: QScopedPointer<Q3DWindowPrivate> d_ptr; - friend class Q3DBarsPrivate; friend class Q3DBars; + friend class Q3DScatter; + friend class Q3DSurface; }; -QT_DATAVIS3D_END_NAMESPACE +QT_DATAVISUALIZATION_END_NAMESPACE #endif diff --git a/src/datavis3d/engine/q3dwindow_p.h b/src/datavisualization/engine/q3dwindow_p.h index d32facfa..6bef7e10 100644 --- a/src/datavis3d/engine/q3dwindow_p.h +++ b/src/datavisualization/engine/q3dwindow_p.h @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -20,7 +20,7 @@ // W A R N I N G // ------------- // -// This file is not part of the QtDataVis3D API. It exists purely as an +// 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. // @@ -29,14 +29,15 @@ #ifndef Q3DWINDOW_p_H #define Q3DWINDOW_p_H -#include "datavis3dglobal_p.h" +#include "datavisualizationglobal_p.h" class QOpenGLContext; class QOpenGLPaintDevice; -QT_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVISUALIZATION_BEGIN_NAMESPACE class Q3DWindow; +class Abstract3DController; class Q3DWindowPrivate { @@ -48,11 +49,11 @@ public: Q3DWindow *q_ptr; bool m_updatePending; - bool m_animating; - QOpenGLContext *m_context; + Abstract3DController *m_visualController; + qreal m_devicePixelRatio; }; -QT_DATAVIS3D_END_NAMESPACE +QT_DATAVISUALIZATION_END_NAMESPACE #endif diff --git a/src/datavisualization/engine/scatter3dcontroller.cpp b/src/datavisualization/engine/scatter3dcontroller.cpp new file mode 100644 index 00000000..9f43d94e --- /dev/null +++ b/src/datavisualization/engine/scatter3dcontroller.cpp @@ -0,0 +1,271 @@ +/**************************************************************************** +** +** 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 "scatter3dcontroller_p.h" +#include "scatter3drenderer_p.h" +#include "camerahelper_p.h" +#include "q3dabstractaxis_p.h" +#include "q3dvalueaxis_p.h" +#include "qscatterdataproxy_p.h" + +#include <QMatrix4x4> +#include <qmath.h> + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +Scatter3DController::Scatter3DController(QRect boundRect) + : Abstract3DController(boundRect), + m_renderer(0), + m_selectedItemIndex(noSelectionIndex()) +{ + // Default object type; specific to scatter + setObjectType(QDataVis::MeshStyleSpheres, false); + + setActiveDataProxy(new QScatterDataProxy); + + // Setting a null axis creates a new default axis according to orientation and graph type. + // Note: These cannot be set in Abstract3DController constructor, as they will call virtual + // functions implemented by subclasses. + setAxisX(0); + setAxisY(0); + setAxisZ(0); +} + +Scatter3DController::~Scatter3DController() +{ +} + +void Scatter3DController::initializeOpenGL() +{ + // Initialization is called multiple times when Qt Quick components are used + if (isInitialized()) + return; + + m_renderer = new Scatter3DRenderer(this); + setRenderer(m_renderer); + synchDataToRenderer(); + + QObject::connect(m_renderer, &Scatter3DRenderer::selectedItemIndexChanged, this, + &Scatter3DController::handleSelectedItemIndexChanged, Qt::QueuedConnection); + emitNeedRender(); +} + +void Scatter3DController::synchDataToRenderer() +{ + Abstract3DController::synchDataToRenderer(); + + if (!isInitialized()) + return; + + // Notify changes to renderer + if (m_changeTracker.slicingActiveChanged) { + // TODO: Add notification. + m_changeTracker.slicingActiveChanged = false; + } + + if (m_changeTracker.selectedItemIndexChanged) { + m_renderer->updateSelectedItemIndex(m_selectedItemIndex); + m_changeTracker.selectedItemIndexChanged = false; + } + + if (m_isDataDirty) { + m_renderer->updateDataModel(static_cast<QScatterDataProxy *>(m_data)); + m_isDataDirty = false; + } +} + + +void Scatter3DController::setActiveDataProxy(QAbstractDataProxy *proxy) +{ + // Setting null proxy indicates default proxy + if (!proxy) { + proxy = new QScatterDataProxy; + proxy->d_ptr->setDefaultProxy(true); + } + + Q_ASSERT(proxy->type() == QAbstractDataProxy::DataTypeScatter); + + Abstract3DController::setActiveDataProxy(proxy); + + QScatterDataProxy *scatterDataProxy = static_cast<QScatterDataProxy *>(m_data); + + QObject::connect(scatterDataProxy, &QScatterDataProxy::arrayReset, + this, &Scatter3DController::handleArrayReset); + QObject::connect(scatterDataProxy, &QScatterDataProxy::itemsAdded, + this, &Scatter3DController::handleItemsAdded); + QObject::connect(scatterDataProxy, &QScatterDataProxy::itemsChanged, + this, &Scatter3DController::handleItemsChanged); + QObject::connect(scatterDataProxy, &QScatterDataProxy::itemsRemoved, + this, &Scatter3DController::handleItemsRemoved); + QObject::connect(scatterDataProxy, &QScatterDataProxy::itemsInserted, + this, &Scatter3DController::handleItemsInserted); + + adjustValueAxisRange(); + setSelectedItemIndex(noSelectionIndex()); + setSlicingActive(false); + m_isDataDirty = true; + emitNeedRender(); +} + +void Scatter3DController::handleArrayReset() +{ + setSlicingActive(false); + adjustValueAxisRange(); + m_isDataDirty = true; + setSelectedItemIndex(noSelectionIndex()); + emitNeedRender(); +} + +void Scatter3DController::handleItemsAdded(int startIndex, int count) +{ + Q_UNUSED(startIndex) + Q_UNUSED(count) + // TODO should dirty only affected values? + adjustValueAxisRange(); + m_isDataDirty = true; + emitNeedRender(); +} + +void Scatter3DController::handleItemsChanged(int startIndex, int count) +{ + Q_UNUSED(startIndex) + Q_UNUSED(count) + // TODO should dirty only affected values? + adjustValueAxisRange(); + m_isDataDirty = true; + emitNeedRender(); +} + +void Scatter3DController::handleItemsRemoved(int startIndex, int count) +{ + Q_UNUSED(startIndex) + Q_UNUSED(count) + // TODO should dirty only affected values? + adjustValueAxisRange(); + m_isDataDirty = true; + if (startIndex >= static_cast<QScatterDataProxy *>(m_data)->itemCount()) + setSelectedItemIndex(noSelectionIndex()); + emitNeedRender(); +} + +void Scatter3DController::handleItemsInserted(int startIndex, int count) +{ + Q_UNUSED(startIndex) + Q_UNUSED(count) + // TODO should dirty only affected values? + adjustValueAxisRange(); + m_isDataDirty = true; + emitNeedRender(); +} + +void Scatter3DController::handleSelectedItemIndexChanged(int index) +{ + if (index != m_selectedItemIndex) { + m_selectedItemIndex = index; + emit selectedItemIndexChanged(index); + emitNeedRender(); + } +} + +void Scatter3DController::handleAxisAutoAdjustRangeChangedInOrientation( + Q3DAbstractAxis::AxisOrientation orientation, bool autoAdjust) +{ + Q_UNUSED(orientation) + Q_UNUSED(autoAdjust) + adjustValueAxisRange(); +} + +void Scatter3DController::setObjectType(QDataVis::MeshStyle style, bool smooth) +{ + QString objFile; + if (style == QDataVis::MeshStyleSpheres) { + if (smooth) + objFile = QStringLiteral(":/defaultMeshes/sphereSmooth"); + else + objFile = QStringLiteral(":/defaultMeshes/sphere"); + } else { + if (smooth) + objFile = QStringLiteral(":/defaultMeshes/dotSmooth"); + else + objFile = QStringLiteral(":/defaultMeshes/dot"); + } + Abstract3DController::setMeshFileName(objFile); +} + +void Scatter3DController::setSelectionMode(QDataVis::SelectionMode mode) +{ + if (mode > QDataVis::SelectionModeItem) { + qWarning("Unsupported selection mode."); + return; + } + // Disable zoom if selection mode changes + setSlicingActive(false); + Abstract3DController::setSelectionMode(mode); +} + +void Scatter3DController::setSelectedItemIndex(int index) +{ + // TODO If items not within axis ranges are culled from drawing, should they be + // TODO unselectable as well? + if (index < 0 || index >= static_cast<QScatterDataProxy *>(m_data)->itemCount()) + index = noSelectionIndex(); + + if (index != m_selectedItemIndex) { + m_selectedItemIndex = index; + m_changeTracker.selectedItemIndexChanged = true; + emit selectedItemIndexChanged(index); + emitNeedRender(); + } +} + +int Scatter3DController::selectedItemIndex() const +{ + return m_selectedItemIndex; +} + +void Scatter3DController::adjustValueAxisRange() +{ + if (m_data) { + QVector3D limits = static_cast<QScatterDataProxy *>(m_data)->dptr()->limitValues(); + Q3DValueAxis *valueAxis = static_cast<Q3DValueAxis *>(m_axisX); + if (valueAxis && valueAxis->isAutoAdjustRange()) { + if (limits.x() > 0) + valueAxis->dptr()->setRange(-limits.x(), limits.x()); + else + valueAxis->dptr()->setRange(-1.0, 1.0); // Only zero value values in data set, set range to default. + } + + valueAxis = static_cast<Q3DValueAxis *>(m_axisY); + if (valueAxis && valueAxis->isAutoAdjustRange()) { + if (limits.y() > 0) + valueAxis->dptr()->setRange(-limits.y(), limits.y()); + else + valueAxis->dptr()->setRange(-1.0, 1.0); // Only zero value values in data set, set range to default. + } + + valueAxis = static_cast<Q3DValueAxis *>(m_axisZ); + if (valueAxis && valueAxis->isAutoAdjustRange()) { + if (limits.z() > 0) + valueAxis->dptr()->setRange(-limits.z(), limits.z()); + else + valueAxis->dptr()->setRange(-1.0, 1.0); // Only zero value values in data set, set range to default. + } + } +} + +QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavis3d/engine/scatter3dcontroller_p.h b/src/datavisualization/engine/scatter3dcontroller_p.h index 437664b7..63735aca 100644 --- a/src/datavis3d/engine/scatter3dcontroller_p.h +++ b/src/datavisualization/engine/scatter3dcontroller_p.h @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -20,7 +20,7 @@ // W A R N I N G // ------------- // -// This file is not part of the QtDataVis3D API. It exists purely as an +// 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. // @@ -29,40 +29,37 @@ #ifndef Q3DSCATTERCONTROLLER_p_H #define Q3DSCATTERCONTROLLER_p_H -#include "datavis3dglobal_p.h" +#include "datavisualizationglobal_p.h" #include "abstract3dcontroller_p.h" //#define DISPLAY_RENDER_SPEED -QT_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVISUALIZATION_BEGIN_NAMESPACE class Scatter3DRenderer; class QScatterDataProxy; struct Scatter3DChangeBitField { bool slicingActiveChanged : 1; + bool selectedItemIndexChanged : 1; Scatter3DChangeBitField() : - slicingActiveChanged(true) + slicingActiveChanged(true), + selectedItemIndexChanged(true) { } }; -class QT_DATAVIS3D_EXPORT Scatter3DController : public Abstract3DController +class QT_DATAVISUALIZATION_EXPORT Scatter3DController : public Abstract3DController { Q_OBJECT private: Scatter3DChangeBitField m_changeTracker; - // Interaction - MouseState m_mouseState; - QPoint m_mousePos; - bool m_isSlicingActivated; - // Rendering Scatter3DRenderer *m_renderer; - QScatterDataProxy *m_data; + int m_selectedItemIndex; public: explicit Scatter3DController(QRect rect); @@ -70,37 +67,21 @@ public: void initializeOpenGL(); - MouseState mouseState(); - QPoint mousePosition(); - - bool isSlicingActive(); - void setSlicingActive(bool isSlicing); - - QMatrix4x4 calculateViewMatrix(int zoom, int viewPortWidth, int viewPortHeight, - bool showUnder = false); - // Object type void setObjectType(QDataVis::MeshStyle style, bool smooth = false); // Change selection mode void setSelectionMode(QDataVis::SelectionMode mode); -#if defined(Q_OS_ANDROID) - void mouseDoubleClickEvent(QMouseEvent *event); - void touchEvent(QTouchEvent *event); -#endif - void mousePressEvent(QMouseEvent *event, const QPoint &mousePos); - void mouseReleaseEvent(QMouseEvent *event, const QPoint &mousePos); - void mouseMoveEvent(QMouseEvent *event, const QPoint &mousePos); - void wheelEvent(QWheelEvent *event); + void setSelectedItemIndex(int index); + int selectedItemIndex() const; + static inline int noSelectionIndex() { return -1; } - // Sets the data proxy. Assumes ownership of the data proxy. Deletes old proxy. - void setDataProxy(QScatterDataProxy *proxy); - QScatterDataProxy *dataProxy(); + virtual void setActiveDataProxy(QAbstractDataProxy *proxy); void synchDataToRenderer(); - virtual void handleAxisAutoAdjustRangeChangedInOrientation(QAbstractAxis::AxisOrientation orientation, bool autoAdjust); + virtual void handleAxisAutoAdjustRangeChangedInOrientation(Q3DAbstractAxis::AxisOrientation orientation, bool autoAdjust); public slots: void handleArrayReset(); @@ -108,9 +89,10 @@ public slots: void handleItemsChanged(int startIndex, int count); void handleItemsRemoved(int startIndex, int count); void handleItemsInserted(int startIndex, int count); + void handleSelectedItemIndexChanged(int index); signals: - void slicingActiveChanged(bool isSlicing); + void selectedItemIndexChanged(int index); private: void adjustValueAxisRange(); @@ -119,6 +101,6 @@ private: }; -QT_DATAVIS3D_END_NAMESPACE +QT_DATAVISUALIZATION_END_NAMESPACE #endif diff --git a/src/datavis3d/engine/scatter3drenderer.cpp b/src/datavisualization/engine/scatter3drenderer.cpp index a7657547..a482cc42 100644 --- a/src/datavis3d/engine/scatter3drenderer.cpp +++ b/src/datavisualization/engine/scatter3drenderer.cpp @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -18,11 +18,13 @@ #include "scatter3drenderer_p.h" #include "scatter3dcontroller_p.h" -#include "camerahelper_p.h" +#include "q3dcamera.h" +#include "q3dcamera_p.h" #include "shaderhelper_p.h" #include "objecthelper_p.h" #include "texturehelper_p.h" #include "utils_p.h" +#include "q3dlight.h" #include <QMatrix4x4> #include <QMouseEvent> @@ -38,17 +40,12 @@ // You should see the scene from where the light is //#define SHOW_DEPTH_TEXTURE_SCENE -#ifdef DISPLAY_RENDER_SPEED -#include <QTime> -#endif - -QT_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVISUALIZATION_BEGIN_NAMESPACE //#define USE_UNIFORM_SCALING // Scale x and z uniformly, or based on autoscaled values -#define DISPLAY_FULL_DATA_ON_SELECTION // Append selection value text with row and column labels - const GLfloat aspectRatio = 2.0f; // Forced ratio of x and z to y. Dynamic will make it look odd. +const GLfloat labelMargin = 0.05f; // TODO: Make margin modifiable? const GLfloat backgroundMargin = 1.1f; // Margin for background (1.1f = make it 10% larger to avoid items being drawn inside background) const GLfloat gridLineWidth = 0.005f; @@ -58,7 +55,6 @@ Scatter3DRenderer::Scatter3DRenderer(Scatter3DController *controller) : Abstract3DRenderer(controller), m_controller(controller), m_selectedItem(0), - m_previouslySelectedItem(0), m_xFlipped(false), m_zFlipped(false), m_yFlipped(false), @@ -78,27 +74,22 @@ Scatter3DRenderer::Scatter3DRenderer(Scatter3DController *controller) m_depthFrameBuffer(0), m_selectionFrameBuffer(0), m_selectionDepthBuffer(0), - m_shadowQualityToShader(33.3f), + m_shadowQualityToShader(100.0f), + m_shadowQualityMultiplier(3), m_heightNormalizer(1.0f), m_scaleFactor(0), m_selection(selectionSkipColor), - m_areaSize(QSizeF(0.0f, 0.0f)), - m_hasHeightAdjustmentChanged(true), - m_dotSizeScale(1.0f) - #ifdef DISPLAY_RENDER_SPEED - , m_isFirstFrame(true), - m_numFrames(0) - #endif + m_previousSelection(selectionSkipColor), + m_areaSize(QSizeF(0.0, 0.0)), + m_dotSizeScale(1.0f), + m_hasHeightAdjustmentChanged(true) { - //qDebug() << __FUNCTION__; - m_dummyRenderItem.setRenderer(this); initializeOpenGLFunctions(); initializeOpenGL(); } Scatter3DRenderer::~Scatter3DRenderer() { - //qDebug() << __FUNCTION__; m_textureHelper->glDeleteFramebuffers(1, &m_selectionFrameBuffer); m_textureHelper->glDeleteRenderbuffers(1, &m_selectionDepthBuffer); m_textureHelper->deleteTexture(&m_selectionTexture); @@ -108,17 +99,16 @@ Scatter3DRenderer::~Scatter3DRenderer() delete m_depthShader; delete m_selectionShader; delete m_backgroundShader; + delete m_labelShader; delete m_dotObj; delete m_backgroundObj; delete m_gridLineObj; - delete m_textureHelper; + delete m_labelObj; } void Scatter3DRenderer::initializeOpenGL() { - //qDebug() << __FUNCTION__; - m_textureHelper = new TextureHelper(); - m_drawer->initializeOpenGL(); + Abstract3DRenderer::initializeOpenGL(); // Initialize shaders handleShadowQualityChange(); @@ -140,30 +130,12 @@ void Scatter3DRenderer::initializeOpenGL() // Load label mesh loadLabelMesh(); - // Set OpenGL features - glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_LESS); - glEnable(GL_CULL_FACE); - glCullFace(GL_BACK); - -#if !defined(QT_OPENGL_ES_2) - glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); - glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); - glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST); -#endif - // Set view port glViewport(m_mainViewPort.x(), m_mainViewPort.y(), m_mainViewPort.width(), m_mainViewPort.height()); - // Resize in case we've missed resize events - // Resize calls initSelectionBuffer and initDepthBuffer, so they don't need to be called here - handleResize(); - // Load background mesh (we need to be initialized first) loadBackgroundMesh(); - - Abstract3DRenderer::initializeOpenGL(); } void Scatter3DRenderer::updateDataModel(QScatterDataProxy *dataProxy) @@ -171,69 +143,69 @@ void Scatter3DRenderer::updateDataModel(QScatterDataProxy *dataProxy) const QScatterDataArray &dataArray = *dataProxy->array(); calculateSceneScalingFactors(); int dataSize = dataArray.size(); - m_renderItemArray.resize(dataSize); + float minX = float(m_axisCacheX.min()); + float maxX = float(m_axisCacheX.max()); + float minY = float(m_axisCacheY.min()); + float maxY = float(m_axisCacheY.max()); + float minZ = float(m_axisCacheZ.min()); + float maxZ = float(m_axisCacheZ.max()); + + if (dataSize != m_renderItemArray.size()) + m_renderItemArray.resize(dataSize); for (int i = 0; i < dataSize ; i++) { - qreal value = dataArray.at(i).position().y(); - m_renderItemArray[i].setValue(value); - m_renderItemArray[i].setPosition(dataArray.at(i).position()); - //m_renderItemArray[i].setHeight(value / m_heightNormalizer); - //m_renderItemArray[i].setItemLabel(dataArray.at(i).label()); - calculateTranslation(m_renderItemArray[i]); - m_renderItemArray[i].setRenderer(this); + QVector3D dotPos = dataArray.at(i).position(); + // TODO: Check if this still works always when ranges are no longer required to be zero centered + // TODO: qreal -> float conversion for axis min/max may cause issues like in surface + if ((dotPos.x() >= minX && dotPos.x() <= maxX ) + && (dotPos.y() >= minY && dotPos.y() <= maxY) + && (dotPos.z() >= minZ && dotPos.z() <= maxZ)) { + m_renderItemArray[i].setPosition(dotPos); + m_renderItemArray[i].setVisible(true); + calculateTranslation(m_renderItemArray[i]); + } else { + m_renderItemArray[i].setVisible(false); + } } - m_dotSizeScale = (GLfloat)qBound(0.01, (qreal)(2.0f / qSqrt((qreal)dataSize)), 0.1); + m_dotSizeScale = (GLfloat)qBound(0.01, (2.0 / qSqrt((qreal)dataSize)), 0.1); + m_selectedItem = 0; Abstract3DRenderer::updateDataModel(dataProxy); } -void Scatter3DRenderer::render(CameraHelper *camera, const GLuint defaultFboHandle) +void Scatter3DRenderer::updateScene(Q3DScene *scene) { - //qDebug() << __FUNCTION__; + // TODO: Move these to more suitable place e.g. controller should be controlling the viewports. + scene->setPrimarySubViewport(m_mainViewPort); -#ifdef DISPLAY_RENDER_SPEED - // For speed computation - if (m_isFirstFrame) { - m_lastFrameTime.start(); - m_isFirstFrame = false; - } + // TODO: See QTRD-2374 + scene->activeCamera()->setMinYRotation(-90.0f); - // Measure speed (as milliseconds per frame) - m_numFrames++; - if (m_lastFrameTime.elapsed() >= 1000) { // print only if last measurement was more than 1s ago - qDebug() << qreal(m_lastFrameTime.elapsed()) / qreal(m_numFrames) << "ms/frame (=" << qreal(m_numFrames) << "fps)"; - m_numFrames = 0; - m_lastFrameTime.restart(); + if (m_hasHeightAdjustmentChanged) { + // Set initial m_cachedScene->activeCamera() position. Also update if height adjustment has changed. + scene->activeCamera()->setBaseOrientation(QVector3D(0.0f, 0.0f, cameraDistance + zComp), + QVector3D(0.0f, 0.0f, zComp), + QVector3D(0.0f, 1.0f, 0.0f)); + m_hasHeightAdjustmentChanged = false; } -#endif - if (defaultFboHandle) { - glDepthMask(true); - glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_LESS); - glEnable(GL_CULL_FACE); - glCullFace(GL_BACK); - } + scene->activeCamera()->d_ptr->updateViewMatrix(m_autoScaleAdjustment); + // Set light position (rotate light with m_cachedScene->activeCamera(), a bit above it (as set in defaultLightPos)) + scene->setLightPositionRelativeToCamera(defaultLightPos); - QVector3D clearColor = Utils::vectorFromColor(m_cachedTheme.m_windowColor); - glClearColor(clearColor.x(), clearColor.y(), clearColor.z(), 1.0f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + Abstract3DRenderer::updateScene(scene); +} - if (m_hasHeightAdjustmentChanged) { - // Set initial camera position. Also update if height adjustment has changed. - camera->setDefaultCameraOrientation(QVector3D(0.0f, 0.0f, 6.0f + zComp), - QVector3D(0.0f, 0.0f, zComp), - QVector3D(0.0f, 1.0f, 0.0f)); - m_hasHeightAdjustmentChanged = false; - } +void Scatter3DRenderer::render(GLuint defaultFboHandle) +{ + // Handle GL state setup for FBO buffers and clearing of the render surface + Abstract3DRenderer::render(defaultFboHandle); - // Draw bars scene - drawScene(camera, defaultFboHandle); + // Draw dots scene + drawScene(defaultFboHandle); } -void Scatter3DRenderer::drawScene(CameraHelper *camera, - const GLuint defaultFboHandle) +void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle) { - //qDebug() << __FUNCTION__; GLfloat backgroundRotation = 0; // Specify viewport @@ -246,11 +218,7 @@ void Scatter3DRenderer::drawScene(CameraHelper *camera, / (GLfloat)m_mainViewPort.height(), 0.1f, 100.0f); // Calculate view matrix - QMatrix4x4 viewMatrix = m_controller->calculateViewMatrix( - m_cachedZoomLevel * m_autoScaleAdjustment, - m_mainViewPort.width(), - m_mainViewPort.height(), - true); + QMatrix4x4 viewMatrix = m_cachedScene->activeCamera()->viewMatrix(); // Calculate label flipping if (viewMatrix.row(0).x() > 0) @@ -278,8 +246,8 @@ void Scatter3DRenderer::drawScene(CameraHelper *camera, else if (m_zFlipped && !m_xFlipped) backgroundRotation = 0.0f; - // Get light position (rotate light with camera, a bit above it (as set in defaultLightPos)) - QVector3D lightPos = camera->calculateLightPosition(defaultLightPos); + // Get light position from the scene + QVector3D lightPos = m_cachedScene->activeLight()->position(); // Map adjustment direction to model matrix scaling // TODO: Let's use these for testing the autoscaling of dots based on their number @@ -289,63 +257,21 @@ void Scatter3DRenderer::drawScene(CameraHelper *camera, GLfloat heightScaler = 0.0f; GLfloat widthScaler = 0.0f; GLfloat depthScaler = 0.0f; - // switch (m_adjustDirection) { - // case Q3DMaps::AdjustHeight: - // widthMultiplier = 0.0f; - // heightMultiplier = 1.0f; - // depthMultiplier = 0.0f; - // widthScaler = m_barThickness.x() / m_scaleFactor; - // heightScaler = 0.0f; - // depthScaler = m_barThickness.z() / m_scaleFactor; - // break; - // case Q3DMaps::AdjustWidth: - // widthMultiplier = 1.0f; - // heightMultiplier = 0.0f; - // depthMultiplier = 0.0f; - // widthScaler = 0.0f; - // heightScaler = m_barThickness.y() / m_scaleFactor; - // depthScaler = m_barThickness.z() / m_scaleFactor; - // break; - // case Q3DMaps::AdjustDepth: - // widthMultiplier = 0.0f; - // heightMultiplier = 0.0f; - // depthMultiplier = 1.0f; - // widthScaler = m_barThickness.x() / m_scaleFactor; - // heightScaler = m_barThickness.y() / m_scaleFactor; - // depthScaler = 0.0f; - // break; - // case Q3DMaps::AdjustRadius: - // widthMultiplier = 1.0f; - // heightMultiplier = 0.0f; - // depthMultiplier = 1.0f; - // widthScaler = 0.0f; - // heightScaler = m_barThickness.y() / m_scaleFactor; - // depthScaler = 0.0f; - // break; - // case Q3DMaps::AdjustAll: - // widthMultiplier = 1.0f; - // heightMultiplier = 1.0f; - // depthMultiplier = 1.0f; - // widthScaler = 0.0f; - // heightScaler = 0.0f; - // depthScaler = 0.0f; - // break; - // } // Introduce regardless of shadow quality to simplify logic QMatrix4x4 depthViewMatrix; QMatrix4x4 depthProjectionMatrix; #if !defined(QT_OPENGL_ES_2) - if (m_cachedShadowQuality > QDataVis::ShadowNone) { + if (m_cachedShadowQuality > QDataVis::ShadowQualityNone) { // Render scene into a depth texture for using with shadow mapping // Bind depth shader m_depthShader->bind(); // Set viewport for depth map rendering. Must match texture size. Larger values give smoother shadows. glViewport(m_mainViewPort.x(), m_mainViewPort.y(), - m_mainViewPort.width() * m_cachedShadowQuality, - m_mainViewPort.height() * m_cachedShadowQuality); + m_mainViewPort.width() * m_shadowQualityMultiplier, + m_mainViewPort.height() * m_shadowQualityMultiplier); // Enable drawing to framebuffer glBindFramebuffer(GL_FRAMEBUFFER, m_depthFrameBuffer); @@ -356,12 +282,13 @@ void Scatter3DRenderer::drawScene(CameraHelper *camera, // Get the depth view matrix // It may be possible to hack lightPos here if we want to make some tweaks to shadow - QVector3D depthLightPos = camera->calculateLightPosition( + QVector3D depthLightPos = m_cachedScene->activeCamera()->calculatePositionRelativeToCamera( defaultLightPos, 0.0f, 1.0f / m_autoScaleAdjustment); depthViewMatrix.lookAt(depthLightPos, QVector3D(0.0f, 0.0f, zComp), QVector3D(0.0f, 1.0f, 0.0f)); - // TODO: Why does depthViewMatrix.column(3).y() goes to zero when we're directly above? That causes the scene to be not drawn from above -> must be fixed - //qDebug() << lightPos << depthViewMatrix << depthViewMatrix.column(3); + // TODO: Why does depthViewMatrix.column(3).y() goes to zero when we're directly above? + // That causes the scene to be not drawn from above -> must be fixed + // qDebug() << lightPos << depthViewMatrix << depthViewMatrix.column(3); // Set the depth projection matrix #ifndef USE_WIDER_SHADOWS // Use this for perspective shadows @@ -377,10 +304,10 @@ void Scatter3DRenderer::drawScene(CameraHelper *camera, -m_heightNormalizer * 2.0f, m_heightNormalizer * 2.0f, 0.0f, 100.0f); #endif - // Draw bars to depth buffer - for (int bar = 0; bar < m_renderItemArray.size(); bar++) { - const ScatterRenderItem &item = m_renderItemArray.at(bar); - if (!item.value()) + // Draw dots to depth buffer + for (int dot = 0; dot < m_renderItemArray.size(); dot++) { + const ScatterRenderItem &item = m_renderItemArray.at(dot); + if (!item.isVisible()) continue; QMatrix4x4 modelMatrix; @@ -452,23 +379,24 @@ void Scatter3DRenderer::drawScene(CameraHelper *camera, #endif // Skip selection mode drawing if we have no selection mode - if (m_cachedSelectionMode > QDataVis::ModeNone) { + if (m_cachedSelectionMode > QDataVis::SelectionModeNone) { // Bind selection shader m_selectionShader->bind(); - // Draw bars to selection buffer + // Draw dots to selection buffer glBindFramebuffer(GL_FRAMEBUFFER, m_selectionFrameBuffer); glEnable(GL_DEPTH_TEST); // Needed, otherwise the depth render buffer is not used - glClearColor(selectionSkipColor.x() / 255, selectionSkipColor.y() / 255, - selectionSkipColor.z() / 255, 1.0f); // Set clear color to white (= skipColor) + glClearColor(1.0f, 1.0f, 1.0f, 1.0f); // Set clear color to white (= skipColor) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Needed for clearing the frame buffer glDisable(GL_DITHER); // disable dithering, it may affect colors if enabled - GLint barIdxRed = 0; - GLint barIdxGreen = 0; - GLint barIdxBlue = 0; - for (int bar = 0; bar < m_renderItemArray.size(); bar++, barIdxRed++) { - const ScatterRenderItem &item = m_renderItemArray.at(bar); - if (!item.value()) + + int arraySize = m_renderItemArray.size(); + if (arraySize > 0xfffffe) // Max possible different selection colors, 0xffffff being skipColor + qFatal("Too many objects"); + + for (int dot = 0; dot < arraySize; dot++) { + const ScatterRenderItem &item = m_renderItemArray.at(dot); + if (!item.isVisible()) continue; QMatrix4x4 modelMatrix; @@ -486,23 +414,11 @@ void Scatter3DRenderer::drawScene(CameraHelper *camera, MVPMatrix = projectionMatrix * viewMatrix * modelMatrix; - if (barIdxRed > 0 && barIdxRed % 256 == 0) { - barIdxRed = 0; - barIdxGreen++; - } - if (barIdxGreen > 0 && barIdxGreen % 256 == 0) { - barIdxGreen = 0; - barIdxBlue++; - } - if (barIdxBlue > 255) - qFatal("Too many objects"); - - QVector3D barColor = QVector3D((GLfloat)barIdxRed / 255.0f, - (GLfloat)barIdxGreen / 255.0f, - (GLfloat)barIdxBlue / 255.0f); + QVector3D dotColor = indexToSelectionColor(dot); + dotColor /= 255.0f; m_selectionShader->setUniformValue(m_selectionShader->MVP(), MVPMatrix); - m_selectionShader->setUniformValue(m_selectionShader->color(), barColor); + m_selectionShader->setUniformValue(m_selectionShader->color(), dotColor); // 1st attribute buffer : vertices glEnableVertexAttribArray(m_selectionShader->posAtt()); @@ -524,18 +440,10 @@ void Scatter3DRenderer::drawScene(CameraHelper *camera, glEnable(GL_DITHER); // Read color under cursor - if (Scatter3DController::MouseOnScene == m_controller->mouseState()) - m_selection = Utils::getSelection(m_controller->mousePosition(), - m_cachedBoundingRect.height()); - - QMutexLocker locker(&m_mutex); - if (m_isSelectionPointRequestActive) { - m_isSelectionPointRequestActive = false; - m_selection = Utils::getSelection(m_selectionPointRequest, + if (QDataVis::InputStateOnScene == m_controller->inputState()) { + m_selection = Utils::getSelection(m_controller->inputPosition(), m_cachedBoundingRect.height()); - emit selectionUpdated(m_selection); } - locker.unlock(); glBindFramebuffer(GL_FRAMEBUFFER, defaultFboHandle); @@ -561,17 +469,33 @@ void Scatter3DRenderer::drawScene(CameraHelper *camera, #endif } - // Bind bar shader + // Bind dot shader m_dotShader->bind(); // Enable texture glEnable(GL_TEXTURE_2D); - // Draw bars - bool barSelectionFound = false; - for (int bar = 0; bar < m_renderItemArray.size(); bar++) { - ScatterRenderItem &item = m_renderItemArray[bar]; - if (!item.value()) + // Draw dots + bool dotSelectionFound = false; + int selectedIndex; + if (m_selection == selectionSkipColor) { + selectedIndex = Scatter3DController::noSelectionIndex(); + } else { + selectedIndex = int(m_selection.x()) + + (int(m_selection.y()) << 8) + + (int(m_selection.z()) << 16); + } + + if (m_selection != m_previousSelection) { + emit selectedItemIndexChanged(selectedIndex); + m_previousSelection = m_selection; + } + + ScatterRenderItem *selectedItem(0); + + for (int dot = 0; dot < m_renderItemArray.size(); dot++) { + ScatterRenderItem &item = m_renderItemArray[dot]; + if (!item.isVisible()) continue; QMatrix4x4 modelMatrix; @@ -602,35 +526,23 @@ void Scatter3DRenderer::drawScene(CameraHelper *camera, #endif depthMVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; +#if 0 QVector3D baseColor = Utils::vectorFromColor(m_cachedTheme.m_baseColor); QVector3D heightColor = Utils::vectorFromColor(m_cachedTheme.m_heightColor) * item.translation().y(); - QVector3D barColor = baseColor + heightColor; + QVector3D dotColor = baseColor + heightColor; +#else + QVector3D dotColor = Utils::vectorFromColor(m_cachedTheme.m_baseColor); +#endif GLfloat lightStrength = m_cachedTheme.m_lightStrength; - if (m_cachedSelectionMode > QDataVis::ModeNone) { - Scatter3DController::SelectionType selectionType = isSelected(bar, m_selection); - switch (selectionType) { - case Scatter3DController::SelectionItem: { - barColor = Utils::vectorFromColor(m_cachedTheme.m_highlightBarColor); - lightStrength = m_cachedTheme.m_highlightLightStrength; - // Insert data to ScatterRenderItem. We have no ownership, don't delete the previous one - m_selectedItem = &item; - barSelectionFound = true; - break; - } - case Scatter3DController::SelectionNone: { - // Current bar is not selected, nor on a row or column - // do nothing - break; - } - default: { - // Unsupported selection mode - // do nothing - break; - } - } + if (m_cachedSelectionMode > QDataVis::SelectionModeNone && (selectedIndex == dot)) { + dotColor = Utils::vectorFromColor(m_cachedTheme.m_highlightBarColor); + lightStrength = m_cachedTheme.m_highlightLightStrength; + // Insert data to ScatterRenderItem. We have no ownership, don't delete the previous one + selectedItem = &item; + dotSelectionFound = true; } // Set shader bindings @@ -640,11 +552,11 @@ void Scatter3DRenderer::drawScene(CameraHelper *camera, m_dotShader->setUniformValue(m_dotShader->nModel(), itModelMatrix.inverted().transposed()); m_dotShader->setUniformValue(m_dotShader->MVP(), MVPMatrix); - m_dotShader->setUniformValue(m_dotShader->color(), barColor); + m_dotShader->setUniformValue(m_dotShader->color(), dotColor); m_dotShader->setUniformValue(m_dotShader->ambientS(), m_cachedTheme.m_ambientStrength); #if !defined(QT_OPENGL_ES_2) - if (m_cachedShadowQuality > QDataVis::ShadowNone) { + if (m_cachedShadowQuality > QDataVis::ShadowQualityNone) { // Set shadow shader bindings m_dotShader->setUniformValue(m_dotShader->shadowQ(), m_shadowQualityToShader); m_dotShader->setUniformValue(m_dotShader->depth(), depthMVPMatrix); @@ -663,7 +575,7 @@ void Scatter3DRenderer::drawScene(CameraHelper *camera, } } - // Release bar shader + // Release dot shader m_dotShader->release(); // Bind background shader @@ -678,20 +590,18 @@ void Scatter3DRenderer::drawScene(CameraHelper *camera, QMatrix4x4 depthMVPMatrix; QMatrix4x4 itModelMatrix; - modelMatrix.translate(0.0f, 0.0f, zComp); #ifndef USE_UNIFORM_SCALING // Use this if we want to use autoscaling for x and z - modelMatrix.scale( - QVector3D( - (aspectRatio * backgroundMargin * m_areaSize.width()) / m_scaleFactor, - backgroundMargin, - (aspectRatio * backgroundMargin * m_areaSize.height()) / m_scaleFactor)); + QVector3D bgScale((aspectRatio * backgroundMargin * m_areaSize.width()) / m_scaleFactor, + backgroundMargin, + (aspectRatio * backgroundMargin * m_areaSize.height()) / m_scaleFactor); #else // ..and this if we want uniform scaling based on largest dimension - modelMatrix.scale(QVector3D((aspectRatio * backgroundMargin), - backgroundMargin, - (aspectRatio * backgroundMargin))); + QVector3D bgScale((aspectRatio * backgroundMargin), + backgroundMargin, + (aspectRatio * backgroundMargin)); #endif - // We can copy modelMatrix to itModelMatrix as it has not been translated - itModelMatrix = modelMatrix; + modelMatrix.translate(0.0f, 0.0f, zComp); + modelMatrix.scale(bgScale); + itModelMatrix.scale(bgScale); // If we're viewing from below, background object must be flipped if (m_yFlipped) { modelMatrix.rotate(180.0f, 1.0, 0.0, 0.0); @@ -721,7 +631,7 @@ void Scatter3DRenderer::drawScene(CameraHelper *camera, m_cachedTheme.m_ambientStrength * 2.0f); #if !defined(QT_OPENGL_ES_2) - if (m_cachedShadowQuality > QDataVis::ShadowNone) { + if (m_cachedShadowQuality > QDataVis::ShadowQualityNone) { // Set shadow shader bindings m_backgroundShader->setUniformValue(m_backgroundShader->shadowQ(), m_shadowQualityToShader); @@ -759,21 +669,23 @@ void Scatter3DRenderer::drawScene(CameraHelper *camera, #endif if (m_cachedIsGridEnabled && m_heightNormalizer) { - // Bind bar shader - m_dotShader->bind(); + ShaderHelper *lineShader = m_backgroundShader; + // Bind line shader + lineShader->bind(); // Set unchanging shader bindings - QVector3D barColor = Utils::vectorFromColor(m_cachedTheme.m_gridLine); - m_dotShader->setUniformValue(m_dotShader->lightP(), lightPos); - m_dotShader->setUniformValue(m_dotShader->view(), viewMatrix); - m_dotShader->setUniformValue(m_dotShader->color(), barColor); - m_dotShader->setUniformValue(m_dotShader->ambientS(), m_cachedTheme.m_ambientStrength); + QVector3D lineColor = Utils::vectorFromColor(m_cachedTheme.m_gridLine); + lineShader->setUniformValue(lineShader->lightP(), lightPos); + lineShader->setUniformValue(lineShader->view(), viewMatrix); + lineShader->setUniformValue(lineShader->color(), lineColor); + lineShader->setUniformValue(lineShader->ambientS(), m_cachedTheme.m_ambientStrength); - // Floor lines: rows (= Z) + // Rows (= Z) if (m_axisCacheZ.segmentCount() > 0) { + // Floor lines #ifndef USE_UNIFORM_SCALING GLfloat lineStep = aspectRatio * m_axisCacheZ.subSegmentStep(); - GLfloat linePos = aspectRatio * m_axisCacheZ.min(); // Start line + GLfloat linePos = -aspectRatio * m_axisCacheZ.min(); // Start line int lastSegment = m_axisCacheZ.subSegmentCount() * m_axisCacheZ.segmentCount(); #else GLfloat lineStep = aspectRatio * axisCacheMax->subSegmentStep(); @@ -787,15 +699,10 @@ void Scatter3DRenderer::drawScene(CameraHelper *camera, QMatrix4x4 depthMVPMatrix; QMatrix4x4 itModelMatrix; - if (m_yFlipped) { - modelMatrix.translate(0.0f, - backgroundMargin, - linePos / m_scaleFactor + zComp); - } else { - modelMatrix.translate(0.0f, - -backgroundMargin, - linePos / m_scaleFactor + zComp); - } + if (m_yFlipped) + modelMatrix.translate(0.0f, backgroundMargin, linePos / m_scaleFactor + zComp); + else + modelMatrix.translate(0.0f, -backgroundMargin, linePos / m_scaleFactor + zComp); #ifndef USE_UNIFORM_SCALING // Use this if we want to use autoscaling for x and z modelMatrix.scale( QVector3D( @@ -820,37 +727,92 @@ void Scatter3DRenderer::drawScene(CameraHelper *camera, depthMVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; // Set the rest of the shader bindings - m_dotShader->setUniformValue(m_dotShader->model(), modelMatrix); - m_dotShader->setUniformValue(m_dotShader->nModel(), - itModelMatrix.inverted().transposed()); - m_dotShader->setUniformValue(m_dotShader->MVP(), MVPMatrix); + lineShader->setUniformValue(lineShader->model(), modelMatrix); + lineShader->setUniformValue(lineShader->nModel(), + itModelMatrix.inverted().transposed()); + lineShader->setUniformValue(lineShader->MVP(), MVPMatrix); #if !defined(QT_OPENGL_ES_2) - if (m_cachedShadowQuality > QDataVis::ShadowNone) { + if (m_cachedShadowQuality > QDataVis::ShadowQualityNone) { // Set shadow shader bindings - m_dotShader->setUniformValue(m_dotShader->shadowQ(), m_shadowQualityToShader); - m_dotShader->setUniformValue(m_dotShader->depth(), depthMVPMatrix); - m_dotShader->setUniformValue(m_dotShader->lightS(), - m_cachedTheme.m_lightStrength / 10.0f); + lineShader->setUniformValue(lineShader->shadowQ(), m_shadowQualityToShader); + lineShader->setUniformValue(lineShader->depth(), depthMVPMatrix); + lineShader->setUniformValue(lineShader->lightS(), + m_cachedTheme.m_lightStrength / 10.0f); // Draw the object - m_drawer->drawObject(m_dotShader, m_gridLineObj, 0, m_depthTexture); + m_drawer->drawObject(lineShader, m_gridLineObj, 0, m_depthTexture); } else #endif { // Set shadowless shader bindings - m_dotShader->setUniformValue(m_dotShader->lightS(), - m_cachedTheme.m_lightStrength); + lineShader->setUniformValue(lineShader->lightS(), + m_cachedTheme.m_lightStrength); // Draw the object - m_drawer->drawObject(m_dotShader, m_gridLineObj); + m_drawer->drawObject(lineShader, m_gridLineObj); } - linePos += lineStep; + linePos -= lineStep; + } + + // Side wall lines +#ifndef USE_UNIFORM_SCALING + GLfloat lineXTrans = (aspectRatio * backgroundMargin * m_areaSize.width()) + / m_scaleFactor; + linePos = -aspectRatio * m_axisCacheZ.min(); // Start line +#else + GLfloat lineXTrans = aspectRatio * backgroundMargin; + linePos = -aspectRatio * m_scaleFactor; // Start line +#endif + if (!m_xFlipped) + lineXTrans = -lineXTrans; + + for (int segment = 0; segment <= lastSegment; segment++) { + QMatrix4x4 modelMatrix; + QMatrix4x4 MVPMatrix; + QMatrix4x4 depthMVPMatrix; + QMatrix4x4 itModelMatrix; + + modelMatrix.translate(lineXTrans, 0.0f, linePos / m_scaleFactor + zComp); + modelMatrix.scale(QVector3D(gridLineWidth, backgroundMargin, gridLineWidth)); + itModelMatrix.scale(QVector3D(gridLineWidth, backgroundMargin, gridLineWidth)); + + MVPMatrix = projectionMatrix * viewMatrix * modelMatrix; + depthMVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; + + // Set the rest of the shader bindings + lineShader->setUniformValue(lineShader->model(), modelMatrix); + lineShader->setUniformValue(lineShader->nModel(), + itModelMatrix.inverted().transposed()); + lineShader->setUniformValue(lineShader->MVP(), MVPMatrix); + +#if !defined(QT_OPENGL_ES_2) + if (m_cachedShadowQuality > QDataVis::ShadowQualityNone) { + // Set shadow shader bindings + lineShader->setUniformValue(lineShader->shadowQ(), m_shadowQualityToShader); + lineShader->setUniformValue(lineShader->depth(), depthMVPMatrix); + lineShader->setUniformValue(lineShader->lightS(), + m_cachedTheme.m_lightStrength / 10.0f); + + // Draw the object + m_drawer->drawObject(lineShader, m_gridLineObj, 0, m_depthTexture); + } else +#endif + { + // Set shadowless shader bindings + lineShader->setUniformValue(lineShader->lightS(), + m_cachedTheme.m_lightStrength); + + // Draw the object + m_drawer->drawObject(lineShader, m_gridLineObj); + } + linePos -= lineStep; } } - // Floor lines: columns (= X) + // Columns (= X) if (m_axisCacheX.segmentCount() > 0) { + // Floor lines #ifndef USE_UNIFORM_SCALING GLfloat lineStep = aspectRatio * m_axisCacheX.subSegmentStep(); GLfloat linePos = aspectRatio * m_axisCacheX.min(); @@ -867,15 +829,10 @@ void Scatter3DRenderer::drawScene(CameraHelper *camera, QMatrix4x4 depthMVPMatrix; QMatrix4x4 itModelMatrix; - if (m_yFlipped) { - modelMatrix.translate(linePos / m_scaleFactor, - backgroundMargin, - zComp); - } else { - modelMatrix.translate(linePos / m_scaleFactor, - -backgroundMargin, - zComp); - } + if (m_yFlipped) + modelMatrix.translate(linePos / m_scaleFactor, backgroundMargin, zComp); + else + modelMatrix.translate(linePos / m_scaleFactor, -backgroundMargin, zComp); #ifndef USE_UNIFORM_SCALING // Use this if we want to use autoscaling for x and z modelMatrix.scale( QVector3D( @@ -900,58 +857,111 @@ void Scatter3DRenderer::drawScene(CameraHelper *camera, depthMVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; // Set the rest of the shader bindings - m_dotShader->setUniformValue(m_dotShader->model(), modelMatrix); - m_dotShader->setUniformValue(m_dotShader->nModel(), - itModelMatrix.inverted().transposed()); - m_dotShader->setUniformValue(m_dotShader->MVP(), MVPMatrix); + lineShader->setUniformValue(lineShader->model(), modelMatrix); + lineShader->setUniformValue(lineShader->nModel(), + itModelMatrix.inverted().transposed()); + lineShader->setUniformValue(lineShader->MVP(), MVPMatrix); #if !defined(QT_OPENGL_ES_2) - if (m_cachedShadowQuality > QDataVis::ShadowNone) { + if (m_cachedShadowQuality > QDataVis::ShadowQualityNone) { // Set shadow shader bindings - m_dotShader->setUniformValue(m_dotShader->shadowQ(), m_shadowQualityToShader); - m_dotShader->setUniformValue(m_dotShader->depth(), depthMVPMatrix); - m_dotShader->setUniformValue(m_dotShader->lightS(), - m_cachedTheme.m_lightStrength / 10.0f); + lineShader->setUniformValue(lineShader->shadowQ(), m_shadowQualityToShader); + lineShader->setUniformValue(lineShader->depth(), depthMVPMatrix); + lineShader->setUniformValue(lineShader->lightS(), + m_cachedTheme.m_lightStrength / 10.0f); // Draw the object - m_drawer->drawObject(m_dotShader, m_gridLineObj, 0, m_depthTexture); + m_drawer->drawObject(lineShader, m_gridLineObj, 0, m_depthTexture); } else #endif { // Set shadowless shader bindings - m_dotShader->setUniformValue(m_dotShader->lightS(), m_cachedTheme.m_lightStrength); + lineShader->setUniformValue(lineShader->lightS(), m_cachedTheme.m_lightStrength); // Draw the object - m_drawer->drawObject(m_dotShader, m_gridLineObj); + m_drawer->drawObject(lineShader, m_gridLineObj); + } + linePos += lineStep; + } + + // Back wall lines +#ifndef USE_UNIFORM_SCALING + GLfloat lineZTrans = (aspectRatio * backgroundMargin * m_areaSize.height()) + / m_scaleFactor; + linePos = aspectRatio * m_axisCacheX.min(); +#else + GLfloat lineZTrans = aspectRatio * backgroundMargin; + linePos = -aspectRatio * m_scaleFactor; +#endif + if (!m_zFlipped) + lineZTrans = -lineZTrans; + + for (int segment = 0; segment <= lastSegment; segment++) { + QMatrix4x4 modelMatrix; + QMatrix4x4 MVPMatrix; + QMatrix4x4 depthMVPMatrix; + QMatrix4x4 itModelMatrix; + + modelMatrix.translate(linePos / m_scaleFactor, 0.0f, lineZTrans + zComp); + modelMatrix.scale(QVector3D(gridLineWidth, backgroundMargin, gridLineWidth)); + itModelMatrix.scale(QVector3D(gridLineWidth, backgroundMargin, gridLineWidth)); + + MVPMatrix = projectionMatrix * viewMatrix * modelMatrix; + depthMVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; + + // Set the rest of the shader bindings + lineShader->setUniformValue(lineShader->model(), modelMatrix); + lineShader->setUniformValue(lineShader->nModel(), + itModelMatrix.inverted().transposed()); + lineShader->setUniformValue(lineShader->MVP(), MVPMatrix); + +#if !defined(QT_OPENGL_ES_2) + if (m_cachedShadowQuality > QDataVis::ShadowQualityNone) { + // Set shadow shader bindings + lineShader->setUniformValue(lineShader->shadowQ(), m_shadowQualityToShader); + lineShader->setUniformValue(lineShader->depth(), depthMVPMatrix); + lineShader->setUniformValue(lineShader->lightS(), + m_cachedTheme.m_lightStrength / 10.0f); + + // Draw the object + m_drawer->drawObject(lineShader, m_gridLineObj, 0, m_depthTexture); + } else +#endif + { + // Set shadowless shader bindings + lineShader->setUniformValue(lineShader->lightS(), + m_cachedTheme.m_lightStrength); + + // Draw the object + m_drawer->drawObject(lineShader, m_gridLineObj); } linePos += lineStep; } } - // Wall lines: back wall + // Horizontal wall lines if (m_axisCacheY.segmentCount() > 0) { + // Back wall GLfloat lineStep = m_axisCacheY.subSegmentStep(); GLfloat linePos = m_axisCacheY.min(); int lastSegment = m_axisCacheY.subSegmentCount() * m_axisCacheY.segmentCount(); - for (int segment = 0; segment <= lastSegment; segment++) { #ifndef USE_UNIFORM_SCALING // Use this if we want to use autoscaling for x and z - GLfloat lineZTrans = (aspectRatio * backgroundMargin * m_areaSize.height()) - / m_scaleFactor; + GLfloat lineZTrans = (aspectRatio * backgroundMargin * m_areaSize.height()) + / m_scaleFactor; #else // ..and this if we want uniform scaling based on largest dimension - GLfloat lineZTrans = aspectRatio * backgroundMargin; + GLfloat lineZTrans = aspectRatio * backgroundMargin; #endif + if (!m_zFlipped) + lineZTrans = -lineZTrans; + + for (int segment = 0; segment <= lastSegment; segment++) { QMatrix4x4 modelMatrix; QMatrix4x4 MVPMatrix; QMatrix4x4 depthMVPMatrix; QMatrix4x4 itModelMatrix; - if (!m_zFlipped) - lineZTrans = -lineZTrans; - - modelMatrix.translate(0.0f, - linePos / m_heightNormalizer, - lineZTrans + zComp); + modelMatrix.translate(0.0f, linePos / m_heightNormalizer, lineZTrans + zComp); #ifndef USE_UNIFORM_SCALING // Use this if we want to use autoscaling for x and z modelMatrix.scale( QVector3D( @@ -972,55 +982,52 @@ void Scatter3DRenderer::drawScene(CameraHelper *camera, depthMVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; // Set the rest of the shader bindings - m_dotShader->setUniformValue(m_dotShader->model(), modelMatrix); - m_dotShader->setUniformValue(m_dotShader->nModel(), - itModelMatrix.inverted().transposed()); - m_dotShader->setUniformValue(m_dotShader->MVP(), MVPMatrix); + lineShader->setUniformValue(lineShader->model(), modelMatrix); + lineShader->setUniformValue(lineShader->nModel(), + itModelMatrix.inverted().transposed()); + lineShader->setUniformValue(lineShader->MVP(), MVPMatrix); #if !defined(QT_OPENGL_ES_2) - if (m_cachedShadowQuality > QDataVis::ShadowNone) { + if (m_cachedShadowQuality > QDataVis::ShadowQualityNone) { // Set shadow shader bindings - m_dotShader->setUniformValue(m_dotShader->shadowQ(), m_shadowQualityToShader); - m_dotShader->setUniformValue(m_dotShader->depth(), depthMVPMatrix); - m_dotShader->setUniformValue(m_dotShader->lightS(), - m_cachedTheme.m_lightStrength / 10.0f); + lineShader->setUniformValue(lineShader->shadowQ(), m_shadowQualityToShader); + lineShader->setUniformValue(lineShader->depth(), depthMVPMatrix); + lineShader->setUniformValue(lineShader->lightS(), + m_cachedTheme.m_lightStrength / 10.0f); // Draw the object - m_drawer->drawObject(m_dotShader, m_gridLineObj, 0, m_depthTexture); + m_drawer->drawObject(lineShader, m_gridLineObj, 0, m_depthTexture); } else #endif { // Set shadowless shader bindings - m_dotShader->setUniformValue(m_dotShader->lightS(), m_cachedTheme.m_lightStrength); + lineShader->setUniformValue(lineShader->lightS(), m_cachedTheme.m_lightStrength); // Draw the object - m_drawer->drawObject(m_dotShader, m_gridLineObj); + m_drawer->drawObject(lineShader, m_gridLineObj); } linePos += lineStep; } - // Wall lines: side wall + // Side wall linePos = m_axisCacheY.min(); lastSegment = m_axisCacheY.subSegmentCount() * m_axisCacheY.segmentCount(); - - for (int segment = 0; segment <= lastSegment; segment++) { #ifndef USE_UNIFORM_SCALING // Use this if we want to use autoscaling for x and z - GLfloat lineXTrans = (aspectRatio * backgroundMargin * m_areaSize.width()) - / m_scaleFactor; + GLfloat lineXTrans = (aspectRatio * backgroundMargin * m_areaSize.width()) + / m_scaleFactor; #else // ..and this if we want uniform scaling based on largest dimension - GLfloat lineXTrans = aspectRatio * backgroundMargin; + GLfloat lineXTrans = aspectRatio * backgroundMargin; #endif + if (!m_xFlipped) + lineXTrans = -lineXTrans; + + for (int segment = 0; segment <= lastSegment; segment++) { QMatrix4x4 modelMatrix; QMatrix4x4 MVPMatrix; QMatrix4x4 depthMVPMatrix; QMatrix4x4 itModelMatrix; - if (!m_xFlipped) - lineXTrans = -lineXTrans; - - modelMatrix.translate(lineXTrans, - linePos / m_heightNormalizer, - zComp); + modelMatrix.translate(lineXTrans, linePos / m_heightNormalizer, zComp); #ifndef USE_UNIFORM_SCALING // Use this if we want to use autoscaling for x and z modelMatrix.scale( QVector3D( @@ -1042,91 +1049,37 @@ void Scatter3DRenderer::drawScene(CameraHelper *camera, depthMVPMatrix = depthProjectionMatrix * depthViewMatrix * modelMatrix; // Set the rest of the shader bindings - m_dotShader->setUniformValue(m_dotShader->model(), modelMatrix); - m_dotShader->setUniformValue(m_dotShader->nModel(), - itModelMatrix.inverted().transposed()); - m_dotShader->setUniformValue(m_dotShader->MVP(), MVPMatrix); + lineShader->setUniformValue(lineShader->model(), modelMatrix); + lineShader->setUniformValue(lineShader->nModel(), + itModelMatrix.inverted().transposed()); + lineShader->setUniformValue(lineShader->MVP(), MVPMatrix); #if !defined(QT_OPENGL_ES_2) - if (m_cachedShadowQuality > QDataVis::ShadowNone) { + if (m_cachedShadowQuality > QDataVis::ShadowQualityNone) { // Set shadow shader bindings - m_dotShader->setUniformValue(m_dotShader->shadowQ(), m_shadowQualityToShader); - m_dotShader->setUniformValue(m_dotShader->depth(), depthMVPMatrix); - m_dotShader->setUniformValue(m_dotShader->lightS(), - m_cachedTheme.m_lightStrength / 10.0f); + lineShader->setUniformValue(lineShader->shadowQ(), m_shadowQualityToShader); + lineShader->setUniformValue(lineShader->depth(), depthMVPMatrix); + lineShader->setUniformValue(lineShader->lightS(), + m_cachedTheme.m_lightStrength / 10.0f); // Draw the object - m_drawer->drawObject(m_dotShader, m_gridLineObj, 0, m_depthTexture); + m_drawer->drawObject(lineShader, m_gridLineObj, 0, m_depthTexture); } else #endif { // Set shadowless shader bindings - m_dotShader->setUniformValue(m_dotShader->lightS(), m_cachedTheme.m_lightStrength); + lineShader->setUniformValue(lineShader->lightS(), + m_cachedTheme.m_lightStrength); // Draw the object - m_drawer->drawObject(m_dotShader, m_gridLineObj); + m_drawer->drawObject(lineShader, m_gridLineObj); } linePos += lineStep; } } - // Release bar shader - m_dotShader->release(); - } - - // Handle selection clearing and selection label drawing - if (!barSelectionFound) { - // We have no ownership, don't delete. Just NULL the pointer. - m_selectedItem = NULL; - } else { - // Print value of selected bar - m_labelShader->bind(); - glDisable(GL_DEPTH_TEST); - glEnable(GL_TEXTURE_2D); - if (m_cachedLabelTransparency > QDataVis::TransparencyNone) { - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - } -#ifndef DISPLAY_FULL_DATA_ON_SELECTION - // Draw just the value string of the selected bar - if (m_previouslySelectedBar != m_selectedBar || m_updateLabels) { - m_drawer->generateLabelTexture(m_selectedBar); - m_previouslySelectedBar = m_selectedBar; - } - - m_drawer->drawLabel(*m_selectedBar, m_selectedBar->labelItem(), - viewMatrix, projectionMatrix, - QVector3D(0.0f, m_yAdjustment, zComp), - QVector3D(0.0f, 0.0f, 0.0f), m_selectedBar->height(), - m_cachedSelectionMode, m_labelShader, - m_labelObj, m_camera, true); -#else - // Draw the value string followed by row label and column label - LabelItem &labelItem = m_selectedItem->selectionLabel(); - if (m_previouslySelectedItem != m_selectedItem || m_updateLabels - || !labelItem.textureId()) { - QString labelText = m_selectedItem->label(); - // TODO More elaborate label? - m_drawer->generateLabelItem(labelItem, labelText); - m_previouslySelectedItem = m_selectedItem; - } - - m_drawer->drawLabel(*m_selectedItem, labelItem, viewMatrix, projectionMatrix, - QVector3D(0.0f, 0.0f, zComp), - QVector3D(0.0f, 0.0f, 0.0f), m_selectedItem->height(), - m_cachedSelectionMode, m_labelShader, - m_labelObj, camera, true, false, Drawer::LabelMid); -#endif - glDisable(GL_TEXTURE_2D); - if (m_cachedLabelTransparency > QDataVis::TransparencyNone) - glDisable(GL_BLEND); - glEnable(GL_DEPTH_TEST); - - // Release label shader - m_labelShader->release(); - - // Reset label update flag; they should have been updated when we get here - m_updateLabels = false; + // Release line shader + lineShader->release(); } // Draw axis labels @@ -1136,20 +1089,18 @@ void Scatter3DRenderer::drawScene(CameraHelper *camera, m_labelShader->bind(); glEnable(GL_TEXTURE_2D); - if (m_cachedLabelTransparency > QDataVis::TransparencyNone) { - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - } + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // Z Labels if (m_axisCacheZ.segmentCount() > 0) { #ifndef USE_UNIFORM_SCALING GLfloat posStep = aspectRatio * m_axisCacheZ.segmentStep(); - GLfloat labelPos = aspectRatio * m_axisCacheZ.min(); + GLfloat labelPos = -aspectRatio * m_axisCacheZ.min(); int lastSegment = m_axisCacheZ.segmentCount(); #else GLfloat posStep = aspectRatio * axisCacheMax->segmentStep(); - GLfloat labelPos = -aspectRatio * m_scaleFactor; + GLfloat labelPos = aspectRatio * m_scaleFactor; int lastSegment = axisCacheMax->segmentCount(); #endif int labelNbr = 0; @@ -1157,10 +1108,10 @@ void Scatter3DRenderer::drawScene(CameraHelper *camera, #ifndef USE_UNIFORM_SCALING // Use this if we want to use autoscaling for x and z if (m_axisCacheZ.labelItems().size() > labelNbr) { GLfloat labelXTrans = (aspectRatio * backgroundMargin * m_areaSize.width()) - / m_scaleFactor; + / m_scaleFactor + labelMargin; #else // ..and this if we want uniform scaling based on largest dimension if (axisCacheMax->labelItems().size() > labelNbr) { - GLfloat labelXTrans = aspectRatio * backgroundMargin; + GLfloat labelXTrans = aspectRatio * backgroundMargin + labelMargin; #endif GLfloat labelYTrans = -backgroundMargin; GLfloat rotLabelX = -90.0f; @@ -1195,11 +1146,11 @@ void Scatter3DRenderer::drawScene(CameraHelper *camera, QVector3D(0.0f, 0.0f, zComp), QVector3D(rotLabelX, rotLabelY, rotLabelZ), 0, m_cachedSelectionMode, - m_labelShader, m_labelObj, camera, true, true, Drawer::LabelMid, + m_labelShader, m_labelObj, m_cachedScene->activeCamera(), true, true, Drawer::LabelMid, alignment); } labelNbr++; - labelPos += posStep; + labelPos -= posStep; } } // X Labels @@ -1218,10 +1169,10 @@ void Scatter3DRenderer::drawScene(CameraHelper *camera, #ifndef USE_UNIFORM_SCALING // Use this if we want to use autoscaling for x and z if (m_axisCacheX.labelItems().size() > labelNbr) { GLfloat labelZTrans = (aspectRatio * backgroundMargin * m_areaSize.height()) - / m_scaleFactor; + / m_scaleFactor + labelMargin; #else // ..and this if we want uniform scaling based on largest dimension if (axisCacheMax->labelItems().size() > labelNbr) { - GLfloat labelZTrans = aspectRatio * backgroundMargin; + GLfloat labelZTrans = aspectRatio * backgroundMargin + labelMargin; #endif GLfloat labelYTrans = -backgroundMargin; GLfloat rotLabelX = -90.0f; @@ -1255,7 +1206,7 @@ void Scatter3DRenderer::drawScene(CameraHelper *camera, QVector3D(0.0f, 0.0f, zComp), QVector3D(rotLabelX, rotLabelY, rotLabelZ), 0, m_cachedSelectionMode, - m_labelShader, m_labelObj, camera, true, true, Drawer::LabelMid, + m_labelShader, m_labelObj, m_cachedScene->activeCamera(), true, true, Drawer::LabelMid, alignment); } labelNbr++; @@ -1271,13 +1222,15 @@ void Scatter3DRenderer::drawScene(CameraHelper *camera, if (m_axisCacheY.labelItems().size() > labelNbr) { #ifndef USE_UNIFORM_SCALING // Use this if we want to use autoscaling for x and z GLfloat labelXTrans = (aspectRatio * backgroundMargin * m_areaSize.width()) - / m_scaleFactor; + / m_scaleFactor; GLfloat labelZTrans = (aspectRatio * backgroundMargin * m_areaSize.height()) - / m_scaleFactor; + / m_scaleFactor; #else // ..and this if we want uniform scaling based on largest dimension GLfloat labelXTrans = aspectRatio * backgroundMargin; GLfloat labelZTrans = labelXTrans; #endif + GLfloat labelMarginXTrans = labelMargin; + GLfloat labelMarginZTrans = labelMargin; GLfloat labelYTrans = labelPos / m_heightNormalizer; GLfloat rotLabelX = 0.0f; GLfloat rotLabelY = -90.0f; @@ -1285,17 +1238,20 @@ void Scatter3DRenderer::drawScene(CameraHelper *camera, Qt::AlignmentFlag alignment = Qt::AlignLeft; if (!m_xFlipped) { labelXTrans = -labelXTrans; + labelMarginXTrans = -labelMargin; rotLabelY = 90.0f; } if (m_zFlipped) { labelZTrans = -labelZTrans; + labelMarginZTrans = -labelMargin; alignment = Qt::AlignRight; } const LabelItem &axisLabelItem = *m_axisCacheY.labelItems().at(labelNbr); // Back wall - QVector3D labelTrans = QVector3D(labelXTrans, labelYTrans, labelZTrans + zComp); + QVector3D labelTrans = QVector3D(labelXTrans, labelYTrans, + labelZTrans + labelMarginZTrans + zComp); // Draw the label here m_dummyRenderItem.setTranslation(labelTrans); @@ -1303,7 +1259,7 @@ void Scatter3DRenderer::drawScene(CameraHelper *camera, QVector3D(0.0f, 0.0f, zComp), QVector3D(rotLabelX, rotLabelY, rotLabelZ), 0, m_cachedSelectionMode, - m_labelShader, m_labelObj, camera, true, true, Drawer::LabelMid, + m_labelShader, m_labelObj, m_cachedScene->activeCamera(), true, true, Drawer::LabelMid, alignment); // Side wall @@ -1316,7 +1272,8 @@ void Scatter3DRenderer::drawScene(CameraHelper *camera, else rotLabelY = 0.0f; - labelTrans = QVector3D(-labelXTrans, labelYTrans, -labelZTrans + zComp); + labelTrans = QVector3D(-labelXTrans - labelMarginXTrans, labelYTrans, + -labelZTrans + zComp); // Draw the label here m_dummyRenderItem.setTranslation(labelTrans); @@ -1324,33 +1281,99 @@ void Scatter3DRenderer::drawScene(CameraHelper *camera, QVector3D(0.0f, 0.0f, zComp), QVector3D(rotLabelX, rotLabelY, rotLabelZ), 0, m_cachedSelectionMode, - m_labelShader, m_labelObj, camera, true, true, Drawer::LabelMid, + m_labelShader, m_labelObj, m_cachedScene->activeCamera(), true, true, Drawer::LabelMid, alignment); } labelNbr++; labelPos += posStep; } } + + // Handle selection clearing and selection label drawing + if (!dotSelectionFound) { + // We have no ownership, don't delete. Just NULL the pointer. + m_selectedItem = NULL; + } else { + glDisable(GL_DEPTH_TEST); + // Draw the selection label + LabelItem &labelItem = selectedItem->selectionLabelItem(); + if (m_selectedItem != selectedItem || m_updateLabels + || !labelItem.textureId()) { + QString labelText = selectedItem->selectionLabel(); + if (labelText.isNull()) { + static const QString xTitleTag(QStringLiteral("@xTitle")); + static const QString yTitleTag(QStringLiteral("@yTitle")); + static const QString zTitleTag(QStringLiteral("@zTitle")); + static const QString xLabelTag(QStringLiteral("@xLabel")); + static const QString yLabelTag(QStringLiteral("@yLabel")); + static const QString zLabelTag(QStringLiteral("@zLabel")); + + labelText = itemLabelFormat(); + + labelText.replace(xTitleTag, m_axisCacheX.title()); + labelText.replace(yTitleTag, m_axisCacheY.title()); + labelText.replace(zTitleTag, m_axisCacheZ.title()); + + if (labelText.contains(xLabelTag)) { + QString labelFormat = m_axisCacheX.labelFormat(); + if (labelFormat.isEmpty()) + labelFormat = Utils::defaultLabelFormat(); + QString valueLabelText = generateValueLabel(labelFormat, + selectedItem->position().x()); + labelText.replace(xLabelTag, valueLabelText); + } + if (labelText.contains(yLabelTag)) { + QString labelFormat = m_axisCacheY.labelFormat(); + if (labelFormat.isEmpty()) + labelFormat = Utils::defaultLabelFormat(); + QString valueLabelText = generateValueLabel(labelFormat, + selectedItem->position().y()); + labelText.replace(yLabelTag, valueLabelText); + } + if (labelText.contains(zLabelTag)) { + QString labelFormat = m_axisCacheZ.labelFormat(); + if (labelFormat.isEmpty()) + labelFormat = Utils::defaultLabelFormat(); + QString valueLabelText = generateValueLabel(labelFormat, + selectedItem->position().z()); + labelText.replace(zLabelTag, valueLabelText); + } + + selectedItem->setSelectionLabel(labelText); + } + m_drawer->generateLabelItem(labelItem, labelText); + m_selectedItem = selectedItem; + } + + m_drawer->drawLabel(*selectedItem, labelItem, viewMatrix, projectionMatrix, + QVector3D(0.0f, 0.0f, zComp), + QVector3D(0.0f, 0.0f, 0.0f), 0, + m_cachedSelectionMode, m_labelShader, + m_labelObj, m_cachedScene->activeCamera(), true, false, + Drawer::LabelMid); + + // Reset label update flag; they should have been updated when we get here + m_updateLabels = false; + glEnable(GL_DEPTH_TEST); + } + glDisable(GL_TEXTURE_2D); - if (m_cachedLabelTransparency > QDataVis::TransparencyNone) - glDisable(GL_BLEND); + glDisable(GL_BLEND); // Release label shader m_labelShader->release(); } -void Scatter3DRenderer::requestSelectionAtPoint(const QPoint &point) +void Scatter3DRenderer::updateSelectedItemIndex(int index) { - //qDebug() << __FUNCTION__; - QMutexLocker locker(&m_mutex); - m_selectionPointRequest.setX(point.x()); - m_selectionPointRequest.setY(point.y()); - m_isSelectionPointRequestActive = true; + if (index == Scatter3DController::noSelectionIndex()) + m_selection = selectionSkipColor; + else + m_selection = indexToSelectionColor(index); } void Scatter3DRenderer::handleResize() { - //qDebug() << __FUNCTION__; if (m_cachedBoundingRect.width() == 0 || m_cachedBoundingRect.height() == 0) return; @@ -1360,36 +1383,45 @@ void Scatter3DRenderer::handleResize() Abstract3DRenderer::handleResize(); } -void Scatter3DRenderer::updateMeshFileName(const QString &objFileName) -{ - Abstract3DRenderer::updateMeshFileName(objFileName); - loadBarMesh(); -} - void Scatter3DRenderer::updateBackgroundEnabled(bool enable) { if (enable != m_cachedIsBackgroundEnabled) { Abstract3DRenderer::updateBackgroundEnabled(enable); - loadBarMesh(); // Load changed bar type + loadMeshFile(); // Load changed dot type } } void Scatter3DRenderer::updateShadowQuality(QDataVis::ShadowQuality quality) { - qDebug() << __FUNCTION__ << quality; m_cachedShadowQuality = quality; switch (quality) { - case QDataVis::ShadowLow: + case QDataVis::ShadowQualityLow: m_shadowQualityToShader = 33.3f; + m_shadowQualityMultiplier = 1; break; - case QDataVis::ShadowMedium: + case QDataVis::ShadowQualityMedium: m_shadowQualityToShader = 100.0f; + m_shadowQualityMultiplier = 3; break; - case QDataVis::ShadowHigh: + case QDataVis::ShadowQualityHigh: m_shadowQualityToShader = 200.0f; + m_shadowQualityMultiplier = 5; + break; + case QDataVis::ShadowQualitySoftLow: + m_shadowQualityToShader = 5.0f; + m_shadowQualityMultiplier = 1; + break; + case QDataVis::ShadowQualitySoftMedium: + m_shadowQualityToShader = 10.0f; + m_shadowQualityMultiplier = 3; + break; + case QDataVis::ShadowQualitySoftHigh: + m_shadowQualityToShader = 15.0f; + m_shadowQualityMultiplier = 4; break; default: m_shadowQualityToShader = 0.0f; + m_shadowQualityMultiplier = 1; break; } @@ -1401,9 +1433,8 @@ void Scatter3DRenderer::updateShadowQuality(QDataVis::ShadowQuality quality) #endif } -void Scatter3DRenderer::loadBarMesh() +void Scatter3DRenderer::loadMeshFile() { - //qDebug() << __FUNCTION__; QString objectFileName = m_cachedObjFile; if (m_dotObj) delete m_dotObj; @@ -1413,7 +1444,6 @@ void Scatter3DRenderer::loadBarMesh() void Scatter3DRenderer::loadBackgroundMesh() { - //qDebug() << __FUNCTION__; if (m_backgroundObj) delete m_backgroundObj; m_backgroundObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/background")); @@ -1422,7 +1452,6 @@ void Scatter3DRenderer::loadBackgroundMesh() void Scatter3DRenderer::loadGridLineMesh() { - //qDebug() << __FUNCTION__; if (m_gridLineObj) delete m_gridLineObj; m_gridLineObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/bar")); @@ -1431,7 +1460,6 @@ void Scatter3DRenderer::loadGridLineMesh() void Scatter3DRenderer::loadLabelMesh() { - //qDebug() << __FUNCTION__; if (m_labelObj) delete m_labelObj; m_labelObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/label")); @@ -1440,12 +1468,11 @@ void Scatter3DRenderer::loadLabelMesh() void Scatter3DRenderer::updateTextures() { - //qDebug() << __FUNCTION__; // Drawer has changed; this flag needs to be checked when checking if we need to update labels m_updateLabels = true; } -void Scatter3DRenderer::updateAxisRange(QAbstractAxis::AxisOrientation orientation, +void Scatter3DRenderer::updateAxisRange(Q3DAbstractAxis::AxisOrientation orientation, qreal min, qreal max) { Abstract3DRenderer::updateAxisRange(orientation, min, max); @@ -1453,14 +1480,12 @@ void Scatter3DRenderer::updateAxisRange(QAbstractAxis::AxisOrientation orientati void Scatter3DRenderer::calculateTranslation(ScatterRenderItem &item) { - //qDebug() << __FUNCTION__; - // Origin should be in the center of scene, ie. both positive and negative values are drawn // above background // We need to normalize translations GLfloat xTrans = (aspectRatio * item.position().x()) / m_scaleFactor; - GLfloat zTrans = (aspectRatio * item.position().z()) / m_scaleFactor; + GLfloat zTrans = -(aspectRatio * item.position().z()) / m_scaleFactor; GLfloat yTrans = item.position().y() / m_heightNormalizer; item.setTranslation(QVector3D(xTrans, yTrans, zTrans + zComp)); //qDebug() << item.translation(); @@ -1468,61 +1493,20 @@ void Scatter3DRenderer::calculateTranslation(ScatterRenderItem &item) void Scatter3DRenderer::calculateSceneScalingFactors() { - m_heightNormalizer = (GLfloat)m_axisCacheY.max(); - // TODO: Get rid of m_areaSize and use m_axisCaches directly? - m_areaSize.setHeight(m_axisCacheZ.max()); - m_areaSize.setWidth(m_axisCacheX.max()); + m_heightNormalizer = (GLfloat)qMax(qAbs(m_axisCacheY.max()), qAbs(m_axisCacheY.min())); + m_areaSize.setHeight(qMax(qAbs(m_axisCacheZ.max()), qAbs(m_axisCacheZ.min()))); + m_areaSize.setWidth(qMax(qAbs(m_axisCacheX.max()), qAbs(m_axisCacheX.min()))); m_scaleFactor = qMax(m_areaSize.width(), m_areaSize.height()); //qDebug() << m_heightNormalizer << m_areaSize << m_scaleFactor << m_axisCacheY.max() << m_axisCacheX.max() << m_axisCacheZ.max(); } -Scatter3DController::SelectionType Scatter3DRenderer::isSelected(GLint bar, - const QVector3D &selection) -{ - //qDebug() << __FUNCTION__; - GLubyte barIdxRed = 0; - GLubyte barIdxGreen = 0; - GLubyte barIdxBlue = 0; - //static QVector3D prevSel = selection; // TODO: For debugging - Scatter3DController::SelectionType isSelectedType = Scatter3DController::SelectionNone; - - if (selection == selectionSkipColor) - return isSelectedType; // skip window - - if (bar <= 255) { - barIdxRed = bar; - } else if (bar <= 65535) { - barIdxGreen = bar / 256; - barIdxRed = bar % 256; - } else { - barIdxBlue = bar / 65535; - barIdxGreen = bar % 65535; - barIdxRed = bar % 256; - } - - QVector3D current = QVector3D(barIdxRed, barIdxGreen, barIdxBlue); - - // TODO: For debugging - //if (selection != prevSel) { - // qDebug() << selection.x() << selection .y() << selection.z(); - // prevSel = selection; - //} - - if (current == selection) - isSelectedType = Scatter3DController::SelectionItem; - - return isSelectedType; -} - QRect Scatter3DRenderer::mainViewPort() { - //qDebug() << __FUNCTION__; return m_mainViewPort; } void Scatter3DRenderer::initShaders(const QString &vertexShader, const QString &fragmentShader) { - //qDebug() << __FUNCTION__; if (m_dotShader) delete m_dotShader; m_dotShader = new ShaderHelper(this, vertexShader, fragmentShader); @@ -1531,7 +1515,6 @@ void Scatter3DRenderer::initShaders(const QString &vertexShader, const QString & void Scatter3DRenderer::initSelectionShader() { - //qDebug() << __FUNCTION__; if (m_selectionShader) delete m_selectionShader; m_selectionShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexSelection"), @@ -1541,7 +1524,6 @@ void Scatter3DRenderer::initSelectionShader() void Scatter3DRenderer::initSelectionBuffer() { - //qDebug() << __FUNCTION__; if (m_selectionTexture) m_textureHelper->deleteTexture(&m_selectionTexture); @@ -1553,7 +1535,6 @@ void Scatter3DRenderer::initSelectionBuffer() #if !defined(QT_OPENGL_ES_2) void Scatter3DRenderer::initDepthShader() { - //qDebug() << __FUNCTION__; if (m_depthShader) delete m_depthShader; m_depthShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexDepth"), @@ -1563,29 +1544,46 @@ void Scatter3DRenderer::initDepthShader() void Scatter3DRenderer::updateDepthBuffer() { - //qDebug() << __FUNCTION__; if (m_depthTexture) { m_textureHelper->deleteTexture(&m_depthTexture); m_depthTexture = 0; } - if (m_cachedShadowQuality > QDataVis::ShadowNone) { + if (m_cachedShadowQuality > QDataVis::ShadowQualityNone) { m_depthTexture = m_textureHelper->createDepthTexture(m_mainViewPort.size(), m_depthFrameBuffer, - m_cachedShadowQuality); + m_shadowQualityMultiplier); if (!m_depthTexture) { switch (m_cachedShadowQuality) { - case QDataVis::ShadowHigh: + case QDataVis::ShadowQualityHigh: qWarning("Creating high quality shadows failed. Changing to medium quality."); - (void)m_controller->setShadowQuality(QDataVis::ShadowMedium); + (void)m_controller->setShadowQuality(QDataVis::ShadowQualityMedium); + updateShadowQuality(QDataVis::ShadowQualityMedium); break; - case QDataVis::ShadowMedium: + case QDataVis::ShadowQualityMedium: qWarning("Creating medium quality shadows failed. Changing to low quality."); - (void)m_controller->setShadowQuality(QDataVis::ShadowLow); + (void)m_controller->setShadowQuality(QDataVis::ShadowQualityLow); + updateShadowQuality(QDataVis::ShadowQualityLow); break; - case QDataVis::ShadowLow: + case QDataVis::ShadowQualityLow: qWarning("Creating low quality shadows failed. Switching shadows off."); - (void)m_controller->setShadowQuality(QDataVis::ShadowNone); + (void)m_controller->setShadowQuality(QDataVis::ShadowQualityNone); + updateShadowQuality(QDataVis::ShadowQualityNone); + break; + case QDataVis::ShadowQualitySoftHigh: + qWarning("Creating soft high quality shadows failed. Changing to soft medium quality."); + (void)m_controller->setShadowQuality(QDataVis::ShadowQualitySoftMedium); + updateShadowQuality(QDataVis::ShadowQualitySoftMedium); + break; + case QDataVis::ShadowQualitySoftMedium: + qWarning("Creating soft medium quality shadows failed. Changing to soft low quality."); + (void)m_controller->setShadowQuality(QDataVis::ShadowQualitySoftLow); + updateShadowQuality(QDataVis::ShadowQualitySoftLow); + break; + case QDataVis::ShadowQualitySoftLow: + qWarning("Creating soft low quality shadows failed. Switching shadows off."); + (void)m_controller->setShadowQuality(QDataVis::ShadowQualityNone); + updateShadowQuality(QDataVis::ShadowQualityNone); break; default: // You'll never get here @@ -1599,7 +1597,6 @@ void Scatter3DRenderer::updateDepthBuffer() void Scatter3DRenderer::initBackgroundShaders(const QString &vertexShader, const QString &fragmentShader) { - //qDebug() << __FUNCTION__; if (m_backgroundShader) delete m_backgroundShader; m_backgroundShader = new ShaderHelper(this, vertexShader, fragmentShader); @@ -1608,11 +1605,19 @@ void Scatter3DRenderer::initBackgroundShaders(const QString &vertexShader, void Scatter3DRenderer::initLabelShaders(const QString &vertexShader, const QString &fragmentShader) { - //qDebug() << __FUNCTION__; if (m_labelShader) delete m_labelShader; m_labelShader = new ShaderHelper(this, vertexShader, fragmentShader); m_labelShader->initialize(); } -QT_DATAVIS3D_END_NAMESPACE +QVector3D Scatter3DRenderer::indexToSelectionColor(GLint index) +{ + GLubyte dotIdxRed = index & 0xff; + GLubyte dotIdxGreen = (index & 0xff00) >> 8; + GLubyte dotIdxBlue = (index & 0xff0000) >> 16; + + return QVector3D(dotIdxRed, dotIdxGreen, dotIdxBlue); +} + +QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavis3d/engine/scatter3drenderer_p.h b/src/datavisualization/engine/scatter3drenderer_p.h index 45054db4..f444f891 100644 --- a/src/datavis3d/engine/scatter3drenderer_p.h +++ b/src/datavisualization/engine/scatter3drenderer_p.h @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -20,7 +20,7 @@ // W A R N I N G // ------------- // -// This file is not part of the QtDataVis3D API. It exists purely as an +// 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. // @@ -29,36 +29,25 @@ #ifndef Q3DSCATTERRENDERER_P_H #define Q3DSCATTERRENDERER_P_H -#include <QtCore/QSize> -#include <QtCore/QObject> -#include <QtGui/QOpenGLFunctions> -#include <QtGui/QFont> -#include <QTime> -#include <QWindow> -#include <QMutex> - -#include "datavis3dglobal_p.h" +#include "datavisualizationglobal_p.h" #include "scatter3dcontroller_p.h" #include "abstract3drenderer_p.h" #include "qscatterdataproxy.h" #include "scatterrenderitem_p.h" -//#define DISPLAY_RENDER_SPEED - class QPoint; class QSizeF; class QOpenGLShaderProgram; -QT_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVISUALIZATION_BEGIN_NAMESPACE class ShaderHelper; class ObjectHelper; -class TextureHelper; class LabelItem; -class CameraHelper; +class Q3DScene; class QAbstractAxisPrivate; -class QT_DATAVIS3D_EXPORT Scatter3DRenderer : public Abstract3DRenderer +class QT_DATAVISUALIZATION_EXPORT Scatter3DRenderer : public Abstract3DRenderer { Q_OBJECT @@ -69,13 +58,8 @@ private: Scatter3DController *m_controller; - // Mutex for sharing resources between render and main threads. - // TODO: this mutex needs to go, too - QMutex m_mutex; - // Internal state ScatterRenderItem *m_selectedItem; // points to renderitem array - ScatterRenderItem *m_previouslySelectedItem; // points to renderitem array bool m_xFlipped; bool m_zFlipped; bool m_yFlipped; @@ -90,7 +74,6 @@ private: ObjectHelper *m_backgroundObj; ObjectHelper *m_gridLineObj; ObjectHelper *m_labelObj; - TextureHelper *m_textureHelper; GLuint m_bgrTexture; GLuint m_depthTexture; GLuint m_selectionTexture; @@ -98,60 +81,41 @@ private: GLuint m_selectionFrameBuffer; GLuint m_selectionDepthBuffer; GLfloat m_shadowQualityToShader; + GLint m_shadowQualityMultiplier; GLfloat m_heightNormalizer; GLfloat m_scaleFactor; QVector3D m_selection; + QVector3D m_previousSelection; QSizeF m_areaSize; GLfloat m_dotSizeScale; - QPoint m_selectionPointRequest; - bool m_isSelectionPointRequestActive; - bool m_hasHeightAdjustmentChanged; ScatterRenderItem m_dummyRenderItem; ScatterRenderItemArray m_renderItemArray; -#ifdef DISPLAY_RENDER_SPEED - bool m_isFirstFrame; - QTime m_lastFrameTime; - GLint m_numFrames; -#endif - public: explicit Scatter3DRenderer(Scatter3DController *controller); ~Scatter3DRenderer(); void updateDataModel(QScatterDataProxy *dataProxy); - void render(CameraHelper *camera, const GLuint defaultFboHandle); + void updateScene(Q3DScene *scene); + void render(GLuint defaultFboHandle); QRect mainViewPort(); -public slots: - void updateBackgroundEnabled(bool enable); - void updateMeshFileName(const QString &objFileName); - - // Overloaded from abstract renderer - virtual void updateAxisRange(QAbstractAxis::AxisOrientation orientation, qreal min, qreal max); - - // Requests that upon next render pass the column and row under the given point is inspected for selection. - // Only one request can be queued per render pass at this point. New request will override any pending requests. - // After inspection the selectionUpdated signal is emitted. - virtual void requestSelectionAtPoint(const QPoint &point); - -signals: - void selectionUpdated(QVector3D selection); +protected: + virtual void initializeOpenGL(); + virtual void loadMeshFile(); private: - virtual void initializeOpenGL(); virtual void initShaders(const QString &vertexShader, const QString &fragmentShader); virtual void updateShadowQuality(QDataVis::ShadowQuality quality); virtual void updateTextures(); - void drawScene(CameraHelper *camera, const GLuint defaultFboHandle); + void drawScene(GLuint defaultFboHandle); void handleResize(); - void loadBarMesh(); void loadBackgroundMesh(); void loadGridLineMesh(); void loadLabelMesh(); @@ -165,14 +129,27 @@ private: #endif void calculateTranslation(ScatterRenderItem &item); void calculateSceneScalingFactors(); - Scatter3DController::SelectionType isSelected(GLint bar, const QVector3D &selection); Q_DISABLE_COPY(Scatter3DRenderer) friend class ScatterRenderItem; -}; +public slots: + void updateBackgroundEnabled(bool enable); + + // Overloaded from abstract renderer + virtual void updateAxisRange(Q3DAbstractAxis::AxisOrientation orientation, qreal min, qreal max); + + void updateSelectedItemIndex(int index); + +signals: + void selectionUpdated(QVector3D selection); + void selectedItemIndexChanged(int index); + +private: + QVector3D indexToSelectionColor(GLint index); +}; -QT_DATAVIS3D_END_NAMESPACE +QT_DATAVISUALIZATION_END_NAMESPACE #endif diff --git a/src/datavisualization/engine/selectionpointer.cpp b/src/datavisualization/engine/selectionpointer.cpp new file mode 100644 index 00000000..6c3e0c8b --- /dev/null +++ b/src/datavisualization/engine/selectionpointer.cpp @@ -0,0 +1,275 @@ +/**************************************************************************** +** +** 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 "selectionpointer_p.h" +#include "surface3dcontroller_p.h" +#include "shaderhelper_p.h" +#include "objecthelper_p.h" +#include "texturehelper_p.h" +#include "q3dcamera.h" +#include "q3dcamera_p.h" +#include "drawer_p.h" +#include "utils_p.h" +#include "q3dlight.h" + +#include <QImage> +#include <QMatrix4x4> + +#include <QDebug> + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +const GLfloat sliceUnits = 2.5; + +SelectionPointer::SelectionPointer(Drawer *drawer) + : QObject(0), + m_labelShader(0), + m_pointShader(0), + m_labelObj(0), + m_pointObj(0), + m_textureHelper(0), + m_isInitialized(false), + m_cachedTheme(drawer->theme()), + m_labelStyle(QDataVis::LabelStyleFromTheme), + m_drawer(drawer), + m_cachedScene(0) +{ + initializeOpenGL(); + + QObject::connect(m_drawer, &Drawer::drawerChanged, + this, &SelectionPointer::handleDrawerChange); +} + +SelectionPointer::~SelectionPointer() +{ + delete m_labelShader; + delete m_pointShader; + delete m_labelObj; + delete m_pointObj; + delete m_textureHelper; +} + +void SelectionPointer::initializeOpenGL() +{ + if (m_isInitialized) + return; + + initializeOpenGLFunctions(); + + m_textureHelper = new TextureHelper(); + m_drawer->initializeOpenGL(); + + initShaders(); + + loadLabelMesh(); + loadPointMesh(); + + // Set initialized -flag + m_isInitialized = true; +} + +void SelectionPointer::updateScene(Q3DScene *scene) +{ + m_cachedScene = scene; +} + +void SelectionPointer::render(GLuint defaultFboHandle) +{ + Q_UNUSED(defaultFboHandle) + + glViewport(m_mainViewPort.x(), m_mainViewPort.y(), + m_mainViewPort.width(), m_mainViewPort.height()); + + Q3DCamera *camera = m_cachedScene->activeCamera(); + QSize textureSize = m_labelItem.size(); + + QMatrix4x4 itModelMatrix; + + // Get view matrix + QMatrix4x4 viewMatrix; + QMatrix4x4 projectionMatrix; + if (m_cachedIsSlicingActivated) { + GLfloat aspect = (GLfloat)m_mainViewPort.width() / (GLfloat)m_mainViewPort.height(); + viewMatrix.lookAt(QVector3D(0.0f, 0.0f, zComp + 1.0), + QVector3D(0.0f, 0.0f, zComp), + QVector3D(0.0f, 1.0f, 0.0f)); + projectionMatrix.ortho(-sliceUnits * aspect, sliceUnits * aspect, + -sliceUnits, sliceUnits, -1.0f, 14.0f); + } else { + viewMatrix = camera->viewMatrix(); + projectionMatrix.perspective(45.0f, (GLfloat)m_mainViewPort.width() + / (GLfloat)m_mainViewPort.height(), 0.1f, 100.0f); + } + + // Calculate scale factor to get uniform font size + GLfloat scaledFontSize = 0.05f + m_drawer->font().pointSizeF() / 500.0f; + GLfloat scaleFactor = scaledFontSize / (GLfloat)textureSize.height(); + + QMatrix4x4 modelMatrix; + QMatrix4x4 MVPMatrix; + + // Position the pointer ball + modelMatrix.translate(m_position + QVector3D(0.0f, 0.0f, zComp)); + + // Scale the point with fixed values (at this point) + modelMatrix.scale(QVector3D(0.05f, 0.05f, 0.05f)); + + MVPMatrix = projectionMatrix * viewMatrix * modelMatrix; + + // Enable texturing + glEnable(GL_TEXTURE_2D); + + QVector3D lightPos = m_cachedScene->activeLight()->position(); + + // + // Draw the point + // + m_pointShader->bind(); + m_pointShader->setUniformValue(m_pointShader->lightP(), lightPos); + m_pointShader->setUniformValue(m_pointShader->view(), viewMatrix); + m_pointShader->setUniformValue(m_pointShader->model(), modelMatrix); + m_pointShader->setUniformValue(m_pointShader->nModel(), itModelMatrix.inverted().transposed()); + m_pointShader->setUniformValue(m_pointShader->color(), + Utils::vectorFromColor(m_cachedTheme.m_highlightBarColor)); + m_pointShader->setUniformValue(m_pointShader->MVP(), MVPMatrix); + m_pointShader->setUniformValue(m_pointShader->ambientS(), m_cachedTheme.m_ambientStrength); + m_pointShader->setUniformValue(m_pointShader->lightS(), m_cachedTheme.m_lightStrength * 2.0f); + + m_drawer->drawObject(m_pointShader, m_pointObj); + + m_pointShader->release(); + + // + // Draw the label + // + QMatrix4x4 modelMatrixLabel; + + // Position label + QVector3D labelAlign(0.0f, 1.0f * scaledFontSize + 0.05f, 0.0f); + modelMatrixLabel.translate(m_position + labelAlign + QVector3D(0.0f, 0.0f, zComp)); + + // Position the label towards the camera + qreal camRotationsX = camera->xRotation(); + qreal camRotationsY = camera->yRotation(); + if (!m_cachedIsSlicingActivated) { + modelMatrixLabel.rotate(-camRotationsX, 0.0f, 1.0f, 0.0f); + modelMatrixLabel.rotate(-camRotationsY, 1.0f, 0.0f, 0.0f); + } + + // Scale label based on text size + modelMatrixLabel.scale(QVector3D((GLfloat)textureSize.width() * scaleFactor, + scaledFontSize, + 0.0f)); + + // Make label to be always on top + glDisable(GL_DEPTH_TEST); + + // Make label transparent + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + m_labelShader->bind(); + + // Set shader bindings + MVPMatrix = projectionMatrix * viewMatrix * modelMatrixLabel; + m_labelShader->setUniformValue(m_labelShader->MVP(), MVPMatrix); + + // Draw the object + m_drawer->drawObject(m_labelShader, m_labelObj, m_labelItem.textureId()); + + m_labelShader->release(); + + // Disable textures + glDisable(GL_TEXTURE_2D); + + // Disable transparency + glDisable(GL_BLEND); + + // Depth test back to normal + glEnable(GL_DEPTH_TEST); +} + +void SelectionPointer::setPosition(QVector3D position) +{ + m_position = position; +} + +void SelectionPointer::updateSliceData(bool sliceActivated, GLfloat autoScaleAdjustment) +{ + m_cachedIsSlicingActivated = sliceActivated; + m_autoScaleAdjustment = autoScaleAdjustment; +} + +void SelectionPointer::setLabel(QString label) +{ + m_label = label; + + m_drawer->generateLabelItem(m_labelItem, m_label); +} + +void SelectionPointer::handleDrawerChange() +{ + m_cachedTheme = m_drawer->theme(); + setLabel(m_label); +} + +void SelectionPointer::updateBoundingRect(QRect rect) +{ + m_mainViewPort = rect; +} + +void SelectionPointer::initShaders() +{ + // The shader for printing the text label + if (m_labelShader) + delete m_labelShader; + m_labelShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexLabel"), + QStringLiteral(":/shaders/fragmentLabel")); + m_labelShader->initialize(); + + // The shader for the small point ball + if (m_pointShader) + delete m_pointShader; +#if defined (Q_OS_ANDROID) + m_pointShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexES2"), + QStringLiteral(":/shaders/fragmentES2")); +#else + m_pointShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertex"), + QStringLiteral(":/shaders/fragment")); +#endif + m_pointShader->initialize(); + +} + +void SelectionPointer::loadLabelMesh() +{ + if (m_labelObj) + delete m_labelObj; + m_labelObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/label")); + m_labelObj->load(); +} + +void SelectionPointer::loadPointMesh() +{ + if (m_pointObj) + delete m_pointObj; + m_pointObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/sphereSmooth")); + m_pointObj->load(); +} + +QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavisualization/engine/selectionpointer_p.h b/src/datavisualization/engine/selectionpointer_p.h new file mode 100644 index 00000000..0e766035 --- /dev/null +++ b/src/datavisualization/engine/selectionpointer_p.h @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** 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 NOTIFICATIONLABEL_P_H +#define NOTIFICATIONLABEL_P_H + +#include <QtCore/QObject> +#include <QtGui/QOpenGLFunctions> +#include <QtGui/QFont> +#include <QWindow> +#include <QVector3D> + +#include "q3dscene.h" +#include "datavisualizationglobal_p.h" +#include "surface3dcontroller_p.h" + +class QOpenGLShaderProgram; + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +class ShaderHelper; +class ObjectHelper; +class SurfaceObject; +class TextureHelper; +class Theme; +class Drawer; +class Q3DCamera; + +class QT_DATAVISUALIZATION_EXPORT SelectionPointer : public QObject, protected QOpenGLFunctions +{ + Q_OBJECT + +public: + explicit SelectionPointer(Drawer *drawer); + ~SelectionPointer(); + + void initializeOpenGL(); + void render(GLuint defaultFboHandle = 0); + void setPosition(QVector3D position); + void setLabel(QString label); + void handleDrawerChange(); + void updateBoundingRect(QRect rect); + void updateScene(Q3DScene *scene); + void updateSliceData(bool sliceActivated, GLfloat autoScaleAdjustment); + +private: + void initShaders(); + void loadLabelMesh(); + void loadPointMesh(); + +private: + ShaderHelper *m_labelShader; + ShaderHelper *m_pointShader; + ObjectHelper *m_labelObj; + ObjectHelper *m_pointObj; + TextureHelper *m_textureHelper; + bool m_isInitialized; + Theme m_cachedTheme; + QDataVis::LabelStyle m_labelStyle; + LabelItem m_labelItem; + Drawer *m_drawer; + QRect m_mainViewPort; + QVector3D m_position; + Q3DScene *m_cachedScene; + QString m_label; + bool m_cachedIsSlicingActivated; + GLfloat m_autoScaleAdjustment; +}; + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif // NOTIFICATIONLABEL_P_H diff --git a/src/datavis3d/engine/shaders/ambient.frag b/src/datavisualization/engine/shaders/ambient.frag index 88f850f3..88f850f3 100644 --- a/src/datavis3d/engine/shaders/ambient.frag +++ b/src/datavisualization/engine/shaders/ambient.frag diff --git a/src/datavis3d/engine/shaders/colorOnY.frag b/src/datavisualization/engine/shaders/colorOnY.frag index ee57e8e5..80e54a61 100644 --- a/src/datavis3d/engine/shaders/colorOnY.frag +++ b/src/datavisualization/engine/shaders/colorOnY.frag @@ -12,7 +12,8 @@ varying highp vec3 lightDirection_cmr; varying highp vec2 coords_mdl; void main() { - highp vec3 materialDiffuseColor = vec3(coords_mdl.y * color_mdl.x, coords_mdl.y * color_mdl.y, coords_mdl.y * color_mdl.z); + highp float heightMod = (coords_mdl.y * 0.3) + 0.7; // Add 30% black to the bottom + highp vec3 materialDiffuseColor = heightMod * color_mdl; highp vec3 materialAmbientColor = vec3(ambientStrength, ambientStrength, ambientStrength) * materialDiffuseColor; highp vec3 materialSpecularColor = vec3(1.0, 1.0, 1.0); @@ -27,7 +28,9 @@ void main() { gl_FragColor.rgb = materialAmbientColor + - materialDiffuseColor * lightStrength * (cosTheta * cosTheta) / (distance * distance) + - materialSpecularColor * lightStrength * pow(cosAlpha, 5) / (distance * distance); + materialDiffuseColor * lightStrength * (cosTheta * cosTheta) / distance + + materialSpecularColor * lightStrength * pow(cosAlpha, 5) / distance; + gl_FragColor.rgb = clamp(gl_FragColor.rgb, 0.0, 1.0); + gl_FragColor.a = 1.0; } diff --git a/src/datavis3d/engine/shaders/colorOnY_ES2.frag b/src/datavisualization/engine/shaders/colorOnY_ES2.frag index 68c8ac39..aba52cfe 100644 --- a/src/datavis3d/engine/shaders/colorOnY_ES2.frag +++ b/src/datavisualization/engine/shaders/colorOnY_ES2.frag @@ -10,7 +10,8 @@ varying highp vec3 lightDirection_cmr; varying highp vec2 coords_mdl; void main() { - highp vec3 materialDiffuseColor = vec3(coords_mdl.y * color_mdl.x, coords_mdl.y * color_mdl.y, coords_mdl.y * color_mdl.z); + highp float heightMod = (coords_mdl.y * 0.3) + 0.7; // Add 30% black to the bottom + highp vec3 materialDiffuseColor = heightMod * color_mdl; highp vec3 materialAmbientColor = vec3(ambientStrength, ambientStrength, ambientStrength) * materialDiffuseColor; highp vec3 materialSpecularColor = vec3(1.0, 1.0, 1.0); @@ -29,8 +30,8 @@ void main() { gl_FragColor.rgb = materialAmbientColor + - materialDiffuseColor * lightStrength * (cosTheta * cosTheta) / (distance * distance) + - materialSpecularColor * lightStrength * (cosAlpha * cosAlpha * cosAlpha * cosAlpha * cosAlpha) / (distance * distance); + materialDiffuseColor * lightStrength * (cosTheta * cosTheta) / distance + + materialSpecularColor * lightStrength * (cosAlpha * cosAlpha * cosAlpha * cosAlpha * cosAlpha) / distance; gl_FragColor.a = 1.0; } diff --git a/src/datavis3d/engine/shaders/default.frag b/src/datavisualization/engine/shaders/default.frag index 5bf9c654..fba1ce4a 100644 --- a/src/datavis3d/engine/shaders/default.frag +++ b/src/datavisualization/engine/shaders/default.frag @@ -30,7 +30,7 @@ void main() { gl_FragColor.rgb = materialAmbientColor + materialDiffuseColor * lightStrength * pow(cosTheta, 2) / distance + - materialSpecularColor * lightStrength * pow(cosAlpha, 10) / distance; + materialSpecularColor * lightStrength * pow(cosAlpha, 5) / distance; gl_FragColor.a = 1.0; } diff --git a/src/datavis3d/engine/shaders/default.vert b/src/datavisualization/engine/shaders/default.vert index 14f77773..14f77773 100644 --- a/src/datavis3d/engine/shaders/default.vert +++ b/src/datavisualization/engine/shaders/default.vert diff --git a/src/datavis3d/engine/shaders/default_ES2.frag b/src/datavisualization/engine/shaders/default_ES2.frag index a70ed241..7d6214b2 100644 --- a/src/datavis3d/engine/shaders/default_ES2.frag +++ b/src/datavisualization/engine/shaders/default_ES2.frag @@ -32,7 +32,7 @@ void main() { gl_FragColor.rgb = materialAmbientColor + materialDiffuseColor * lightStrength * (cosTheta * cosTheta) / distance + - materialSpecularColor * lightStrength * (cosAlpha * cosAlpha * cosAlpha * cosAlpha * cosAlpha * cosAlpha * cosAlpha * cosAlpha * cosAlpha * cosAlpha) / distance; + materialSpecularColor * lightStrength * (cosAlpha * cosAlpha * cosAlpha * cosAlpha * cosAlpha) / distance; gl_FragColor.a = 1.0; } diff --git a/src/datavis3d/engine/shaders/default_ES2.vert b/src/datavisualization/engine/shaders/default_ES2.vert index efb40862..efb40862 100644 --- a/src/datavis3d/engine/shaders/default_ES2.vert +++ b/src/datavisualization/engine/shaders/default_ES2.vert diff --git a/src/datavis3d/engine/shaders/depth.frag b/src/datavisualization/engine/shaders/depth.frag index 5cfd4b10..5cfd4b10 100644 --- a/src/datavis3d/engine/shaders/depth.frag +++ b/src/datavisualization/engine/shaders/depth.frag diff --git a/src/datavis3d/engine/shaders/depth.vert b/src/datavisualization/engine/shaders/depth.vert index 9fe5a193..9fe5a193 100644 --- a/src/datavis3d/engine/shaders/depth.vert +++ b/src/datavisualization/engine/shaders/depth.vert diff --git a/src/datavis3d/engine/shaders/label.frag b/src/datavisualization/engine/shaders/label.frag index 86021410..86021410 100644 --- a/src/datavis3d/engine/shaders/label.frag +++ b/src/datavisualization/engine/shaders/label.frag diff --git a/src/datavis3d/engine/shaders/label.vert b/src/datavisualization/engine/shaders/label.vert index b4debe53..b4debe53 100644 --- a/src/datavis3d/engine/shaders/label.vert +++ b/src/datavisualization/engine/shaders/label.vert diff --git a/src/datavis3d/engine/shaders/selection.frag b/src/datavisualization/engine/shaders/selection.frag index 099c87a1..099c87a1 100644 --- a/src/datavis3d/engine/shaders/selection.frag +++ b/src/datavisualization/engine/shaders/selection.frag diff --git a/src/datavis3d/engine/shaders/selection.vert b/src/datavisualization/engine/shaders/selection.vert index 64d17e15..64d17e15 100644 --- a/src/datavis3d/engine/shaders/selection.vert +++ b/src/datavisualization/engine/shaders/selection.vert diff --git a/src/datavis3d/engine/shaders/shadow.frag b/src/datavisualization/engine/shaders/shadow.frag index 919cedee..5309b5bb 100644 --- a/src/datavis3d/engine/shaders/shadow.frag +++ b/src/datavisualization/engine/shaders/shadow.frag @@ -13,22 +13,22 @@ varying highp vec3 normal_cmr; varying highp vec3 eyeDirection_cmr; varying highp vec3 lightDirection_cmr; -const highp vec2 poissonDisk[16] = vec2[](vec2(-0.94201624, -0.39906216), - vec2(0.94558609, -0.76890725), - vec2(-0.094184101, -0.92938870), - vec2(0.34495938, 0.29387760), - vec2(-0.91588581, 0.45771432), - vec2(-0.81544232, -0.87912464), - vec2(-0.38277543, 0.27676845), - vec2(0.97484398, 0.75648379), - vec2(0.44323325, -0.97511554), - vec2(0.53742981, -0.47373420), - vec2(-0.26496911, -0.41893023), - vec2(0.79197514, 0.19090188), - vec2(-0.24188840, 0.99706507), - vec2(-0.81409955, 0.91437590), - vec2(0.19984126, 0.78641367), - vec2(0.14383161, -0.14100790)); +highp vec2 poissonDisk[16] = vec2[16](vec2(-0.94201624, -0.39906216), + vec2(0.94558609, -0.76890725), + vec2(-0.094184101, -0.92938870), + vec2(0.34495938, 0.29387760), + vec2(-0.91588581, 0.45771432), + vec2(-0.81544232, -0.87912464), + vec2(-0.38277543, 0.27676845), + vec2(0.97484398, 0.75648379), + vec2(0.44323325, -0.97511554), + vec2(0.53742981, -0.47373420), + vec2(-0.26496911, -0.41893023), + vec2(0.79197514, 0.19090188), + vec2(-0.24188840, 0.99706507), + vec2(-0.81409955, 0.91437590), + vec2(0.19984126, 0.78641367), + vec2(0.14383161, -0.14100790)); /*float random(vec3 seed, int i) { vec4 seed4 = vec4(seed, i); @@ -58,7 +58,7 @@ void main() { // direct method; needs large shadow texture to look good //highp float visibility = 0.75 * shadow2DProj(shadowMap, shadCoords).r + 0.25; // poisson disk sampling; smoothes edges - highp float visibility = 0.4; + highp float visibility = 0.6; for (int i = 0; i < 15; i++) { vec4 shadCoordsPD = shadCoords; shadCoordsPD.x += cos(poissonDisk[i].x) / shadowQuality; diff --git a/src/datavis3d/engine/shaders/shadow.vert b/src/datavisualization/engine/shaders/shadow.vert index e29a8a30..e29a8a30 100644 --- a/src/datavis3d/engine/shaders/shadow.vert +++ b/src/datavisualization/engine/shaders/shadow.vert diff --git a/src/datavis3d/engine/shaders/shadowNoTex.frag b/src/datavisualization/engine/shaders/shadowNoTex.frag index 50f900ba..0252ba49 100644 --- a/src/datavis3d/engine/shaders/shadowNoTex.frag +++ b/src/datavisualization/engine/shaders/shadowNoTex.frag @@ -7,45 +7,44 @@ uniform highp vec3 color_mdl; uniform highp sampler2DShadow shadowMap; varying highp vec4 shadowCoord; -varying highp vec2 UV; varying highp vec3 position_wrld; varying highp vec3 normal_cmr; varying highp vec3 eyeDirection_cmr; varying highp vec3 lightDirection_cmr; -const highp vec2 poissonDisk[16] = vec2[](vec2(-0.94201624, -0.39906216), - vec2(0.94558609, -0.76890725), - vec2(-0.094184101, -0.92938870), - vec2(0.34495938, 0.29387760), - vec2(-0.91588581, 0.45771432), - vec2(-0.81544232, -0.87912464), - vec2(-0.38277543, 0.27676845), - vec2(0.97484398, 0.75648379), - vec2(0.44323325, -0.97511554), - vec2(0.53742981, -0.47373420), - vec2(-0.26496911, -0.41893023), - vec2(0.79197514, 0.19090188), - vec2(-0.24188840, 0.99706507), - vec2(-0.81409955, 0.91437590), - vec2(0.19984126, 0.78641367), - vec2(0.14383161, -0.14100790)); +highp vec2 poissonDisk[16] = vec2[16](vec2(-0.94201624, -0.39906216), + vec2(0.94558609, -0.76890725), + vec2(-0.094184101, -0.92938870), + vec2(0.34495938, 0.29387760), + vec2(-0.91588581, 0.45771432), + vec2(-0.81544232, -0.87912464), + vec2(-0.38277543, 0.27676845), + vec2(0.97484398, 0.75648379), + vec2(0.44323325, -0.97511554), + vec2(0.53742981, -0.47373420), + vec2(-0.26496911, -0.41893023), + vec2(0.79197514, 0.19090188), + vec2(-0.24188840, 0.99706507), + vec2(-0.81409955, 0.91437590), + vec2(0.19984126, 0.78641367), + vec2(0.14383161, -0.14100790)); -/*const highp vec2 poissonDisk[16] = vec2[](vec2(-0.25, -0.25), - vec2(0.25, -0.25), - vec2(-0.25, 0.25), - vec2(0.25, 0.25), - vec2(-0.5, -0.5), - vec2(0.5, -0.5), - vec2(-0.5, 0.5), - vec2(0.5, 0.5), - vec2(-0.75, -0.75), - vec2(0.75, -0.75), - vec2(-0.75, 0.75), - vec2(0.75, 0.75), - vec2(-1.0, -1.0), - vec2(1.0, -1.0), - vec2(-1.0, 1.0), - vec2(1.0, 1.0));*/ +/*highp vec2 poissonDisk[16] = vec2[16](vec2(-0.25, -0.25), + vec2(0.25, -0.25), + vec2(-0.25, 0.25), + vec2(0.25, 0.25), + vec2(-0.5, -0.5), + vec2(0.5, -0.5), + vec2(-0.5, 0.5), + vec2(0.5, 0.5), + vec2(-0.75, -0.75), + vec2(0.75, -0.75), + vec2(-0.75, 0.75), + vec2(0.75, 0.75), + vec2(-1.0, -1.0), + vec2(1.0, -1.0), + vec2(-1.0, 1.0), + vec2(1.0, 1.0));*/ /*float random(vec3 seed, int i) { vec4 seed4 = vec4(seed, i); @@ -75,7 +74,7 @@ void main() { // direct method; needs large shadow texture to look good //highp float visibility = 0.75 * shadow2DProj(shadowMap, shadCoords).r + 0.25; // poisson disk sampling; smoothes edges - highp float visibility = 0.4; + highp float visibility = 0.6; for (int i = 0; i < 15; i++) { vec4 shadCoordsPD = shadCoords; shadCoordsPD.x += cos(poissonDisk[i].x) / shadowQuality; diff --git a/src/datavis3d/engine/shaders/shadowNoTexColorOnY.frag b/src/datavisualization/engine/shaders/shadowNoTexColorOnY.frag index 75f0e6d3..68ba2368 100644 --- a/src/datavis3d/engine/shaders/shadowNoTexColorOnY.frag +++ b/src/datavisualization/engine/shaders/shadowNoTexColorOnY.frag @@ -13,22 +13,22 @@ varying highp vec3 eyeDirection_cmr; varying highp vec3 lightDirection_cmr; varying highp vec2 coords_mdl; -const highp vec2 poissonDisk[16] = vec2[](vec2(-0.94201624, -0.39906216), - vec2(0.94558609, -0.76890725), - vec2(-0.094184101, -0.92938870), - vec2(0.34495938, 0.29387760), - vec2(-0.91588581, 0.45771432), - vec2(-0.81544232, -0.87912464), - vec2(-0.38277543, 0.27676845), - vec2(0.97484398, 0.75648379), - vec2(0.44323325, -0.97511554), - vec2(0.53742981, -0.47373420), - vec2(-0.26496911, -0.41893023), - vec2(0.79197514, 0.19090188), - vec2(-0.24188840, 0.99706507), - vec2(-0.81409955, 0.91437590), - vec2(0.19984126, 0.78641367), - vec2(0.14383161, -0.14100790)); +highp vec2 poissonDisk[16] = vec2[16](vec2(-0.94201624, -0.39906216), + vec2(0.94558609, -0.76890725), + vec2(-0.094184101, -0.92938870), + vec2(0.34495938, 0.29387760), + vec2(-0.91588581, 0.45771432), + vec2(-0.81544232, -0.87912464), + vec2(-0.38277543, 0.27676845), + vec2(0.97484398, 0.75648379), + vec2(0.44323325, -0.97511554), + vec2(0.53742981, -0.47373420), + vec2(-0.26496911, -0.41893023), + vec2(0.79197514, 0.19090188), + vec2(-0.24188840, 0.99706507), + vec2(-0.81409955, 0.91437590), + vec2(0.19984126, 0.78641367), + vec2(0.14383161, -0.14100790)); /*float random(vec3 seed, int i) { vec4 seed4 = vec4(seed, i); @@ -37,7 +37,8 @@ const highp vec2 poissonDisk[16] = vec2[](vec2(-0.94201624, -0.39906216), }*/ void main() { - highp vec3 materialDiffuseColor = vec3(coords_mdl.y * color_mdl.x, coords_mdl.y * color_mdl.y, coords_mdl.y * color_mdl.z); + highp float heightMod = (coords_mdl.y * 0.3) + 0.7; // Add 30% black to the bottom + highp vec3 materialDiffuseColor = heightMod * color_mdl; highp vec3 materialAmbientColor = vec3(ambientStrength, ambientStrength, ambientStrength) * materialDiffuseColor; highp vec3 materialSpecularColor = vec3(1.0, 1.0, 1.0); @@ -58,7 +59,7 @@ void main() { // direct method; needs large shadow texture to look good //highp float visibility = 0.75 * shadow2DProj(shadowMap, shadCoords).r + 0.25; // poisson disk sampling; smoothes edges - highp float visibility = 0.4; + highp float visibility = 0.6; for (int i = 0; i < 15; i++) { vec4 shadCoordsPD = shadCoords; shadCoordsPD.x += cos(poissonDisk[i].x) / shadowQuality; @@ -76,5 +77,6 @@ void main() { visibility * (materialAmbientColor + materialDiffuseColor * lightStrength * cosTheta + materialSpecularColor * lightStrength * pow(cosAlpha, 10)); + gl_FragColor.rgb = clamp(gl_FragColor.rgb, 0.0, 1.0); gl_FragColor.a = 1.0; } diff --git a/src/datavis3d/engine/shaders/surface.frag b/src/datavisualization/engine/shaders/surface.frag index 9fe7f45b..4b1357b1 100644 --- a/src/datavis3d/engine/shaders/surface.frag +++ b/src/datavisualization/engine/shaders/surface.frag @@ -1,6 +1,5 @@ #version 120 -varying highp vec2 UV; varying highp vec3 coords_mdl; varying highp vec3 position_wrld; varying highp vec3 normal_cmr; @@ -13,7 +12,7 @@ uniform highp float lightStrength; uniform highp float ambientStrength; void main() { - highp vec2 gradientUV = vec2(0.5, (coords_mdl.y + 1.0) / 2.0); + highp vec2 gradientUV = vec2(0.0, (coords_mdl.y + 1.001) / 2.0); // 1000 pixel texture, we need a margin for 1/1000 rounding error highp vec3 materialDiffuseColor = texture2D(textureSampler, gradientUV).xyz; highp vec3 materialAmbientColor = vec3(ambientStrength, ambientStrength, ambientStrength) * materialDiffuseColor; highp vec3 materialSpecularColor = vec3(1.0, 1.0, 1.0); @@ -28,12 +27,10 @@ void main() { highp vec3 R = reflect(-l, n); highp float cosAlpha = clamp(dot(E, R), 0.0, 1.0); -// gl_FragColor.rgb = materialDiffuseColor; gl_FragColor.rgb = materialAmbientColor + materialDiffuseColor * lightStrength * pow(cosTheta, 2) / distance + materialSpecularColor * lightStrength * pow(cosAlpha, 10) / distance; gl_FragColor.a = 1.0; -// gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); } diff --git a/src/datavis3d/engine/shaders/surface.vert b/src/datavisualization/engine/shaders/surface.vert index cbfb7569..28152abc 100644 --- a/src/datavis3d/engine/shaders/surface.vert +++ b/src/datavisualization/engine/shaders/surface.vert @@ -1,7 +1,4 @@ -#version 120 - attribute highp vec3 vertexPosition_mdl; -attribute highp vec2 vertexUV; attribute highp vec3 vertexNormal_mdl; uniform highp mat4 MVP; @@ -10,7 +7,6 @@ uniform highp mat4 M; uniform highp mat4 itM; uniform highp vec3 lightPosition_wrld; -varying highp vec2 UV; varying highp vec3 position_wrld; varying highp vec3 normal_cmr; varying highp vec3 eyeDirection_cmr; @@ -26,5 +22,4 @@ void main() { vec3 lightPosition_cmr = (V * vec4(lightPosition_wrld, 1.0)).xyz; lightDirection_cmr = lightPosition_cmr + eyeDirection_cmr; normal_cmr = (V * itM * vec4(vertexNormal_mdl, 0.0)).xyz; - UV = vertexUV; } diff --git a/src/datavis3d/engine/shaders/surfaceFlat.frag b/src/datavisualization/engine/shaders/surfaceFlat.frag index eb398582..a8a3dbb1 100644 --- a/src/datavis3d/engine/shaders/surfaceFlat.frag +++ b/src/datavisualization/engine/shaders/surfaceFlat.frag @@ -1,6 +1,5 @@ #version 150 -varying highp vec2 UV; varying highp vec3 coords_mdl; varying highp vec3 position_wrld; flat in highp vec3 normal_cmr; @@ -13,7 +12,7 @@ uniform highp float lightStrength; uniform highp float ambientStrength; void main() { - highp vec2 gradientUV = vec2(0.5, (coords_mdl.y + 1.0) / 2.0); + highp vec2 gradientUV = vec2(0.0, (coords_mdl.y + 1.001) / 2.0); // 1000 pixel texture, we need a margin for 1/1000 rounding error highp vec3 materialDiffuseColor = texture2D(textureSampler, gradientUV).xyz; highp vec3 materialAmbientColor = vec3(ambientStrength, ambientStrength, ambientStrength) * materialDiffuseColor; highp vec3 materialSpecularColor = vec3(1.0, 1.0, 1.0); @@ -28,7 +27,6 @@ void main() { highp vec3 R = reflect(-l, n); highp float cosAlpha = clamp(dot(E, R), 0.0, 1.0); -// gl_FragColor.rgb = materialDiffuseColor; gl_FragColor.rgb = materialAmbientColor + materialDiffuseColor * lightStrength * pow(cosTheta, 2) / distance + diff --git a/src/datavis3d/engine/shaders/surfaceFlat.vert b/src/datavisualization/engine/shaders/surfaceFlat.vert index 24c9b9a3..7e248d02 100644 --- a/src/datavis3d/engine/shaders/surfaceFlat.vert +++ b/src/datavisualization/engine/shaders/surfaceFlat.vert @@ -1,7 +1,6 @@ #version 150 attribute highp vec3 vertexPosition_mdl; -attribute highp vec2 vertexUV; attribute highp vec3 vertexNormal_mdl; uniform highp mat4 MVP; @@ -10,7 +9,6 @@ uniform highp mat4 M; uniform highp mat4 itM; uniform highp vec3 lightPosition_wrld; -varying highp vec2 UV; varying highp vec3 position_wrld; flat out highp vec3 normal_cmr; varying highp vec3 eyeDirection_cmr; @@ -26,5 +24,4 @@ void main() { vec3 lightPosition_cmr = (V * vec4(lightPosition_wrld, 1.0)).xyz; lightDirection_cmr = lightPosition_cmr + eyeDirection_cmr; normal_cmr = (V * itM * vec4(vertexNormal_mdl, 0.0)).xyz; - UV = vertexUV; } diff --git a/src/datavisualization/engine/shaders/surfaceGrid.frag b/src/datavisualization/engine/shaders/surfaceGrid.frag new file mode 100644 index 00000000..1658b316 --- /dev/null +++ b/src/datavisualization/engine/shaders/surfaceGrid.frag @@ -0,0 +1,6 @@ +uniform highp vec3 color_mdl; + +void main() { + gl_FragColor.rgb = color_mdl; +} + diff --git a/src/datavisualization/engine/shaders/surfaceGrid.vert b/src/datavisualization/engine/shaders/surfaceGrid.vert new file mode 100644 index 00000000..5582d633 --- /dev/null +++ b/src/datavisualization/engine/shaders/surfaceGrid.vert @@ -0,0 +1,6 @@ +attribute highp vec3 vertexPosition_mdl; +uniform highp mat4 MVP; + +void main() { + gl_Position = MVP * vec4(vertexPosition_mdl, 1.0); +} diff --git a/src/datavisualization/engine/shaders/surface_ES2.frag b/src/datavisualization/engine/shaders/surface_ES2.frag new file mode 100644 index 00000000..a9aec528 --- /dev/null +++ b/src/datavisualization/engine/shaders/surface_ES2.frag @@ -0,0 +1,39 @@ +varying highp vec2 UV; +varying highp vec3 coords_mdl; +varying highp vec3 position_wrld; +varying highp vec3 normal_cmr; +varying highp vec3 eyeDirection_cmr; +varying highp vec3 lightDirection_cmr; + +uniform sampler2D textureSampler; +uniform highp vec3 lightPosition_wrld; +uniform highp float lightStrength; +uniform highp float ambientStrength; + +void main() { + highp vec2 gradientUV = vec2(0.5, (coords_mdl.y + 1.0) / 2.0); + highp vec3 materialDiffuseColor = texture2D(textureSampler, gradientUV).xyz; + highp vec3 materialAmbientColor = vec3(ambientStrength, ambientStrength, ambientStrength) * materialDiffuseColor; + highp vec3 materialSpecularColor = vec3(1.0, 1.0, 1.0); + + highp float distance = length(lightPosition_wrld - position_wrld); + + highp vec3 n = normalize(normal_cmr); + highp vec3 l = normalize(lightDirection_cmr); + highp float cosTheta = dot(n, l); + if (cosTheta < 0.0) cosTheta = 0.0; + else if (cosTheta > 1.0) cosTheta = 1.0; + + highp vec3 E = normalize(eyeDirection_cmr); + highp vec3 R = reflect(-l, n); + highp float cosAlpha = dot(E, R); + if (cosAlpha < 0.0) cosAlpha = 0.0; + else if (cosAlpha > 1.0) cosAlpha = 1.0; + + gl_FragColor.rgb = + materialAmbientColor + + materialDiffuseColor * lightStrength * cosTheta * cosTheta / distance + + materialSpecularColor * lightStrength * cosAlpha * cosAlpha * cosAlpha * cosAlpha * cosAlpha * cosAlpha * cosAlpha * cosAlpha * cosAlpha * cosAlpha / distance; + gl_FragColor.a = 1.0; +} + diff --git a/src/datavis3d/engine/shaders/texture.frag b/src/datavisualization/engine/shaders/texture.frag index a6d7b2eb..a6d7b2eb 100644 --- a/src/datavis3d/engine/shaders/texture.frag +++ b/src/datavisualization/engine/shaders/texture.frag diff --git a/src/datavis3d/engine/shaders/texture.vert b/src/datavisualization/engine/shaders/texture.vert index 01f922e0..01f922e0 100644 --- a/src/datavis3d/engine/shaders/texture.vert +++ b/src/datavisualization/engine/shaders/texture.vert diff --git a/src/datavis3d/engine/shaders/texture_ES2.frag b/src/datavisualization/engine/shaders/texture_ES2.frag index 16161035..58097ba5 100644 --- a/src/datavis3d/engine/shaders/texture_ES2.frag +++ b/src/datavisualization/engine/shaders/texture_ES2.frag @@ -31,7 +31,7 @@ void main() { gl_FragColor.rgb = materialAmbientColor + materialDiffuseColor * lightStrength * (cosTheta * cosTheta) / distance + - materialSpecularColor * lightStrength * (cosAlpha * cosAlpha * cosAlpha * cosAlpha * cosAlpha * cosAlpha * cosAlpha * cosAlpha * cosAlpha * cosAlpha) / distance; + materialSpecularColor * lightStrength * (cosAlpha * cosAlpha * cosAlpha * cosAlpha * cosAlpha) / distance; gl_FragColor.a = texture2D(textureSampler, UV).a; } diff --git a/src/datavisualization/engine/surface3dcontroller.cpp b/src/datavisualization/engine/surface3dcontroller.cpp new file mode 100644 index 00000000..2272b731 --- /dev/null +++ b/src/datavisualization/engine/surface3dcontroller.cpp @@ -0,0 +1,233 @@ +/**************************************************************************** +** +** 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 "surface3dcontroller_p.h" +#include "surface3drenderer_p.h" +#include "camerahelper_p.h" +#include "q3dabstractaxis_p.h" +#include "q3dvalueaxis_p.h" +#include "q3dcategoryaxis.h" +#include "qsurfacedataproxy_p.h" + +#include <QMatrix4x4> + +#include <QDebug> + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +Surface3DController::Surface3DController(QRect rect) + : Abstract3DController(rect), + m_renderer(0), + m_isSmoothSurfaceEnabled(false), + m_isSurfaceGridEnabled(true) +{ + setActiveDataProxy(0); + + // Setting a null axis creates a new default axis according to orientation and graph type. + // Note: These cannot be set in Abstract3DController constructor, as they will call virtual + // functions implemented by subclasses. + setAxisX(0); + setAxisY(0); + setAxisZ(0); + + // Set the default from the theme + m_userDefinedGradient = theme().m_surfaceGradient; +} + +Surface3DController::~Surface3DController() +{ +} + +void Surface3DController::initializeOpenGL() +{ + // Initialization is called multiple times when Qt Quick components are used + if (isInitialized()) + return; + + m_renderer = new Surface3DRenderer(this); + setRenderer(m_renderer); + synchDataToRenderer(); + emitNeedRender(); +} + +void Surface3DController::synchDataToRenderer() +{ + Abstract3DController::synchDataToRenderer(); + + if (!isInitialized()) + return; + + // Notify changes to renderer + if (m_changeTracker.gradientColorChanged) { + m_renderer->updateSurfaceGradient(m_userDefinedGradient); + m_changeTracker.gradientColorChanged = false; + } + + if (m_changeTracker.smoothStatusChanged) { + m_isSmoothSurfaceEnabled = m_renderer->updateSmoothStatus(m_isSmoothSurfaceEnabled); + m_changeTracker.smoothStatusChanged = false; + } + + if (m_changeTracker.surfaceGridChanged) { + m_renderer->updateSurfaceGridStatus(m_isSurfaceGridEnabled); + m_changeTracker.surfaceGridChanged = false; + } + + if (m_isDataDirty) { + m_renderer->updateDataModel(static_cast<QSurfaceDataProxy *>(m_data)); + m_isDataDirty = false; + } +} + +void Surface3DController::handleAxisAutoAdjustRangeChangedInOrientation(Q3DAbstractAxis::AxisOrientation orientation, bool autoAdjust) +{ + Q_UNUSED(orientation) + Q_UNUSED(autoAdjust) + + adjustValueAxisRange(); +} + +void Surface3DController::handleAxisRangeChangedBySender(QObject *sender) +{ + scene()->setSlicingActive(false); + Abstract3DController::handleAxisRangeChangedBySender(sender); +} + +void Surface3DController::setSmoothSurface(bool enable) +{ + m_isSmoothSurfaceEnabled = enable; + m_changeTracker.smoothStatusChanged = true; + emitNeedRender(); +} + +bool Surface3DController::smoothSurface() +{ + return m_isSmoothSurfaceEnabled; +} + +void Surface3DController::setSurfaceGrid(bool enable) +{ + m_isSurfaceGridEnabled = enable; + m_changeTracker.surfaceGridChanged = true; + emitNeedRender(); +} + +bool Surface3DController::surfaceGrid() +{ + return m_isSurfaceGridEnabled; +} + +void Surface3DController::setGradient(const QLinearGradient &gradient) +{ + m_userDefinedGradient = gradient; + m_userDefinedGradient.setStart(1, 1000); + m_userDefinedGradient.setFinalStop(0, 0); + m_changeTracker.gradientColorChanged = true; + emitNeedRender(); +} + +QLinearGradient Surface3DController::gradient() const +{ + return m_userDefinedGradient; +} + +void Surface3DController::setGradientColorAt(qreal pos, const QColor &color) +{ + m_userDefinedGradient.setColorAt(pos, color); + m_changeTracker.gradientColorChanged = true; + emitNeedRender(); +} + +void Surface3DController::setSelectionMode(QDataVis::SelectionMode mode) +{ + if (!(mode == QDataVis::SelectionModeNone || mode == QDataVis::SelectionModeItem + || mode == QDataVis::SelectionModeSliceRow + || mode == QDataVis::SelectionModeSliceColumn)) { + qWarning("Unsupported selection mode."); + return; + } + // Disable zoom if selection mode changes + setSlicingActive(false); + Abstract3DController::setSelectionMode(mode); +} + + +void Surface3DController::setActiveDataProxy(QAbstractDataProxy *proxy) +{ + // Setting null proxy indicates default proxy + if (!proxy) { + proxy = new QSurfaceDataProxy; + proxy->d_ptr->setDefaultProxy(true); + } + + Q_ASSERT(proxy->type() == QAbstractDataProxy::DataTypeSurface); + + Abstract3DController::setActiveDataProxy(proxy); + + QSurfaceDataProxy *surfaceDataProxy = static_cast<QSurfaceDataProxy *>(m_data); + + QObject::connect(surfaceDataProxy, &QSurfaceDataProxy::arrayReset, + this, &Surface3DController::handleArrayReset); + + scene()->setSlicingActive(false); + adjustValueAxisRange(); + m_isDataDirty = true; + emitNeedRender(); +} + +void Surface3DController::handleArrayReset() +{ + scene()->setSlicingActive(false); + adjustValueAxisRange(); + m_isDataDirty = true; + emitNeedRender(); +} + +void Surface3DController::adjustValueAxisRange() +{ + if (m_data) { + QVector3D minLimits; + QVector3D maxLimits; + static_cast<QSurfaceDataProxy *>(m_data)->dptr()->limitValues(minLimits, maxLimits); + Q3DValueAxis *valueAxis = static_cast<Q3DValueAxis *>(m_axisX); + if (valueAxis && valueAxis->isAutoAdjustRange()) { + if (minLimits.x() != maxLimits.x()) + valueAxis->dptr()->setRange(minLimits.x(), maxLimits.x()); + else + valueAxis->dptr()->setRange(minLimits.x() - 1.0f, minLimits.x() + 1.0f); // Default to some valid range + } + + valueAxis = static_cast<Q3DValueAxis *>(m_axisY); + if (valueAxis && valueAxis->isAutoAdjustRange()) { + if (minLimits.y() != maxLimits.y()) + valueAxis->dptr()->setRange(minLimits.y(), maxLimits.y()); + else + valueAxis->dptr()->setRange(minLimits.y() - 1.0f, minLimits.y() + 1.0f); // Default to some valid range + } + + valueAxis = static_cast<Q3DValueAxis *>(m_axisZ); + if (valueAxis && valueAxis->isAutoAdjustRange()) { + if (minLimits.z() != maxLimits.z()) + valueAxis->dptr()->setRange(minLimits.z(), maxLimits.z()); + else + valueAxis->dptr()->setRange(minLimits.z() - 1.0f, minLimits.z() + 1.0f); // Default to some valid range + } + } +} + +QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavisualization/engine/surface3dcontroller_p.h b/src/datavisualization/engine/surface3dcontroller_p.h new file mode 100644 index 00000000..0efece97 --- /dev/null +++ b/src/datavisualization/engine/surface3dcontroller_p.h @@ -0,0 +1,108 @@ +/**************************************************************************** +** +** 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 SURFACE3DCONTROLLER_P_H +#define SURFACE3DCONTROLLER_P_H + +#include "abstract3dcontroller_p.h" +#include "datavisualizationglobal_p.h" + +#include <QLinearGradient> + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +class Surface3DRenderer; + +struct Surface3DChangeBitField { + bool gradientColorChanged : 1; + bool smoothStatusChanged : 1; + bool surfaceGridChanged : 1; + + Surface3DChangeBitField() : + gradientColorChanged(true), + smoothStatusChanged(true), + surfaceGridChanged(true) + { + } +}; + +class QT_DATAVISUALIZATION_EXPORT Surface3DController : public Abstract3DController +{ + Q_OBJECT + +private: + Surface3DChangeBitField m_changeTracker; + + // Rendering + Surface3DRenderer *m_renderer; + bool m_isSmoothSurfaceEnabled; + bool m_isSurfaceGridEnabled; + QLinearGradient m_userDefinedGradient; + +public: + explicit Surface3DController(QRect rect); + ~Surface3DController(); + + void initializeOpenGL(); + virtual void synchDataToRenderer(); + + void setSmoothSurface(bool enable); + bool smoothSurface(); + + void setSurfaceGrid(bool enable); + bool surfaceGrid(); + + void setGradient(const QLinearGradient &gradient); + QLinearGradient gradient() const; + + void setGradientColorAt(qreal pos, const QColor &color); + + void setSelectionMode(QDataVis::SelectionMode mode); + + virtual void setActiveDataProxy(QAbstractDataProxy *proxy); + + virtual void handleAxisAutoAdjustRangeChangedInOrientation(Q3DAbstractAxis::AxisOrientation orientation, bool autoAdjust); + virtual void handleAxisRangeChangedBySender(QObject *sender); + +public slots: + void handleArrayReset(); + +signals: + void smoothStatusChanged(bool enable); + void surfaceGridChanged(bool enable); + void segmentCountChanged(GLint segmentCount, GLfloat step, GLfloat minimum); + +private: + void adjustValueAxisRange(); + + Q_DISABLE_COPY(Surface3DController) +}; + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif // SURFACE3DCONTROLLER_P_H diff --git a/src/datavisualization/engine/surface3drenderer.cpp b/src/datavisualization/engine/surface3drenderer.cpp new file mode 100644 index 00000000..a1dfc7e8 --- /dev/null +++ b/src/datavisualization/engine/surface3drenderer.cpp @@ -0,0 +1,2185 @@ +/**************************************************************************** +** +** 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 "surface3dcontroller_p.h" +#include "surface3drenderer_p.h" +#include "q3dcamera.h" +#include "q3dcamera_p.h" +#include "shaderhelper_p.h" +#include "objecthelper_p.h" +#include "surfaceobject_p.h" +#include "texturehelper_p.h" +#include "selectionpointer_p.h" +#include "theme_p.h" +#include "utils_p.h" +#include "drawer_p.h" +#include "q3dlight.h" + +#include <QMatrix4x4> +#include <QMouseEvent> +#include <qmath.h> + +#include <QLinearGradient> +#include <QPainter> + +#include <QDebug> + +static const int ID_TO_RGBA_MASK = 0xff; + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +//#define SHOW_DEPTH_TEXTURE_SCENE + +// TODO Uniform scaling is broken on surface +//#define USE_UNIFORM_SCALING // Scale x and z uniformly, or based on autoscaled values + +const GLfloat aspectRatio = 2.0f; // Forced ratio of x and z to y. Dynamic will make it look odd. +const GLfloat backgroundMargin = 1.1f; // Margin for background (1.1f = make it 10% larger to avoid items being drawn inside background) +const GLfloat labelMargin = 0.05f; +const GLfloat backgroundBottom = 1.0f; +const GLfloat gridLineWidth = 0.005f; +const GLfloat sliceZScale = 0.1f; +const GLfloat surfaceGridYOffsetValue = 0.001f; +const GLfloat sliceUnits = 2.5f; +const int subViewDivider = 5; +// The second offset to opposite direction is double because same matrix is translated twice +const GLfloat surfaceGridYOffset[2] = {-surfaceGridYOffsetValue, 2.0f * surfaceGridYOffsetValue}; + +Surface3DRenderer::Surface3DRenderer(Surface3DController *controller) + : Abstract3DRenderer(controller), + m_controller(controller), + m_labelStyle(QDataVis::LabelStyleFromTheme), + m_font(QFont(QStringLiteral("Arial"))), + m_isGridEnabled(true), + m_shader(0), + m_depthShader(0), + m_backgroundShader(0), + m_surfaceShader(0), + m_surfaceGridShader(0), + m_selectionShader(0), + m_labelShader(0), + m_heightNormalizer(0.0f), + m_scaleFactor(0.0f), + m_scaleX(0.0f), + m_scaleZ(0.0f), + m_scaleXWithBackground(0.0f), + m_scaleZWithBackground(0.0f), + m_surfaceScaleX(0.0f), + m_surfaceScaleZ(0.0f), + m_surfaceOffsetX(0.0f), + m_surfaceOffsetZ(0.0f), + m_minVisibleColumnValue(0.0f), + m_maxVisibleColumnValue(0.0f), + m_minVisibleRowValue(0.0f), + m_maxVisibleRowValue(0.0f), + m_visibleColumnRange(0.0f), + m_visibleRowRange(0.0f), + m_backgroundObj(0), + m_gridLineObj(0), + m_labelObj(0), + m_surfaceObj(0), + m_sliceSurfaceObj(0), + m_depthTexture(0), + m_depthFrameBuffer(0), + m_selectionFrameBuffer(0), + m_selectionDepthBuffer(0), + m_gradientTexture(0), + m_selectionTexture(0), + m_selectionResultTexture(0), + m_shadowQualityToShader(33.3f), + m_flatSupported(true), + m_selectionPointer(0), + m_selectionActive(false), + m_xFlipped(false), + m_zFlipped(false), + m_yFlipped(false), + m_sampleSpace(QRect(0, 0, 0, 0)), + m_shadowQualityMultiplier(3), + m_cachedSelectionId(0), + m_selectionModeChanged(false), + m_hasHeightAdjustmentChanged(true) +{ +#if !defined(QT_OPENGL_ES_2) + // Check if flat feature is supported + ShaderHelper tester(this, QStringLiteral(":/shaders/vertexSurfaceFlat"), + QStringLiteral(":/shaders/fragmentSurfaceFlat")); + if (!tester.testCompile()) { + m_flatSupported = false; + m_controller->setSmoothSurface(true); + } +#endif + + m_cachedSmoothSurface = m_controller->smoothSurface(); + updateSurfaceGridStatus(m_controller->surfaceGrid()); + + // Shadows are disabled for Q3DSurface in Tech Preview + updateShadowQuality(QDataVis::ShadowQualityNone); + + initializeOpenGLFunctions(); + initializeOpenGL(); +} + +Surface3DRenderer::~Surface3DRenderer() +{ + m_textureHelper->glDeleteFramebuffers(1, &m_depthFrameBuffer); + m_textureHelper->glDeleteRenderbuffers(1, &m_selectionDepthBuffer); + m_textureHelper->glDeleteFramebuffers(1, &m_selectionFrameBuffer); + + m_textureHelper->deleteTexture(&m_depthTexture); + m_textureHelper->deleteTexture(&m_gradientTexture); + m_textureHelper->deleteTexture(&m_selectionTexture); + m_textureHelper->deleteTexture(&m_selectionResultTexture); + + delete m_shader; + delete m_depthShader; + delete m_backgroundShader; + delete m_selectionShader; + delete m_surfaceShader; + delete m_surfaceGridShader; + delete m_labelShader; + + delete m_backgroundObj; + delete m_surfaceObj; + delete m_sliceSurfaceObj; + delete m_gridLineObj; + delete m_labelObj; + + delete m_selectionPointer; + + for (int i = 0; i < m_dataArray.size(); i++) + delete m_dataArray.at(i); + m_dataArray.clear(); + + for (int i = 0; i < m_sliceDataArray.size(); i++) + delete m_sliceDataArray.at(i); + m_sliceDataArray.clear(); +} + +void Surface3DRenderer::initializeOpenGL() +{ + Abstract3DRenderer::initializeOpenGL(); + + // Initialize shaders + handleShadowQualityChange(); + + initSurfaceShaders(); + + initLabelShaders(QStringLiteral(":/shaders/vertexLabel"), + QStringLiteral(":/shaders/fragmentLabel")); + +#if !defined(QT_OPENGL_ES_2) + // Init depth shader (for shadows). Init in any case, easier to handle shadow activation if done via api. + initDepthShader(); +#endif + + // Init selection shader + initSelectionShaders(); + + // Load grid line mesh + loadGridLineMesh(); + + // Load label mesh + loadLabelMesh(); + + // Resize in case we've missed resize events + // Resize calls initSelectionBuffer and initDepthBuffer, so they don't need to be called here + handleResize(); + + // Load background mesh (we need to be initialized first) + loadBackgroundMesh(); +} + +void Surface3DRenderer::updateDataModel(QSurfaceDataProxy *dataProxy) +{ + calculateSceneScalingFactors(); + + const QSurfaceDataArray &array = *dataProxy->array(); + + // Need minimum of 2x2 array to draw a surface + if (array.size() >= 2 && array.at(0)->size() >= 2) { + QRect sampleSpace = calculateSampleRect(array); + + bool dimensionChanged = false; + if (m_sampleSpace != sampleSpace) { + dimensionChanged = true; + m_sampleSpace = sampleSpace; + + for (int i = 0; i < m_dataArray.size(); i++) + delete m_dataArray.at(i); + m_dataArray.clear(); + } + + // TODO: Handle partial surface grids on the graph edges + if (sampleSpace.width() >= 2 && sampleSpace.height() >= 2) { + if (dimensionChanged) { + m_dataArray.reserve(sampleSpace.height()); + for (int i = 0; i < sampleSpace.height(); i++) + m_dataArray << new QSurfaceDataRow(sampleSpace.width()); + } + for (int i = 0; i < sampleSpace.height(); i++) { + for (int j = 0; j < sampleSpace.width(); j++) + (*(m_dataArray.at(i)))[j] = array.at(i + sampleSpace.y())->at(j + sampleSpace.x()); + } + + if (m_dataArray.size() > 0) { + if (!m_surfaceObj) + loadSurfaceObj(); + + // Note: Data setup can change samplespace (as min width/height is 1) + if (m_cachedSmoothSurface) { + m_surfaceObj->setUpSmoothData(m_dataArray, m_sampleSpace, m_heightNormalizer, + m_axisCacheY.min(), dimensionChanged); + } else { + m_surfaceObj->setUpData(m_dataArray, m_sampleSpace, m_heightNormalizer, + m_axisCacheY.min(), dimensionChanged); + } + + if (dimensionChanged) + updateSelectionTexture(); + } + } + } + + m_selectionActive = false; + m_cachedSelectionId = 0; + for (int i = 0; i < m_sliceDataArray.size(); i++) + delete m_sliceDataArray.at(i); + m_sliceDataArray.clear(); + + Abstract3DRenderer::updateDataModel(dataProxy); +} + +void Surface3DRenderer::updateSliceDataModel(int selectionId) +{ + int column = (selectionId - 1) % m_sampleSpace.width(); + int row = (selectionId - 1) / m_sampleSpace.width(); + + for (int i = 0; i < m_sliceDataArray.size(); i++) + delete m_sliceDataArray.at(i); + m_sliceDataArray.clear(); + + m_sliceDataArray.reserve(2); + QSurfaceDataRow *sliceRow; + + qreal adjust = (0.025 * m_heightNormalizer) / 2.0; + qreal stepDown = 2.0 * adjust; + if (m_cachedSelectionMode == QDataVis::SelectionModeSliceRow) { + QSurfaceDataRow *src = m_dataArray.at(row); + sliceRow = new QSurfaceDataRow(src->size()); + for (int i = 0; i < sliceRow->size(); i++) + (*sliceRow)[i].setPosition(QVector3D(src->at(i).x(), src->at(i).y() + adjust, -1.0)); + } else { + sliceRow = new QSurfaceDataRow(m_sampleSpace.height()); + for (int i = 0; i < m_sampleSpace.height(); i++) { + (*sliceRow)[i].setPosition(QVector3D(m_dataArray.at(i)->at(column).z(), + m_dataArray.at(i)->at(column).y() + adjust, + -1.0)); + } + } + + m_sliceDataArray << sliceRow; + + // Make a duplicate, so that we get a little bit depth + QSurfaceDataRow *duplicateRow = new QSurfaceDataRow(*sliceRow); + for (int i = 0; i < sliceRow->size(); i++) + (*sliceRow)[i].setPosition(QVector3D(sliceRow->at(i).x(), sliceRow->at(i).y() - stepDown, 1.0)); + + m_sliceDataArray << duplicateRow; + + QRect sliceRect(0, 0, sliceRow->size(), 2); + + if (sliceRow->size() > 0) { + if (!m_sliceSurfaceObj) + loadSliceSurfaceObj(); + + if (m_cachedSmoothSurface) { + m_sliceSurfaceObj->setUpSmoothData(m_sliceDataArray, sliceRect, m_heightNormalizer, + m_axisCacheY.min(), true); + } else { + m_sliceSurfaceObj->setUpData(m_sliceDataArray, sliceRect, m_heightNormalizer, + m_axisCacheY.min(), true); + } + } +} + +QRect Surface3DRenderer::calculateSampleRect(const QSurfaceDataArray &array) +{ + QRect sampleSpace; + + int rowCount = array.size(); + int columnCount = array.at(0)->size(); + + int i; + bool found; + float axisMinX = float(m_axisCacheX.min()); + float axisMaxX = float(m_axisCacheX.max()); + float axisMinZ = float(m_axisCacheZ.min()); + float axisMaxZ = float(m_axisCacheZ.max()); + + // Comparisons between float and double are not accurate, so fudge our comparison values + //a little to get all rows and columns into view that need to be visible. + const float fudgeFactor = 0.00001f; + float fudgedAxisXRange = (axisMaxX - axisMinX) * fudgeFactor; + float fudgedAxisZRange = (axisMaxZ - axisMinZ) * fudgeFactor; + axisMinX -= fudgedAxisXRange; + axisMinZ -= fudgedAxisZRange; + axisMaxX += fudgedAxisXRange; + axisMaxZ += fudgedAxisZRange; + + // m_minVisibleColumnValue + for (i = 0, found = false; i < columnCount; i++) { + if (array.at(0)->at(i).x() >= axisMinX) { + found = true; + break; + } + } + if (found) { + m_minVisibleColumnValue = array.at(0)->at(i).x(); + sampleSpace.setLeft(i); + } else { + sampleSpace.setWidth(-1); // to indicate nothing needs to be shown + return sampleSpace; + } + + // m_maxVisibleColumnValue + for (i = columnCount - 1, found = false; i >= 0; i--) { + if (array.at(0)->at(i).x() <= axisMaxX) { + found = true; + break; + } + } + if (found) { + m_maxVisibleColumnValue = array.at(0)->at(i).x(); + sampleSpace.setRight(i); + } else { + sampleSpace.setWidth(-1); // to indicate nothing needs to be shown + return sampleSpace; + } + + // m_minVisibleRowValue + for (i = 0, found = false; i < rowCount; i++) { + if (array.at(i)->at(0).z() >= axisMinZ) { + found = true; + break; + } + } + if (found) { + m_minVisibleRowValue = array.at(i)->at(0).z(); + sampleSpace.setTop(i); + } else { + sampleSpace.setWidth(-1); // to indicate nothing needs to be shown + return sampleSpace; + } + + // m_maxVisibleRowValue + for (i = rowCount - 1, found = false; i >= 0; i--) { + if (array.at(i)->at(0).z() <= axisMaxZ) { + found = true; + break; + } + } + if (found) { + m_maxVisibleRowValue = array.at(i)->at(0).z(); + sampleSpace.setBottom(i); + } else { + sampleSpace.setWidth(-1); // to indicate nothing needs to be shown + return sampleSpace; + } + + m_visibleColumnRange = m_maxVisibleColumnValue - m_minVisibleColumnValue; + m_visibleRowRange = m_maxVisibleRowValue - m_minVisibleRowValue; + m_surfaceScaleX = m_scaleX * m_visibleColumnRange / m_areaSize.width(); + m_surfaceScaleZ = m_scaleZ * m_visibleRowRange / m_areaSize.height(); + GLfloat axis2XCenterX = axisMinX + axisMaxX; + GLfloat axis2XCenterZ = axisMinZ + axisMaxZ; + GLfloat data2XCenterX = GLfloat(m_minVisibleColumnValue + m_maxVisibleColumnValue); + GLfloat data2XCenterZ = GLfloat(m_minVisibleRowValue + m_maxVisibleRowValue); + m_surfaceOffsetX = m_scaleX * (data2XCenterX - axis2XCenterX) / m_areaSize.width(); + m_surfaceOffsetZ = -m_scaleZ * (data2XCenterZ - axis2XCenterZ) / m_areaSize.height(); + + return sampleSpace; +} + +void Surface3DRenderer::updateScene(Q3DScene *scene) +{ + // TODO: Move these to more suitable place e.g. controller should be controlling the viewports. + scene->setSecondarySubViewport(m_sliceViewPort); + scene->setPrimarySubViewport(m_mainViewPort); + + // Set initial camera position + // X must be 0 for rotation to work - we can use "setCameraRotation" for setting it later + if (m_hasHeightAdjustmentChanged) { + scene->activeCamera()->setBaseOrientation(QVector3D(0.0f, 0.0f, cameraDistance + zComp), + QVector3D(0.0f, 0.0f, zComp), + QVector3D(0.0f, 1.0f, 0.0f)); + // For now this is used just to make things once. Proper use will come + m_hasHeightAdjustmentChanged = false; + } + + scene->activeCamera()->d_ptr->updateViewMatrix(m_autoScaleAdjustment); + scene->setLightPositionRelativeToCamera(defaultLightPos); + + if (m_selectionPointer) + m_selectionPointer->updateScene(scene); + + Abstract3DRenderer::updateScene(scene); +} + +void Surface3DRenderer::render(GLuint defaultFboHandle) +{ + bool slicingActivated = m_cachedScene->isSlicingActive(); + bool slicingChanged = m_cachedIsSlicingActivated != slicingActivated; + + updateSlicingActive(slicingActivated); + + // Handle GL state setup for FBO buffers and clearing of the render surface + Abstract3DRenderer::render(defaultFboHandle); + + // In slice mode; draw slice and render selection ball + if (m_cachedIsSlicingActivated && m_selectionPointer && m_selectionActive) { + drawSlicedScene(); + m_selectionPointer->render(defaultFboHandle); + } + + // Draw the surface scene + drawScene(defaultFboHandle); + + // Render selection ball if not in slice mode + if (!m_cachedIsSlicingActivated && m_selectionPointer && m_selectionActive) + m_selectionPointer->render(defaultFboHandle); + + // If slicing has been activated by this render pass, we need another render + // Also trigger another render always when slicing changes in general to ensure + // final draw is correct. + if (slicingActivated != m_cachedScene->isSlicingActive() || slicingChanged) + emit needRender(); +} + +void Surface3DRenderer::drawSlicedScene() +{ + QVector3D lightPos; + + // Specify viewport + glViewport(m_sliceViewPort.x(), m_sliceViewPort.y(), + m_sliceViewPort.width(), m_sliceViewPort.height()); + + // Set up projection matrix + QMatrix4x4 projectionMatrix; + + GLfloat aspect = (GLfloat)m_mainViewPort.width() / (GLfloat)m_mainViewPort.height(); + projectionMatrix.ortho(-sliceUnits * aspect, sliceUnits * aspect, + -sliceUnits, sliceUnits, -1.0f, 14.0f); // 14.0 because of zComp + + // Set view matrix + QMatrix4x4 viewMatrix; + viewMatrix.lookAt(QVector3D(0.0f, 0.0f, zComp + 1.0f), + QVector3D(0.0f, 0.0f, zComp), + QVector3D(0.0f, 1.0f, 0.0f)); + + // Set light position + lightPos = m_cachedScene->activeLight()->position(); + + QMatrix4x4 projectionViewMatrix = projectionMatrix * viewMatrix; + + GLfloat scaleX = 0.0f; + GLfloat scaleXBackground = 0.0f; + GLfloat offset = 0.0f; + if (m_cachedSelectionMode == QDataVis::SelectionModeSliceRow) { + scaleX = m_surfaceScaleX; + scaleXBackground = m_scaleXWithBackground; + offset = m_surfaceOffsetX; + } else if (m_cachedSelectionMode == QDataVis::SelectionModeSliceColumn) { + scaleX = m_surfaceScaleZ; + scaleXBackground = m_scaleZWithBackground; + offset = -m_surfaceOffsetZ; + } + + if (m_surfaceObj) { + ShaderHelper *surfaceShader = m_shader; + surfaceShader->bind(); + + QMatrix4x4 modelMatrix; + QMatrix4x4 MVPMatrix; + QMatrix4x4 itModelMatrix; + + modelMatrix.translate(offset, 0.0f, zComp); + QVector3D scaling(scaleX, 1.0f, sliceZScale); + modelMatrix.scale(scaling); + itModelMatrix.scale(scaling); + + MVPMatrix = projectionViewMatrix * modelMatrix; + + QVector3D color; + if (m_cachedSelectionMode == QDataVis::SelectionModeSliceRow) + color = Utils::vectorFromColor(m_cachedTheme.m_highlightRowColor); + else + color = Utils::vectorFromColor(m_cachedTheme.m_highlightColumnColor); + + // Set shader bindings + surfaceShader->setUniformValue(surfaceShader->lightP(), lightPos); + surfaceShader->setUniformValue(surfaceShader->view(), viewMatrix); + surfaceShader->setUniformValue(surfaceShader->model(), modelMatrix); + surfaceShader->setUniformValue(surfaceShader->nModel(), itModelMatrix.inverted().transposed()); + surfaceShader->setUniformValue(surfaceShader->MVP(), MVPMatrix); + surfaceShader->setUniformValue(surfaceShader->color(), color); + surfaceShader->setUniformValue(surfaceShader->lightS(), 0.25f); + surfaceShader->setUniformValue(surfaceShader->ambientS(), + m_cachedTheme.m_ambientStrength * 2.0f); + + m_drawer->drawObject(surfaceShader, m_sliceSurfaceObj); + + surfaceShader->release(); + + // Draw surface grid + if (m_cachedSurfaceGridOn) { + m_surfaceGridShader->bind(); + + m_surfaceGridShader->setUniformValue(m_surfaceGridShader->color(), + Utils::vectorFromColor(m_cachedTheme.m_gridLine)); + // Draw the grid twice, with slight offset on Y axis to each direction + for (int i = 0; i < 2; i++) { + MVPMatrix.translate(0.0f, surfaceGridYOffset[i], 0.0f); + + m_surfaceGridShader->setUniformValue(m_surfaceGridShader->MVP(), MVPMatrix); + m_drawer->drawSurfaceGrid(m_surfaceGridShader, m_sliceSurfaceObj); + } + m_surfaceGridShader->release(); + } + } + + // Disable textures + glDisable(GL_TEXTURE_2D); + + // lines to the back + if (m_cachedIsGridEnabled && m_heightNormalizer) { + ShaderHelper *lineShader = m_backgroundShader; + // Bind line shader + lineShader->bind(); + + if (m_axisCacheY.segmentCount() > 0) { + QVector3D gridLineScaleX(scaleXBackground, gridLineWidth, gridLineWidth); + + // Set unchanging shader bindings + QVector3D lineColor = Utils::vectorFromColor(m_cachedTheme.m_gridLine); + lineShader->setUniformValue(lineShader->lightP(), lightPos); + lineShader->setUniformValue(lineShader->view(), viewMatrix); + lineShader->setUniformValue(lineShader->color(), lineColor); + lineShader->setUniformValue(lineShader->ambientS(), m_cachedTheme.m_ambientStrength * 2.0f); + lineShader->setUniformValue(lineShader->lightS(), 0.25f); + + // Back wall + GLfloat lineStep = 2.0f * m_axisCacheY.subSegmentStep() / m_heightNormalizer; + GLfloat linePos = -1.0f; + int lastSegment = m_axisCacheY.subSegmentCount() * m_axisCacheY.segmentCount(); + + for (int segment = 0; segment <= lastSegment; segment++) { + QMatrix4x4 modelMatrix; + QMatrix4x4 MVPMatrix; + QMatrix4x4 itModelMatrix; + + modelMatrix.translate(0.0f, linePos, zComp - sliceZScale); + + modelMatrix.scale(gridLineScaleX); + itModelMatrix.scale(gridLineScaleX); + + MVPMatrix = projectionViewMatrix * modelMatrix; + + // Set the rest of the shader bindings + lineShader->setUniformValue(lineShader->model(), modelMatrix); + lineShader->setUniformValue(lineShader->nModel(), + itModelMatrix.inverted().transposed()); + lineShader->setUniformValue(lineShader->MVP(), MVPMatrix); + + // Draw the object + m_drawer->drawObject(lineShader, m_gridLineObj); + + linePos += lineStep; + } + } + + // Floor lines + QVector3D gridLineScaleZ(gridLineWidth, gridLineWidth, sliceZScale); + QVector3D gridLineScaleY(gridLineWidth, backgroundMargin, gridLineWidth); + + int lastSegment; + GLfloat lineStep; + GLfloat linePos; + if (m_cachedSelectionMode == QDataVis::SelectionModeSliceRow) { + lineStep = -2.0f * aspectRatio * m_axisCacheX.subSegmentStep() / m_scaleFactor; + lastSegment = m_axisCacheX.subSegmentCount() * m_axisCacheX.segmentCount(); + linePos = m_scaleX; + } else { + lineStep = -2.0f * aspectRatio * m_axisCacheZ.subSegmentStep() / m_scaleFactor; + lastSegment = m_axisCacheZ.subSegmentCount() * m_axisCacheZ.segmentCount(); + linePos = m_scaleZ; + } + + for (int segment = 0; segment <= lastSegment; segment++) { + QMatrix4x4 modelMatrix; + QMatrix4x4 MVPMatrix; + QMatrix4x4 itModelMatrix; + + modelMatrix.translate(linePos, -backgroundMargin, zComp); + + modelMatrix.scale(gridLineScaleZ); + itModelMatrix.scale(gridLineScaleZ); + + MVPMatrix = projectionViewMatrix * modelMatrix; + + // Set the rest of the shader bindings + lineShader->setUniformValue(lineShader->model(), modelMatrix); + lineShader->setUniformValue(lineShader->nModel(), + itModelMatrix.inverted().transposed()); + lineShader->setUniformValue(lineShader->MVP(), MVPMatrix); + + // Draw the object + m_drawer->drawObject(lineShader, m_gridLineObj); + + linePos += lineStep; + } + + if (m_cachedSelectionMode == QDataVis::SelectionModeSliceRow) + linePos = m_scaleX; + else + linePos = m_scaleZ; + + for (int segment = 0; segment <= lastSegment; segment++) { + QMatrix4x4 modelMatrix; + QMatrix4x4 MVPMatrix; + QMatrix4x4 itModelMatrix; + + modelMatrix.translate(linePos, 0.0f, zComp - sliceZScale); + modelMatrix.scale(gridLineScaleY); + itModelMatrix.scale(gridLineScaleY); + + MVPMatrix = projectionViewMatrix * modelMatrix; + + // Set the rest of the shader bindings + lineShader->setUniformValue(lineShader->model(), modelMatrix); + lineShader->setUniformValue(lineShader->nModel(), + itModelMatrix.inverted().transposed()); + lineShader->setUniformValue(lineShader->MVP(), MVPMatrix); + + // Draw the object + m_drawer->drawObject(lineShader, m_gridLineObj); + + linePos += lineStep; + } + + // Release line shader + lineShader->release(); + } + + // Draw axis labels + m_labelShader->bind(); + glEnable(GL_TEXTURE_2D); + glDisable(GL_DEPTH_TEST); + glCullFace(GL_BACK); + if (m_cachedLabelStyle > QDataVis::LabelStyleOpaque) { + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + + // Y Labels to back wall + GLfloat posStep = 2.0f * m_axisCacheY.segmentStep() / m_heightNormalizer; + GLfloat labelPos = -1.0f; + int labelNbr = 0; + + QVector3D positionComp(0.0f, 0.0f, zComp); + QVector3D rotation(0.0f, 0.0f, 0.0f); + QVector3D labelTrans = QVector3D(scaleXBackground + labelMargin, labelPos, zComp); + for (int segment = 0; segment <= m_axisCacheY.segmentCount(); segment++) { + if (m_axisCacheY.labelItems().size() > labelNbr) { + labelTrans.setY(labelPos); + const LabelItem &axisLabelItem = *m_axisCacheY.labelItems().at(labelNbr); + + // Draw the label here + m_dummyRenderItem.setTranslation(labelTrans); + m_drawer->drawLabel(m_dummyRenderItem, axisLabelItem, viewMatrix, projectionMatrix, + positionComp, rotation, 0, m_cachedSelectionMode, m_labelShader, + m_labelObj, m_cachedScene->activeCamera(), + true, true, Drawer::LabelMid, Qt::AlignRight); + } + labelNbr++; + labelPos += posStep; + } + + // X Labels to ground + int countLabelItems; + int lastSegment; + if (m_cachedSelectionMode == QDataVis::SelectionModeSliceRow) { + posStep = 2.0f * aspectRatio * m_axisCacheX.segmentStep() / m_scaleFactor; + labelPos = -m_scaleX; + lastSegment = m_axisCacheX.segmentCount(); + countLabelItems = m_axisCacheX.labelItems().size(); + } else { + posStep = 2.0f * aspectRatio * m_axisCacheZ.segmentStep() / m_scaleFactor; + labelPos = -m_scaleZ; + lastSegment = m_axisCacheZ.segmentCount(); + countLabelItems = m_axisCacheZ.labelItems().size(); + } + + labelNbr = 0; + positionComp.setY(backgroundMargin); + rotation.setZ(-45.0f); + labelTrans.setY(-backgroundMargin); + for (int segment = 0; segment <= lastSegment; segment++) { + if (countLabelItems > labelNbr) { + // Draw the label here + labelTrans.setX(labelPos); + + m_dummyRenderItem.setTranslation(labelTrans); + + LabelItem *axisLabelItem; + if (m_cachedSelectionMode == QDataVis::SelectionModeSliceRow) + axisLabelItem = m_axisCacheX.labelItems().at(labelNbr); + else + axisLabelItem = m_axisCacheZ.labelItems().at(labelNbr); + + m_drawer->drawLabel(m_dummyRenderItem, *axisLabelItem, viewMatrix, projectionMatrix, + positionComp, rotation, 0, QDataVis::SelectionModeSliceRow, + m_labelShader, m_labelObj, m_cachedScene->activeCamera(), + false, false, Drawer::LabelBelow, Qt::AlignTop); + } + labelNbr++; + labelPos += posStep; + } + + glDisable(GL_TEXTURE_2D); + glEnable(GL_DEPTH_TEST); + if (m_cachedLabelStyle > QDataVis::LabelStyleOpaque) + glDisable(GL_BLEND); + + // Release label shader + m_labelShader->release(); +} + +void Surface3DRenderer::drawScene(GLuint defaultFboHandle) +{ + GLfloat backgroundRotation = 0; + uint selectionId = 0; + + // Specify viewport + glViewport(m_mainViewPort.x(), m_mainViewPort.y(), + m_mainViewPort.width(), m_mainViewPort.height()); + + // Set up projection matrix + QMatrix4x4 projectionMatrix; + projectionMatrix.perspective(45.0f, (GLfloat)m_mainViewPort.width() + / (GLfloat)m_mainViewPort.height(), 0.1f, 100.0f); + + // Calculate view matrix + QMatrix4x4 viewMatrix = m_cachedScene->activeCamera()->viewMatrix(); + + QMatrix4x4 projectionViewMatrix = projectionMatrix * viewMatrix; + + // Calculate flipping indicators + if (viewMatrix.row(0).x() > 0) + m_zFlipped = false; + else + m_zFlipped = true; + if (viewMatrix.row(0).z() <= 0) + m_xFlipped = false; + else + m_xFlipped = true; + + // calculate background rotation based on view matrix rotation + if (viewMatrix.row(0).x() > 0 && viewMatrix.row(0).z() <= 0) + backgroundRotation = 270.0f; + else if (viewMatrix.row(0).x() > 0 && viewMatrix.row(0).z() > 0) + backgroundRotation = 180.0f; + else if (viewMatrix.row(0).x() <= 0 && viewMatrix.row(0).z() > 0) + backgroundRotation = 90.0f; + else if (viewMatrix.row(0).x() <= 0 && viewMatrix.row(0).z() <= 0) + backgroundRotation = 0.0f; + + QVector3D lightPos = m_cachedScene->activeLight()->position(); + + QMatrix4x4 depthViewMatrix; + QMatrix4x4 depthProjectionMatrix; + QMatrix4x4 depthProjectionViewMatrix; + + GLfloat adjustedLightStrength = m_cachedTheme.m_lightStrength / 10.0f; + + QVector3D surfaceScaler(m_surfaceScaleX, 1.0f, m_surfaceScaleZ); + QVector3D surfaceOffset(m_surfaceOffsetX, 0.0f, m_surfaceOffsetZ + zComp); + + // Draw depth buffer +#if !defined(QT_OPENGL_ES_2) + if (m_cachedShadowQuality > QDataVis::ShadowQualityNone && m_surfaceObj) { + // Render scene into a depth texture for using with shadow mapping + // Enable drawing to depth framebuffer + glBindFramebuffer(GL_FRAMEBUFFER, m_depthFrameBuffer); + glClear(GL_DEPTH_BUFFER_BIT); + + // Bind depth shader + m_depthShader->bind(); + + // Set viewport for depth map rendering. Must match texture size. Larger values give smoother shadows. + glViewport(m_mainViewPort.x(), m_mainViewPort.y(), + m_mainViewPort.width() * m_shadowQualityMultiplier, + m_mainViewPort.height() * m_shadowQualityMultiplier); + + // Get the depth view matrix + // It may be possible to hack lightPos here if we want to make some tweaks to shadow + QVector3D depthLightPos = m_cachedScene->activeCamera()->calculatePositionRelativeToCamera( + QVector3D(0.0f, 0.0f, zComp), 0.0f, 1.5f / m_autoScaleAdjustment); + depthViewMatrix.lookAt(depthLightPos, QVector3D(0.0f, 0.0f, zComp), + QVector3D(0.0f, 1.0f, 0.0f)); + + // TODO: Why does depthViewMatrix.column(3).y() goes to zero when we're directly above? + // That causes the scene to be not drawn from above -> must be fixed + // qDebug() << lightPos << depthViewMatrix << depthViewMatrix.column(3); + // Set the depth projection matrix +#ifndef USE_WIDER_SHADOWS + // Use this for perspective shadows + depthProjectionMatrix.perspective(10.0f, (GLfloat)m_mainViewPort.width() + / (GLfloat)m_mainViewPort.height(), 3.0f, 100.0f); +#else + // Use these for orthographic shadows + depthProjectionMatrix.ortho(-2.0f * 2.0f, 2.0f * 2.0f, + -2.0f, 2.0f, + 0.0f, 100.0f); +#endif + depthProjectionViewMatrix = depthProjectionMatrix * depthViewMatrix; + + glCullFace(GL_FRONT); + + QMatrix4x4 modelMatrix; + QMatrix4x4 MVPMatrix; + + modelMatrix.translate(surfaceOffset); + modelMatrix.scale(surfaceScaler); + + MVPMatrix = depthProjectionViewMatrix * modelMatrix; + + m_depthShader->setUniformValue(m_depthShader->MVP(), MVPMatrix); + + // 1st attribute buffer : vertices + glEnableVertexAttribArray(m_depthShader->posAtt()); + glBindBuffer(GL_ARRAY_BUFFER, m_surfaceObj->vertexBuf()); + glVertexAttribPointer(m_depthShader->posAtt(), 3, GL_FLOAT, GL_FALSE, 0, + (void *)0); + + // Index buffer + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_surfaceObj->elementBuf()); + + // Draw the triangles + glDrawElements(GL_TRIANGLES, m_surfaceObj->indexCount(), GL_UNSIGNED_SHORT, + (void *)0); + + // Free buffers + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + glDisableVertexAttribArray(m_depthShader->posAtt()); + + // Disable drawing to depth framebuffer (= enable drawing to screen) + glBindFramebuffer(GL_FRAMEBUFFER, defaultFboHandle); + + // Release depth shader + m_depthShader->release(); + + // Revert to original viewport + glViewport(m_mainViewPort.x(), m_mainViewPort.y(), + m_mainViewPort.width(), m_mainViewPort.height()); + + // Reset culling to normal + glCullFace(GL_BACK); + +#if 0 // Use this if you want to see what is being drawn to the framebuffer + // You'll also have to comment out GL_COMPARE_R_TO_TEXTURE -line in texturehelper (if using it) + { + m_labelShader->bind(); + glEnable(GL_TEXTURE_2D); + QMatrix4x4 modelMatrix; + QMatrix4x4 viewmatrix; + viewmatrix.lookAt(QVector3D(0.0f, 0.0f, 2.5f + zComp), + QVector3D(0.0f, 0.0f, zComp), + QVector3D(0.0f, 1.0f, 0.0f)); + modelMatrix.translate(0.0, 0.0, zComp); + QMatrix4x4 MVPMatrix = projectionMatrix * viewmatrix * modelMatrix; + m_labelShader->setUniformValue(m_labelShader->MVP(), MVPMatrix); + m_drawer->drawObject(m_labelShader, m_labelObj, m_depthTexture); + glDisable(GL_TEXTURE_2D); + m_labelShader->release(); + } +#endif + } +#endif + + bool selectionDirty = false; + + // Enable texturing + glEnable(GL_TEXTURE_2D); + + // Draw selection buffer + if (!m_cachedIsSlicingActivated && m_controller->inputState() == QDataVis::InputStateOnScene + && m_surfaceObj && m_cachedSelectionMode > QDataVis::SelectionModeNone) { + m_selectionShader->bind(); + glBindFramebuffer(GL_FRAMEBUFFER, m_selectionFrameBuffer); + glEnable(GL_DEPTH_TEST); // Needed, otherwise the depth render buffer is not used + glClearColor(0, 0, 0, 0); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Needed for clearing the frame buffer + glDisable(GL_DITHER); // disable dithering, it may affect colors if enabled + + glDisable(GL_CULL_FACE); + + QMatrix4x4 modelMatrix; + QMatrix4x4 MVPMatrix; + + modelMatrix.translate(surfaceOffset); + modelMatrix.scale(surfaceScaler); + + MVPMatrix = projectionViewMatrix * modelMatrix; + + m_selectionShader->setUniformValue(m_selectionShader->MVP(), MVPMatrix); + + m_drawer->drawObject(m_selectionShader, m_surfaceObj, m_selectionTexture); + + glEnable(GL_DITHER); + + QPoint point = m_controller->inputPosition(); + GLubyte pixel[4] = {0}; + glReadPixels(point.x(), m_cachedBoundingRect.height() - point.y(), 1, 1, + GL_RGBA, GL_UNSIGNED_BYTE, (void *)pixel); + + glBindFramebuffer(GL_FRAMEBUFFER, defaultFboHandle); + + // Release selection shader + m_selectionShader->release(); + + // Put the RGBA value back to uint +#if defined (Q_OS_ANDROID) + selectionId = pixel[0] + pixel[1] * 256 + pixel[2] * 65536; +#else + selectionId = pixel[0] + pixel[1] * 256 + pixel[2] * 65536 + pixel[3] * 16777216; +#endif + + selectionDirty = true; + } + + // Draw the surface + if (m_surfaceObj && m_sampleSpace.width() >= 2 && m_sampleSpace.height() >= 2) { + m_surfaceShader->bind(); + + // For surface we can see climpses from underneath + glDisable(GL_CULL_FACE); + + QMatrix4x4 modelMatrix; + QMatrix4x4 MVPMatrix; + QMatrix4x4 depthMVPMatrix; + QMatrix4x4 itModelMatrix; + + modelMatrix.translate(surfaceOffset); + modelMatrix.scale(surfaceScaler); + itModelMatrix.scale(surfaceScaler); + +#ifdef SHOW_DEPTH_TEXTURE_SCENE + MVPMatrix = depthProjectionViewMatrix * modelMatrix; +#else + MVPMatrix = projectionViewMatrix * modelMatrix; +#endif + depthMVPMatrix = depthProjectionViewMatrix * modelMatrix; + + // Set shader bindings + m_surfaceShader->setUniformValue(m_surfaceShader->lightP(), lightPos); + m_surfaceShader->setUniformValue(m_surfaceShader->view(), viewMatrix); + m_surfaceShader->setUniformValue(m_surfaceShader->model(), modelMatrix); + m_surfaceShader->setUniformValue(m_surfaceShader->nModel(), + itModelMatrix.inverted().transposed()); + m_surfaceShader->setUniformValue(m_surfaceShader->MVP(), MVPMatrix); + m_surfaceShader->setUniformValue(m_surfaceShader->ambientS(), + m_cachedTheme.m_ambientStrength); + +#if !defined(QT_OPENGL_ES_2) + if (m_cachedShadowQuality > QDataVis::ShadowQualityNone) { + // Set shadow shader bindings + m_surfaceShader->setUniformValue(m_surfaceShader->shadowQ(), m_shadowQualityToShader); + m_surfaceShader->setUniformValue(m_surfaceShader->depth(), depthMVPMatrix); + m_surfaceShader->setUniformValue(m_surfaceShader->lightS(), adjustedLightStrength); + + // Draw the object + m_drawer->drawObject(m_surfaceShader, m_surfaceObj, m_gradientTexture, m_depthTexture); + } else +#endif + { + // Set shadowless shader bindings + m_surfaceShader->setUniformValue(m_surfaceShader->lightS(), + m_cachedTheme.m_lightStrength); + + // Draw the object + m_drawer->drawObject(m_surfaceShader, m_surfaceObj, m_gradientTexture); + } + + m_surfaceShader->release(); + + glEnable(GL_CULL_FACE); + + // Draw surface grid + if (m_cachedSurfaceGridOn) { + m_surfaceGridShader->bind(); + + m_surfaceGridShader->setUniformValue(m_surfaceGridShader->color(), + Utils::vectorFromColor(m_cachedTheme.m_gridLine)); + // Draw the grid twice, with slight offset on Y axis to each direction + for (int i = 0; i < 2; i++) { + MVPMatrix.translate(0.0f, surfaceGridYOffset[i], 0.0f); + + m_surfaceGridShader->setUniformValue(m_surfaceGridShader->MVP(), MVPMatrix); + m_drawer->drawSurfaceGrid(m_surfaceGridShader, m_surfaceObj); + } + m_surfaceGridShader->release(); + } + } + + // Bind background shader + m_backgroundShader->bind(); + glCullFace(GL_BACK); + + // Draw background + if (m_cachedIsBackgroundEnabled && m_backgroundObj) { + QMatrix4x4 modelMatrix; + QMatrix4x4 MVPMatrix; + QMatrix4x4 depthMVPMatrix; + QMatrix4x4 itModelMatrix; + + modelMatrix.translate(0.0f, 0.0f, zComp); + QVector3D bgScale(m_scaleXWithBackground, backgroundMargin, m_scaleZWithBackground); + modelMatrix.scale(bgScale); + itModelMatrix.scale(bgScale); + + // If we're viewing from below, background object must be flipped + if (m_yFlipped) { + modelMatrix.rotate(180.0f, 1.0, 0.0, 0.0); + modelMatrix.rotate(270.0f - backgroundRotation, 0.0f, 1.0f, 0.0f); + } else { + modelMatrix.rotate(backgroundRotation, 0.0f, 1.0f, 0.0f); + } + +#ifdef SHOW_DEPTH_TEXTURE_SCENE + MVPMatrix = depthProjectionViewMatrix * modelMatrix; +#else + MVPMatrix = projectionViewMatrix * modelMatrix; +#endif + depthMVPMatrix = depthProjectionViewMatrix * modelMatrix; + + QVector3D backgroundColor = Utils::vectorFromColor(m_cachedTheme.m_backgroundColor); + + // Set shader bindings + m_backgroundShader->setUniformValue(m_backgroundShader->lightP(), lightPos); + m_backgroundShader->setUniformValue(m_backgroundShader->view(), viewMatrix); + m_backgroundShader->setUniformValue(m_backgroundShader->model(), modelMatrix); + m_backgroundShader->setUniformValue(m_backgroundShader->nModel(), + itModelMatrix.inverted().transposed()); + m_backgroundShader->setUniformValue(m_backgroundShader->MVP(), MVPMatrix); + m_backgroundShader->setUniformValue(m_backgroundShader->color(), backgroundColor); + m_backgroundShader->setUniformValue(m_backgroundShader->ambientS(), + m_cachedTheme.m_ambientStrength * 2.0f); + +#if !defined(QT_OPENGL_ES_2) + if (m_cachedShadowQuality > QDataVis::ShadowQualityNone) { + // Set shadow shader bindings + m_backgroundShader->setUniformValue(m_backgroundShader->shadowQ(), + m_shadowQualityToShader); + m_backgroundShader->setUniformValue(m_backgroundShader->depth(), depthMVPMatrix); + m_backgroundShader->setUniformValue(m_backgroundShader->lightS(), + adjustedLightStrength); + + // Draw the object + m_drawer->drawObject(m_backgroundShader, m_backgroundObj, 0, m_depthTexture); + } else +#endif + { + // Set shadowless shader bindings + m_backgroundShader->setUniformValue(m_backgroundShader->lightS(), + m_cachedTheme.m_lightStrength); + + // Draw the object + m_drawer->drawObject(m_backgroundShader, m_backgroundObj); + } + } + + // Release background shader + m_backgroundShader->release(); + + // Draw grid lines + QVector3D gridLineScaleX(m_scaleXWithBackground, gridLineWidth, gridLineWidth); + QVector3D gridLineScaleZ(gridLineWidth, gridLineWidth, m_scaleZWithBackground); + QVector3D gridLineScaleY(gridLineWidth, backgroundMargin, gridLineWidth); + + if (m_cachedIsGridEnabled && m_heightNormalizer) { + ShaderHelper *lineShader = m_backgroundShader; + // Bind line shader + lineShader->bind(); + + // Set unchanging shader bindings + QVector3D lineColor = Utils::vectorFromColor(m_cachedTheme.m_gridLine); + lineShader->setUniformValue(lineShader->lightP(), lightPos); + lineShader->setUniformValue(lineShader->view(), viewMatrix); + lineShader->setUniformValue(lineShader->color(), lineColor); + lineShader->setUniformValue(lineShader->ambientS(), m_cachedTheme.m_ambientStrength); + + // Rows (= Z) + if (m_axisCacheZ.segmentCount() > 0) { + // Floor lines + GLfloat lineStep = 2.0f * aspectRatio * m_axisCacheZ.subSegmentStep() / m_scaleFactor; + GLfloat linePos = m_scaleZ + zComp; // Start line + int lastSegment = m_axisCacheZ.subSegmentCount() * m_axisCacheZ.segmentCount(); + + for (int segment = 0; segment <= lastSegment; segment++) { + QMatrix4x4 modelMatrix; + QMatrix4x4 MVPMatrix; + QMatrix4x4 depthMVPMatrix; + QMatrix4x4 itModelMatrix; + + if (m_yFlipped) + modelMatrix.translate(0.0f, backgroundMargin, linePos); + else + modelMatrix.translate(0.0f, -backgroundMargin, linePos); + + modelMatrix.scale(gridLineScaleX); + itModelMatrix.scale(gridLineScaleX); + + // If we're viewing from below, grid line object must be flipped + if (m_yFlipped) + modelMatrix.rotate(180.0f, 1.0, 0.0, 0.0); + + MVPMatrix = projectionViewMatrix * modelMatrix; + depthMVPMatrix = depthProjectionViewMatrix * modelMatrix; + + // Set the rest of the shader bindings + lineShader->setUniformValue(lineShader->model(), modelMatrix); + lineShader->setUniformValue(lineShader->nModel(), + itModelMatrix.inverted().transposed()); + lineShader->setUniformValue(lineShader->MVP(), MVPMatrix); + +#if !defined(QT_OPENGL_ES_2) + if (m_cachedShadowQuality > QDataVis::ShadowQualityNone) { + // Set shadow shader bindings + lineShader->setUniformValue(lineShader->shadowQ(), m_shadowQualityToShader); + lineShader->setUniformValue(lineShader->depth(), depthMVPMatrix); + lineShader->setUniformValue(lineShader->lightS(), adjustedLightStrength); + + // Draw the object + m_drawer->drawObject(lineShader, m_gridLineObj, 0, m_depthTexture); + } else +#endif + { + // Set shadowless shader bindings + lineShader->setUniformValue(lineShader->lightS(), + m_cachedTheme.m_lightStrength); + + // Draw the object + m_drawer->drawObject(lineShader, m_gridLineObj); + } + linePos -= lineStep; + } + + // Side wall lines + GLfloat lineXTrans = m_scaleXWithBackground; + linePos = m_scaleZ + zComp; // Start line + + if (!m_xFlipped) + lineXTrans = -lineXTrans; + + for (int segment = 0; segment <= lastSegment; segment++) { + QMatrix4x4 modelMatrix; + QMatrix4x4 MVPMatrix; + QMatrix4x4 depthMVPMatrix; + QMatrix4x4 itModelMatrix; + + modelMatrix.translate(lineXTrans, 0.0f, linePos); + modelMatrix.scale(gridLineScaleY); + itModelMatrix.scale(gridLineScaleY); + + MVPMatrix = projectionViewMatrix * modelMatrix; + depthMVPMatrix = depthProjectionViewMatrix * modelMatrix; + + // Set the rest of the shader bindings + lineShader->setUniformValue(lineShader->model(), modelMatrix); + lineShader->setUniformValue(lineShader->nModel(), + itModelMatrix.inverted().transposed()); + lineShader->setUniformValue(lineShader->MVP(), MVPMatrix); + +#if !defined(QT_OPENGL_ES_2) + if (m_cachedShadowQuality > QDataVis::ShadowQualityNone) { + // Set shadow shader bindings + lineShader->setUniformValue(lineShader->shadowQ(), m_shadowQualityToShader); + lineShader->setUniformValue(lineShader->depth(), depthMVPMatrix); + lineShader->setUniformValue(lineShader->lightS(), + adjustedLightStrength); + + // Draw the object + m_drawer->drawObject(lineShader, m_gridLineObj, 0, m_depthTexture); + } else +#endif + { + // Set shadowless shader bindings + lineShader->setUniformValue(lineShader->lightS(), + m_cachedTheme.m_lightStrength); + + // Draw the object + m_drawer->drawObject(lineShader, m_gridLineObj); + } + linePos -= lineStep; + } + } + + // Columns (= X) + if (m_axisCacheX.segmentCount() > 0) { + // Floor lines + GLfloat lineStep = -2.0f * aspectRatio * m_axisCacheX.subSegmentStep() / m_scaleFactor; + GLfloat linePos = m_scaleX; + int lastSegment = m_axisCacheX.subSegmentCount() * m_axisCacheX.segmentCount(); + + for (int segment = 0; segment <= lastSegment; segment++) { + QMatrix4x4 modelMatrix; + QMatrix4x4 MVPMatrix; + QMatrix4x4 depthMVPMatrix; + QMatrix4x4 itModelMatrix; + + if (m_yFlipped) + modelMatrix.translate(linePos, backgroundMargin, zComp); + else + modelMatrix.translate(linePos, -backgroundMargin, zComp); + + modelMatrix.scale(gridLineScaleZ); + itModelMatrix.scale(gridLineScaleZ); + + // If we're viewing from below, grid line object must be flipped + if (m_yFlipped) + modelMatrix.rotate(180.0f, 1.0, 0.0, 0.0); + + MVPMatrix = projectionViewMatrix * modelMatrix; + depthMVPMatrix = depthProjectionViewMatrix * modelMatrix; + + // Set the rest of the shader bindings + lineShader->setUniformValue(lineShader->model(), modelMatrix); + lineShader->setUniformValue(lineShader->nModel(), + itModelMatrix.inverted().transposed()); + lineShader->setUniformValue(lineShader->MVP(), MVPMatrix); + +#if !defined(QT_OPENGL_ES_2) + if (m_cachedShadowQuality > QDataVis::ShadowQualityNone) { + // Set shadow shader bindings + lineShader->setUniformValue(lineShader->shadowQ(), m_shadowQualityToShader); + lineShader->setUniformValue(lineShader->depth(), depthMVPMatrix); + lineShader->setUniformValue(lineShader->lightS(), adjustedLightStrength); + + // Draw the object + m_drawer->drawObject(lineShader, m_gridLineObj, 0, m_depthTexture); + } else +#endif + { + // Set shadowless shader bindings + lineShader->setUniformValue(lineShader->lightS(), + m_cachedTheme.m_lightStrength); + + // Draw the object + m_drawer->drawObject(lineShader, m_gridLineObj); + } + linePos += lineStep; + } + + // Back wall lines + GLfloat lineZTrans = m_scaleZWithBackground + zComp; + linePos = m_scaleX; + + if (!m_zFlipped) + lineZTrans = -lineZTrans + zComp + zComp; + + for (int segment = 0; segment <= lastSegment; segment++) { + QMatrix4x4 modelMatrix; + QMatrix4x4 MVPMatrix; + QMatrix4x4 depthMVPMatrix; + QMatrix4x4 itModelMatrix; + + modelMatrix.translate(linePos, 0.0f, lineZTrans); + modelMatrix.scale(gridLineScaleY); + itModelMatrix.scale(gridLineScaleY); + + MVPMatrix = projectionViewMatrix * modelMatrix; + depthMVPMatrix = depthProjectionViewMatrix * modelMatrix; + + // Set the rest of the shader bindings + lineShader->setUniformValue(lineShader->model(), modelMatrix); + lineShader->setUniformValue(lineShader->nModel(), + itModelMatrix.inverted().transposed()); + lineShader->setUniformValue(lineShader->MVP(), MVPMatrix); + +#if !defined(QT_OPENGL_ES_2) + if (m_cachedShadowQuality > QDataVis::ShadowQualityNone) { + // Set shadow shader bindings + lineShader->setUniformValue(lineShader->shadowQ(), m_shadowQualityToShader); + lineShader->setUniformValue(lineShader->depth(), depthMVPMatrix); + lineShader->setUniformValue(lineShader->lightS(), adjustedLightStrength); + + // Draw the object + m_drawer->drawObject(lineShader, m_gridLineObj, 0, m_depthTexture); + } else +#endif + { + // Set shadowless shader bindings + lineShader->setUniformValue(lineShader->lightS(), + m_cachedTheme.m_lightStrength); + + // Draw the object + m_drawer->drawObject(lineShader, m_gridLineObj); + } + linePos += lineStep; + } + } + + // Horizontal wall lines + if (m_axisCacheY.segmentCount() > 0) { + // Back wall + GLfloat lineStep = 2.0f * m_axisCacheY.subSegmentStep() / m_heightNormalizer; + GLfloat linePos = -1.0f; + int lastSegment = m_axisCacheY.subSegmentCount() * m_axisCacheY.segmentCount(); + + GLfloat lineZTrans = m_scaleZWithBackground + zComp; + + if (!m_zFlipped) + lineZTrans = -lineZTrans + zComp + zComp; + + for (int segment = 0; segment <= lastSegment; segment++) { + QMatrix4x4 modelMatrix; + QMatrix4x4 MVPMatrix; + QMatrix4x4 depthMVPMatrix; + QMatrix4x4 itModelMatrix; + + modelMatrix.translate(0.0f, linePos, lineZTrans); + + modelMatrix.scale(gridLineScaleX); + itModelMatrix.scale(gridLineScaleX); + + MVPMatrix = projectionViewMatrix * modelMatrix; + depthMVPMatrix = depthProjectionViewMatrix * modelMatrix; + + // Set the rest of the shader bindings + lineShader->setUniformValue(lineShader->model(), modelMatrix); + lineShader->setUniformValue(lineShader->nModel(), + itModelMatrix.inverted().transposed()); + lineShader->setUniformValue(lineShader->MVP(), MVPMatrix); + +#if !defined(QT_OPENGL_ES_2) + if (m_cachedShadowQuality > QDataVis::ShadowQualityNone) { + // Set shadow shader bindings + lineShader->setUniformValue(lineShader->shadowQ(), m_shadowQualityToShader); + lineShader->setUniformValue(lineShader->depth(), depthMVPMatrix); + lineShader->setUniformValue(lineShader->lightS(), adjustedLightStrength); + + // Draw the object + m_drawer->drawObject(lineShader, m_gridLineObj, 0, m_depthTexture); + } else +#endif + { + // Set shadowless shader bindings + lineShader->setUniformValue(lineShader->lightS(), + m_cachedTheme.m_lightStrength); + + // Draw the object + m_drawer->drawObject(lineShader, m_gridLineObj); + } + linePos += lineStep; + } + + // Side wall + linePos = -1.0f; + lastSegment = m_axisCacheY.subSegmentCount() * m_axisCacheY.segmentCount(); + GLfloat lineXTrans = m_scaleXWithBackground; + + if (!m_xFlipped) + lineXTrans = -lineXTrans; + + for (int segment = 0; segment <= lastSegment; segment++) { + QMatrix4x4 modelMatrix; + QMatrix4x4 MVPMatrix; + QMatrix4x4 depthMVPMatrix; + QMatrix4x4 itModelMatrix; + + modelMatrix.translate(lineXTrans, linePos, zComp); + + modelMatrix.scale(gridLineScaleZ); + itModelMatrix.scale(gridLineScaleZ); + + MVPMatrix = projectionViewMatrix * modelMatrix; + depthMVPMatrix = depthProjectionViewMatrix * modelMatrix; + + // Set the rest of the shader bindings + lineShader->setUniformValue(lineShader->model(), modelMatrix); + lineShader->setUniformValue(lineShader->nModel(), + itModelMatrix.inverted().transposed()); + lineShader->setUniformValue(lineShader->MVP(), MVPMatrix); + +#if !defined(QT_OPENGL_ES_2) + if (m_cachedShadowQuality > QDataVis::ShadowQualityNone) { + // Set shadow shader bindings + lineShader->setUniformValue(lineShader->shadowQ(), m_shadowQualityToShader); + lineShader->setUniformValue(lineShader->depth(), depthMVPMatrix); + lineShader->setUniformValue(lineShader->lightS(), adjustedLightStrength); + + // Draw the object + m_drawer->drawObject(lineShader, m_gridLineObj, 0, m_depthTexture); + } else +#endif + { + // Set shadowless shader bindings + lineShader->setUniformValue(lineShader->lightS(), + m_cachedTheme.m_lightStrength); + + // Draw the object + m_drawer->drawObject(lineShader, m_gridLineObj); + } + linePos += lineStep; + } + } + + // Release line shader + lineShader->release(); + } + + // Draw axis labels + m_labelShader->bind(); + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + // Z Labels + QVector3D positionZComp(0.0f, 0.0f, zComp); + if (m_axisCacheZ.segmentCount() > 0) { + GLfloat posStep = 2.0f * aspectRatio * m_axisCacheZ.segmentStep() / m_scaleFactor; + GLfloat labelPos = m_scaleZ + zComp; + int lastSegment = m_axisCacheZ.segmentCount(); + int labelNbr = 0; + GLfloat labelXTrans = m_scaleXWithBackground + labelMargin; + GLfloat labelYTrans = -backgroundMargin; + GLfloat rotLabelX = -90.0f; + GLfloat rotLabelY = 0.0f; + GLfloat rotLabelZ = 0.0f; + Qt::AlignmentFlag alignment = Qt::AlignRight; + if (m_zFlipped) + rotLabelY = 180.0f; + if (m_xFlipped) { + labelXTrans = -labelXTrans; + alignment = Qt::AlignLeft; + } + if (m_yFlipped) { + rotLabelZ += 180.0f; + rotLabelY += 180.0f; + labelYTrans = -labelYTrans; + } + QVector3D labelTrans = QVector3D(labelXTrans, + labelYTrans, + labelPos); + QVector3D rotation(rotLabelX, rotLabelY, rotLabelZ); + + for (int segment = 0; segment <= lastSegment; segment++) { + if (m_axisCacheZ.labelItems().size() > labelNbr) { + labelTrans.setZ(labelPos); + + // Draw the label here + m_dummyRenderItem.setTranslation(labelTrans); + const LabelItem &axisLabelItem = *m_axisCacheZ.labelItems().at(labelNbr); + + m_drawer->drawLabel(m_dummyRenderItem, axisLabelItem, viewMatrix, projectionMatrix, + positionZComp, rotation, 0, m_cachedSelectionMode, + m_labelShader, m_labelObj, m_cachedScene->activeCamera(), + true, true, Drawer::LabelMid, alignment); + } + labelNbr++; + labelPos -= posStep; + } + } + // X Labels + if (m_axisCacheX.segmentCount() > 0) { + GLfloat posStep = 2.0f * aspectRatio * m_axisCacheX.segmentStep() / m_scaleFactor; + GLfloat labelPos = -m_scaleX; + int lastSegment = m_axisCacheX.segmentCount(); + + int labelNbr = 0; + GLfloat labelZTrans = m_scaleZWithBackground + labelMargin; + GLfloat labelYTrans = -backgroundMargin; + GLfloat rotLabelX = -90.0f; + GLfloat rotLabelY = 90.0f; + GLfloat rotLabelZ = 0.0f; + Qt::AlignmentFlag alignment = Qt::AlignLeft; + if (m_xFlipped) + rotLabelY = -90.0f; + if (m_zFlipped) { + labelZTrans = -labelZTrans; + alignment = Qt::AlignRight; + } + if (m_yFlipped) { + rotLabelZ += 180.0f; + rotLabelY += 180.0f; + labelYTrans = -labelYTrans; + } + QVector3D labelTrans = QVector3D(labelPos, + labelYTrans, + labelZTrans + zComp); + QVector3D rotation(rotLabelX, rotLabelY, rotLabelZ); + + for (int segment = 0; segment <= lastSegment; segment++) { + if (m_axisCacheX.labelItems().size() > labelNbr) { + // Draw the label here + labelTrans.setX(labelPos); + m_dummyRenderItem.setTranslation(labelTrans); + const LabelItem &axisLabelItem = *m_axisCacheX.labelItems().at(labelNbr); + + m_drawer->drawLabel(m_dummyRenderItem, axisLabelItem, viewMatrix, projectionMatrix, + positionZComp, rotation, 0, m_cachedSelectionMode, + m_labelShader, m_labelObj, m_cachedScene->activeCamera(), + true, true, Drawer::LabelMid, alignment); + } + labelNbr++; + labelPos += posStep; + } + } + // Y Labels + if (m_axisCacheY.segmentCount() > 0) { + GLfloat posStep = 2.0f * m_axisCacheY.segmentStep() / m_heightNormalizer; + GLfloat labelPos = -1.0f; + int labelNbr = 0; + GLfloat labelXTrans = m_scaleXWithBackground; + GLfloat labelZTrans = m_scaleZWithBackground; + + GLfloat labelMarginXTrans = labelMargin; + GLfloat labelMarginZTrans = labelMargin; + GLfloat rotLabelX = 0.0f; + GLfloat rotLabelY = -90.0f; + GLfloat rotLabelZ = 0.0f; + Qt::AlignmentFlag alignment = Qt::AlignLeft; + if (!m_xFlipped) { + labelXTrans = -labelXTrans; + labelMarginXTrans = -labelMargin; + rotLabelY = 90.0f; + } + if (m_zFlipped) { + labelZTrans = -labelZTrans; + labelMarginZTrans = -labelMargin; + alignment = Qt::AlignRight; + } + + // Back wall + QVector3D rotation(rotLabelX, rotLabelY, rotLabelZ); + + for (int segment = 0; segment <= m_axisCacheY.segmentCount(); segment++) { + if (m_axisCacheY.labelItems().size() > labelNbr) { + const LabelItem &axisLabelItem = *m_axisCacheY.labelItems().at(labelNbr); + + // Side wall + QVector3D labelTrans = QVector3D(labelXTrans, labelPos, + labelZTrans + labelMarginZTrans + zComp); + if (m_xFlipped) + rotation.setY(-90.0f); + else + rotation.setY(90.0f); + if (m_zFlipped) + alignment = Qt::AlignRight; + else + alignment = Qt::AlignLeft; + + // Draw the label here + m_dummyRenderItem.setTranslation(labelTrans); + m_drawer->drawLabel(m_dummyRenderItem, axisLabelItem, viewMatrix, projectionMatrix, + positionZComp, rotation, 0, m_cachedSelectionMode, + m_labelShader, m_labelObj, m_cachedScene->activeCamera(), + true, true, Drawer::LabelMid, alignment); + + // Back wall + if (m_xFlipped) + alignment = Qt::AlignLeft; + else + alignment = Qt::AlignRight; + if (m_zFlipped) + rotation.setY(180.0f); + else + rotation.setY(0.0f); + + labelTrans = QVector3D(-labelXTrans - labelMarginXTrans, labelPos, + -labelZTrans + zComp); + + // Draw the label here + m_dummyRenderItem.setTranslation(labelTrans); + m_drawer->drawLabel(m_dummyRenderItem, axisLabelItem, viewMatrix, projectionMatrix, + positionZComp, rotation, 0, m_cachedSelectionMode, + m_labelShader, m_labelObj, m_cachedScene->activeCamera(), + true, true, Drawer::LabelMid, alignment); + } + labelNbr++; + labelPos += posStep; + } + } + + glDisable(GL_TEXTURE_2D); + + glDisable(GL_BLEND); + + // Release label shader + m_labelShader->release(); + + // Selection handling + if (m_selectionModeChanged || selectionDirty) { + if (selectionDirty) + m_cachedSelectionId = selectionId; + if (m_cachedSelectionMode == QDataVis::SelectionModeNone) { + m_cachedSelectionId = 0; + m_selectionActive = false; + } + if (m_cachedSelectionMode == QDataVis::SelectionModeItem) { + if (m_cachedSelectionId) + surfacePointSelected(m_cachedSelectionId); + else + m_selectionActive = false; + } + if (m_cachedSelectionMode == QDataVis::SelectionModeSliceRow + || m_cachedSelectionMode == QDataVis::SelectionModeSliceColumn) { + if (m_cachedSelectionId) { + updateSliceDataModel(m_cachedSelectionId); + m_cachedScene->setSlicingActive(true); + + surfacePointSelected(m_cachedSelectionId); + + emit needRender(); + } + } + + m_selectionModeChanged = false; + } + if (m_controller->inputState() == QDataVis::InputStateOnOverview) { + if (m_cachedIsSlicingActivated) { + m_cachedScene->setSlicingActive(false); + m_selectionActive = false; + m_cachedSelectionId = 0; + } + } +} + +void Surface3DRenderer::updateSurfaceGradient(const QLinearGradient &gradient) +{ + QImage image(QSize(1, 1000), QImage::Format_RGB32); + QPainter pmp(&image); + pmp.setBrush(QBrush(gradient)); + pmp.setPen(Qt::NoPen); + pmp.drawRect(0, 0, 1, 1000); + + if (m_gradientTexture) { + m_textureHelper->deleteTexture(&m_gradientTexture); + m_gradientTexture = 0; + } + + m_gradientTexture = m_textureHelper->create2DTexture(image, false, true); +} + +// This one needs to be called when the data size changes +void Surface3DRenderer::updateSelectionTexture() +{ + // Create the selection ID image. Each grid corner gets 2x2 pixel area of + // ID color so that each vertex (data point) has 4x4 pixel area of ID color + int idImageWidth = (m_sampleSpace.width() - 1) * 4; + int idImageHeight = (m_sampleSpace.height() - 1) * 4; + int stride = idImageWidth * 4 * sizeof(uchar); // 4 = number of color components (rgba) + + uchar *bits = new uchar[idImageWidth * idImageHeight * 4 * sizeof(uchar)]; + uint id = 1; + for (int i = 0; i < idImageHeight; i += 4) { + for (int j = 0; j < idImageWidth; j += 4) { + int p = (i * idImageWidth + j) * 4; + uchar r, g, b, a; + idToRGBA(id, &r, &g, &b, &a); + fillIdCorner(&bits[p], r, g, b, a, stride); + + idToRGBA(id + 1, &r, &g, &b, &a); + fillIdCorner(&bits[p + 8], r, g, b, a, stride); + + idToRGBA(id + m_sampleSpace.width(), &r, &g, &b, &a); + fillIdCorner(&bits[p + 2 * stride], r, g, b, a, stride); + + idToRGBA(id + m_sampleSpace.width() + 1, &r, &g, &b, &a); + fillIdCorner(&bits[p + 2 * stride + 8], r, g, b, a, stride); + + id++; + } + id++; + } + + // If old texture exists, delete it + if (m_selectionTexture) { + m_textureHelper->deleteTexture(&m_selectionTexture); + m_selectionTexture = 0; + } + + // Move the ID image (bits) to the texture + QImage image = QImage(bits, idImageWidth, idImageHeight, QImage::Format_RGB32); + m_selectionTexture = m_textureHelper->create2DTexture(image, false, false, false); + + // Release the temp bits allocation + delete[] bits; +} + +void Surface3DRenderer::initSelectionBuffer() +{ + // Create the result selection texture and buffers + if (m_selectionResultTexture) { + m_textureHelper->deleteTexture(&m_selectionResultTexture); + m_selectionResultTexture = 0; + } + + m_selectionResultTexture = m_textureHelper->createSelectionTexture(m_mainViewPort.size(), + m_selectionFrameBuffer, + m_selectionDepthBuffer); +} + +void Surface3DRenderer::fillIdCorner(uchar *p, uchar r, uchar g, uchar b, uchar a, int stride) +{ + p[0] = r; + p[1] = g; + p[2] = b; + p[3] = a; + p[4] = r; + p[5] = g; + p[6] = b; + p[7] = a; + p[stride + 0] = r; + p[stride + 1] = g; + p[stride + 2] = b; + p[stride + 3] = a; + p[stride + 4] = r; + p[stride + 5] = g; + p[stride + 6] = b; + p[stride + 7] = a; +} + +void Surface3DRenderer::idToRGBA(uint id, uchar *r, uchar *g, uchar *b, uchar *a) +{ + *r = id & ID_TO_RGBA_MASK; + *g = (id >> 8) & ID_TO_RGBA_MASK; + *b = (id >> 16) & ID_TO_RGBA_MASK; + *a = (id >> 24) & ID_TO_RGBA_MASK; +} + +void Surface3DRenderer::updateTextures() +{ + updateSurfaceGradient(m_cachedTheme.m_surfaceGradient); +} + +void Surface3DRenderer::calculateSceneScalingFactors() +{ + // Calculate scene scaling and translation factors + m_heightNormalizer = GLfloat(m_axisCacheY.max() - m_axisCacheY.min()); + m_areaSize.setHeight(m_axisCacheZ.max() - m_axisCacheZ.min()); + m_areaSize.setWidth(m_axisCacheX.max() - m_axisCacheX.min()); + m_scaleFactor = qMax(m_areaSize.width(), m_areaSize.height()); +#ifndef USE_UNIFORM_SCALING // Use this if we want to use autoscaling for x and z + m_scaleX = aspectRatio * m_areaSize.width() / m_scaleFactor; + m_scaleZ = aspectRatio * m_areaSize.height() / m_scaleFactor; + m_scaleXWithBackground = m_scaleX * backgroundMargin; + m_scaleZWithBackground = m_scaleZ * backgroundMargin; +#else // ..and this if we want uniform scaling based on largest dimension + m_scaleX = aspectRatio / m_scaleFactor; + m_scaleZ = aspectRatio / m_scaleFactor; + m_scaleXWithBackground = aspectRatio * backgroundMargin; + m_scaleZWithBackground = aspectRatio * backgroundMargin; +#endif +} + +bool Surface3DRenderer::updateSmoothStatus(bool enable) +{ + if (!enable && !m_flatSupported) { + qWarning() << "Warning: Flat qualifier not supported on your platform's GLSL language." + " Requires at least GLSL version 1.5."; + enable = true; + } + + bool changed = false; + if (enable != m_cachedSmoothSurface) { + m_cachedSmoothSurface = enable; + changed = true; + initSurfaceShaders(); + } + + // If no surface object created yet, don't try to update the object + if (m_surfaceObj && changed && m_sampleSpace.width() >= 2 && m_sampleSpace.height() >= 2) { + if (m_cachedSmoothSurface) { + m_surfaceObj->setUpSmoothData(m_dataArray, m_sampleSpace, m_heightNormalizer, + m_axisCacheY.min(), true); + } else { + m_surfaceObj->setUpData(m_dataArray, m_sampleSpace, m_heightNormalizer, + m_axisCacheY.min(), true); + } + } + + return m_cachedSmoothSurface; +} + +void Surface3DRenderer::updateSelectionMode(QDataVis::SelectionMode mode) +{ + if (mode != m_cachedSelectionMode) + m_selectionModeChanged = true; + + Abstract3DRenderer::updateSelectionMode(mode); +} + +void Surface3DRenderer::updateSurfaceGridStatus(bool enable) +{ + m_cachedSurfaceGridOn = enable; +} + +void Surface3DRenderer::loadBackgroundMesh() +{ + if (m_backgroundObj) + delete m_backgroundObj; + m_backgroundObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/background")); + m_backgroundObj->load(); +} + +void Surface3DRenderer::loadSurfaceObj() +{ + if (m_surfaceObj) + delete m_surfaceObj; + m_surfaceObj = new SurfaceObject(); +} + +void Surface3DRenderer::loadSliceSurfaceObj() +{ + if (m_sliceSurfaceObj) + delete m_sliceSurfaceObj; + m_sliceSurfaceObj = new SurfaceObject(); +} + +void Surface3DRenderer::loadGridLineMesh() +{ + if (m_gridLineObj) + delete m_gridLineObj; + m_gridLineObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/bar")); + m_gridLineObj->load(); +} + +void Surface3DRenderer::handleResize() +{ + if (m_cachedBoundingRect.width() == 0 || m_cachedBoundingRect.height() == 0) + return; + + // Set view port + if (m_cachedIsSlicingActivated) { + m_mainViewPort = QRect(0, + m_cachedBoundingRect.height() - m_cachedBoundingRect.height() / subViewDivider, + m_cachedBoundingRect.width() / subViewDivider, + m_cachedBoundingRect.height() / subViewDivider); + } else { + m_mainViewPort = QRect(0, 0, m_cachedBoundingRect.width(), m_cachedBoundingRect.height()); + } + m_sliceViewPort = QRect(0, 0, m_cachedBoundingRect.width(), m_cachedBoundingRect.height()); + + if (m_selectionPointer) { + if (m_cachedIsSlicingActivated) + m_selectionPointer->updateBoundingRect(m_sliceViewPort); + else + m_selectionPointer->updateBoundingRect(m_mainViewPort); + } + + Abstract3DRenderer::handleResize(); +} + +void Surface3DRenderer::surfacePointSelected(int id) +{ + int column = (id - 1) % m_sampleSpace.width(); + int row = (id - 1) / m_sampleSpace.width(); + + if (row < 0 || column < 0 || m_dataArray.size() < row || m_dataArray.at(row)->size() < column) + return; + + qreal value = qreal(m_dataArray.at(row)->at(column).y()); + + if (!m_selectionPointer) + m_selectionPointer = new SelectionPointer(m_drawer); + + QVector3D pos; + if (m_cachedSelectionMode == QDataVis::SelectionModeSliceRow) { + pos = m_sliceSurfaceObj->vertexAt(column, 0); + pos *= QVector3D(m_surfaceScaleX, 1.0f, 0.0f); + pos += QVector3D(m_surfaceOffsetX, 0.0f, 0.0f); + m_selectionPointer->updateBoundingRect(m_sliceViewPort); + m_selectionPointer->updateSliceData(true, m_autoScaleAdjustment); + } else if (m_cachedSelectionMode == QDataVis::SelectionModeSliceColumn) { + pos = m_sliceSurfaceObj->vertexAt(row, 0); + pos *= QVector3D(m_surfaceScaleZ, 1.0f, 0.0f); + pos += QVector3D(-m_surfaceOffsetZ, 0.0f, 0.0f); + m_selectionPointer->updateBoundingRect(m_sliceViewPort); + m_selectionPointer->updateSliceData(true, m_autoScaleAdjustment); + } else { + pos = m_surfaceObj->vertexAt(column, row); + pos *= QVector3D(m_surfaceScaleX, 1.0f, m_surfaceScaleZ);; + pos += QVector3D(m_surfaceOffsetX, 0.0f, m_surfaceOffsetZ); + m_selectionPointer->updateBoundingRect(m_mainViewPort); + m_selectionPointer->updateSliceData(false, m_autoScaleAdjustment); + } + + m_selectionPointer->setPosition(pos); + m_selectionPointer->setLabel(createSelectionLabel(value, column, row)); + m_selectionPointer->updateScene(m_cachedScene); + + //Put the selection pointer flag active + m_selectionActive = true; +} + +QString Surface3DRenderer::createSelectionLabel(qreal value, int column, int row) +{ + QString labelText = itemLabelFormat(); + static const QString xTitleTag(QStringLiteral("@xTitle")); + static const QString yTitleTag(QStringLiteral("@yTitle")); + static const QString zTitleTag(QStringLiteral("@zTitle")); + static const QString xLabelTag(QStringLiteral("@xLabel")); + static const QString yLabelTag(QStringLiteral("@yLabel")); + static const QString zLabelTag(QStringLiteral("@zLabel")); + + labelText.replace(xTitleTag, m_axisCacheX.title()); + labelText.replace(yTitleTag, m_axisCacheY.title()); + labelText.replace(zTitleTag, m_axisCacheZ.title()); + + if (labelText.contains(xLabelTag)) { + QString labelFormat = m_axisCacheX.labelFormat(); + if (labelFormat.isEmpty()) + labelFormat = Utils::defaultLabelFormat(); + QString valueLabelText = generateValueLabel(labelFormat, + m_dataArray.at(row)->at(column).x()); + labelText.replace(xLabelTag, valueLabelText); + } + if (labelText.contains(yLabelTag)) { + QString labelFormat = m_axisCacheY.labelFormat(); + if (labelFormat.isEmpty()) + labelFormat = Utils::defaultLabelFormat(); + QString valueLabelText = generateValueLabel(labelFormat, value); + labelText.replace(yLabelTag, valueLabelText); + } + if (labelText.contains(zLabelTag)) { + QString labelFormat = m_axisCacheZ.labelFormat(); + if (labelFormat.isEmpty()) + labelFormat = Utils::defaultLabelFormat(); + QString valueLabelText = generateValueLabel(labelFormat, + m_dataArray.at(row)->at(column).z()); + labelText.replace(zLabelTag, valueLabelText); + } + + return labelText; +} + +void Surface3DRenderer::loadMeshFile() +{ + qDebug() << __FUNCTION__ << "should we do something"; +} + +void Surface3DRenderer::updateShadowQuality(QDataVis::ShadowQuality quality) +{ + qWarning() << "Shadows have been disabled for Q3DSurface in technology preview"; + m_cachedShadowQuality = QDataVis::ShadowQualityNone; //quality; + switch (quality) { + case QDataVis::ShadowQualityLow: + m_shadowQualityToShader = 33.3f; + m_shadowQualityMultiplier = 1; + break; + case QDataVis::ShadowQualityMedium: + m_shadowQualityToShader = 100.0f; + m_shadowQualityMultiplier = 3; + break; + case QDataVis::ShadowQualityHigh: + m_shadowQualityToShader = 200.0f; + m_shadowQualityMultiplier = 5; + break; + case QDataVis::ShadowQualitySoftLow: + m_shadowQualityToShader = 5.0f; + m_shadowQualityMultiplier = 1; + break; + case QDataVis::ShadowQualitySoftMedium: + m_shadowQualityToShader = 10.0f; + m_shadowQualityMultiplier = 3; + break; + case QDataVis::ShadowQualitySoftHigh: + m_shadowQualityToShader = 15.0f; + m_shadowQualityMultiplier = 4; + break; + default: + m_shadowQualityToShader = 0.0f; + m_shadowQualityMultiplier = 1; + break; + } + +#if !defined(QT_OPENGL_ES_2) + updateDepthBuffer(); +#endif +} + +void Surface3DRenderer::updateSlicingActive(bool isSlicing) +{ + if (isSlicing == m_cachedIsSlicingActivated) + return; + + m_cachedIsSlicingActivated = isSlicing; + if (isSlicing) { + m_mainViewPort = QRect(0, m_cachedBoundingRect.height() - m_cachedBoundingRect.height() / subViewDivider, + m_cachedBoundingRect.width() / subViewDivider, m_cachedBoundingRect.height() / subViewDivider); + if (m_depthTexture) { + m_textureHelper->deleteTexture(&m_depthTexture); + m_depthTexture = 0; + } + } else { + m_mainViewPort = QRect(0, 0, this->m_cachedBoundingRect.width(), + this->m_cachedBoundingRect.height()); + initSelectionBuffer(); // We need to re-init selection buffer in case there has been a resize +#if !defined(QT_OPENGL_ES_2) + updateDepthBuffer(); // Re-init depth buffer as well +#endif + } +} + +void Surface3DRenderer::loadLabelMesh() +{ + if (m_labelObj) + delete m_labelObj; + m_labelObj = new ObjectHelper(QStringLiteral(":/defaultMeshes/label")); + m_labelObj->load(); +} + +void Surface3DRenderer::initShaders(const QString &vertexShader, const QString &fragmentShader) +{ + if (m_shader) + delete m_shader; + m_shader = new ShaderHelper(this, vertexShader, fragmentShader); + m_shader->initialize(); +} + +void Surface3DRenderer::initBackgroundShaders(const QString &vertexShader, + const QString &fragmentShader) +{ + if (m_backgroundShader) + delete m_backgroundShader; + m_backgroundShader = new ShaderHelper(this, vertexShader, fragmentShader); + m_backgroundShader->initialize(); +} + +void Surface3DRenderer::initSelectionShaders() +{ + if (m_selectionShader) + delete m_selectionShader; + m_selectionShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexLabel"), + QStringLiteral(":/shaders/fragmentLabel")); + m_selectionShader->initialize(); +} + +void Surface3DRenderer::initSurfaceShaders() +{ + if (m_surfaceShader) + delete m_surfaceShader; + +#if !defined(QT_OPENGL_ES_2) + if (m_cachedSmoothSurface) { + m_surfaceShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexSurface"), + QStringLiteral(":/shaders/fragmentSurface")); + } else { + m_surfaceShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexSurfaceFlat"), + QStringLiteral(":/shaders/fragmentSurfaceFlat")); + } +#else + m_surfaceShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexSurface"), + QStringLiteral(":/shaders/fragmentSurfaceES2")); +#endif + m_surfaceShader->initialize(); + + if (m_surfaceGridShader) + delete m_surfaceGridShader; + + m_surfaceGridShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexSurfaceGrid"), + QStringLiteral(":/shaders/fragmentSurfaceGrid")); + + m_surfaceGridShader->initialize(); +} + +void Surface3DRenderer::initLabelShaders(const QString &vertexShader, const QString &fragmentShader) +{ + if (m_labelShader) + delete m_labelShader; + m_labelShader = new ShaderHelper(this, vertexShader, fragmentShader); + m_labelShader->initialize(); +} + +#if !defined(QT_OPENGL_ES_2) +void Surface3DRenderer::initDepthShader() +{ + // TODO: Implement a depth shader for surface after technology preview + if (m_depthShader) + delete m_depthShader; + m_depthShader = new ShaderHelper(this, QStringLiteral(":/shaders/vertexDepth"), + QStringLiteral(":/shaders/fragmentDepth")); + m_depthShader->initialize(); +} + +void Surface3DRenderer::updateDepthBuffer() +{ + if (m_depthTexture) { + m_textureHelper->deleteTexture(&m_depthTexture); + m_depthTexture = 0; + } + + if (m_cachedShadowQuality > QDataVis::ShadowQualityNone) { + m_depthTexture = m_textureHelper->createDepthTexture(m_mainViewPort.size(), + m_depthFrameBuffer, + m_shadowQualityMultiplier); + if (!m_depthTexture) { + switch (m_cachedShadowQuality) { + case QDataVis::ShadowQualityHigh: + qWarning("Creating high quality shadows failed. Changing to medium quality."); + (void)m_controller->setShadowQuality(QDataVis::ShadowQualityMedium); + updateShadowQuality(QDataVis::ShadowQualityMedium); + break; + case QDataVis::ShadowQualityMedium: + qWarning("Creating medium quality shadows failed. Changing to low quality."); + (void)m_controller->setShadowQuality(QDataVis::ShadowQualityLow); + updateShadowQuality(QDataVis::ShadowQualityLow); + break; + case QDataVis::ShadowQualityLow: + qWarning("Creating low quality shadows failed. Switching shadows off."); + (void)m_controller->setShadowQuality(QDataVis::ShadowQualityNone); + updateShadowQuality(QDataVis::ShadowQualityNone); + break; + case QDataVis::ShadowQualitySoftHigh: + qWarning("Creating soft high quality shadows failed. Changing to soft medium quality."); + (void)m_controller->setShadowQuality(QDataVis::ShadowQualitySoftMedium); + updateShadowQuality(QDataVis::ShadowQualitySoftMedium); + break; + case QDataVis::ShadowQualitySoftMedium: + qWarning("Creating soft medium quality shadows failed. Changing to soft low quality."); + (void)m_controller->setShadowQuality(QDataVis::ShadowQualitySoftLow); + updateShadowQuality(QDataVis::ShadowQualitySoftLow); + break; + case QDataVis::ShadowQualitySoftLow: + qWarning("Creating soft low quality shadows failed. Switching shadows off."); + (void)m_controller->setShadowQuality(QDataVis::ShadowQualityNone); + updateShadowQuality(QDataVis::ShadowQualityNone); + break; + default: + // You'll never get here + break; + } + } + } +} +#endif + +QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavis3d/engine/surface3drenderer_p.h b/src/datavisualization/engine/surface3drenderer_p.h index f2fb120a..e42e820a 100644 --- a/src/datavis3d/engine/surface3drenderer_p.h +++ b/src/datavisualization/engine/surface3drenderer_p.h @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -20,7 +20,7 @@ // W A R N I N G // ------------- // -// This file is not part of the QtDataVis3D API. It exists purely as an +// 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. // @@ -36,12 +36,15 @@ #include <QLinearGradient> #include <QWindow> -#include "datavis3dglobal_p.h" +#include "datavisualizationglobal_p.h" #include "surface3dcontroller_p.h" +#include "abstract3drenderer_p.h" +#include "scatterrenderitem_p.h" +#include "qsurfacedataproxy.h" class QOpenGLShaderProgram; -QT_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVISUALIZATION_BEGIN_NAMESPACE class ShaderHelper; class ObjectHelper; @@ -49,68 +52,56 @@ class SurfaceObject; class TextureHelper; class Theme; class Drawer; -class CameraHelper; +class Q3DScene; +class SelectionPointer; -class QT_DATAVIS3D_EXPORT Surface3dRenderer : public QObject, protected QOpenGLFunctions +class QT_DATAVISUALIZATION_EXPORT Surface3DRenderer : public Abstract3DRenderer { Q_OBJECT public: - enum MousePressType { - MouseNone = 0, - MouseOnScene, - MouseOnOverview, - MouseOnZoom, - MouseRotating, - MouseOnPinch - }; - - Surface3dController *m_controller; - - // Interaction related parameters // TODO: Moved to controller - MousePressType m_mousePressed; - QPoint m_mousePos; - QDataVis::SelectionMode m_selectionMode; + Surface3DController *m_controller; // Visual parameters QRect m_boundingRect; - Theme m_cachedTheme; - QDataVis::LabelTransparency m_labelTransparency; + QDataVis::LabelStyle m_labelStyle; QFont m_font; bool m_isGridEnabled; - bool m_isBackgroundEnabled; - QDataVis::ShadowQuality m_shadowQuality; - bool m_hasNegativeValues; private: - // Data parameters - QList<qreal> m_series; // TODO: TEMP - GLint m_segmentYCount; - GLfloat m_segmentYStep; - GLint m_segmentXCount; - GLint m_segmentZCount; + bool m_cachedIsSlicingActivated; // Internal attributes purely related to how the scene is drawn with GL. QRect m_mainViewPort; QRect m_sliceViewPort; + ShaderHelper *m_shader; + ShaderHelper *m_depthShader; ShaderHelper *m_backgroundShader; ShaderHelper *m_surfaceShader; ShaderHelper *m_surfaceGridShader; ShaderHelper *m_selectionShader; - TextureHelper *m_textureHelper; - bool m_isInitialized; - GLfloat m_yRange; // m_heightNormalizer - GLfloat m_yAdjustment; - GLfloat m_xLength; - GLfloat m_zLength; - GLfloat m_maxDimension; + ShaderHelper *m_labelShader; + GLfloat m_heightNormalizer; GLfloat m_scaleFactor; GLfloat m_scaleX; GLfloat m_scaleZ; - GLfloat m_maxSceneSize; + GLfloat m_scaleXWithBackground; + GLfloat m_scaleZWithBackground; + GLfloat m_surfaceScaleX; + GLfloat m_surfaceScaleZ; + GLfloat m_surfaceOffsetX; + GLfloat m_surfaceOffsetZ; + GLfloat m_minVisibleColumnValue; + GLfloat m_maxVisibleColumnValue; + GLfloat m_minVisibleRowValue; + GLfloat m_maxVisibleRowValue; + GLfloat m_visibleColumnRange; + GLfloat m_visibleRowRange; ObjectHelper *m_backgroundObj; ObjectHelper *m_gridLineObj; + ObjectHelper *m_labelObj; SurfaceObject *m_surfaceObj; + SurfaceObject *m_sliceSurfaceObj; GLuint m_depthTexture; GLuint m_depthFrameBuffer; GLuint m_selectionFrameBuffer; @@ -119,71 +110,76 @@ private: GLuint m_selectionTexture; GLuint m_selectionResultTexture; GLfloat m_shadowQualityToShader; - bool m_querySelection; bool m_cachedSmoothSurface; + bool m_flatSupported; bool m_cachedSurfaceGridOn; - - Drawer *m_drawer; + SelectionPointer *m_selectionPointer; + bool m_selectionActive; + bool m_xFlipped; + bool m_zFlipped; + bool m_yFlipped; + AbstractRenderItem m_dummyRenderItem; + QSurfaceDataArray m_dataArray; + QSurfaceDataArray m_sliceDataArray; + QRect m_sampleSpace; + GLint m_shadowQualityMultiplier; + QSizeF m_areaSize; + uint m_cachedSelectionId; + bool m_selectionModeChanged; + bool m_hasHeightAdjustmentChanged; public: - explicit Surface3dRenderer(Surface3dController *controller); - ~Surface3dRenderer(); + explicit Surface3DRenderer(Surface3DController *controller); + ~Surface3DRenderer(); - void initializeOpenGL(); - void render(CameraHelper *camera, const GLuint defaultFboHandle = 0); + void updateDataModel(QSurfaceDataProxy *dataProxy); + void updateScene(Q3DScene *scene); + void drawSlicedScene(); + void render(GLuint defaultFboHandle = 0); - // TODO: Not thread-safe, needs rethinking how axes create labels - Drawer *drawer() { return m_drawer; } +protected: + void initializeOpenGL(); + virtual void loadMeshFile(); public slots: - void updateTheme(Theme theme); - void updateSmoothStatus(bool enable); + bool updateSmoothStatus(bool enable); void updateSurfaceGridStatus(bool enable); - void updateSurfaceGradient(); - void updateSegmentCount(GLint segmentCount, GLfloat step, GLfloat minimum = 0.0f); - - void getSelection(); - -public: - // Size - const QSize size(); - const QRect boundingRect(); - void setBoundingRect(const QRect boundingRect); - void setWidth(const int width); - int width(); - void setHeight(const int height); - int height(); - void setX(const int x); - int x(); - void setY(const int y); - int y(); - - void handleResize(); + void updateSurfaceGradient(const QLinearGradient &gradient); + void updateSlicingActive(bool isSlicing); + void updateSelectionMode(QDataVis::SelectionMode mode); -#if !defined(QT_OPENGL_ES_2) - void updateDepthBuffer(); -#endif +private: + void updateSliceDataModel(int selectionId); + virtual void updateShadowQuality(QDataVis::ShadowQuality quality); + virtual void updateTextures(); + virtual void initShaders(const QString &vertexShader, const QString &fragmentShader); + QRect calculateSampleRect(const QSurfaceDataArray &array); void loadBackgroundMesh(); void loadGridLineMesh(); + void loadLabelMesh(); void loadSurfaceObj(); - - // TODO: temp - void setXZStuff(GLint segmentXCount, GLint segmentZCount); - void setSeries(QList<qreal> series); - -private: - void drawScene(CameraHelper *camera, const GLuint defaultFboHandle); + void loadSliceSurfaceObj(); + void drawScene(GLuint defaultFboHandle); + void handleResize(); void calculateSceneScalingFactors(); void initBackgroundShaders(const QString &vertexShader, const QString &fragmentShader); + void initLabelShaders(const QString &vertexShader, const QString &fragmentShader); void initSelectionShaders(); void initSurfaceShaders(); + void initSelectionBuffer(); + void initDepthShader(); void updateSelectionTexture(); void idToRGBA(uint id, uchar *r, uchar *g, uchar *b, uchar *a); void fillIdCorner(uchar *p, uchar r, uchar g, uchar b, uchar a, int stride); + void surfacePointSelected(int id); + QString createSelectionLabel(qreal value, int column, int row); +#if !defined(QT_OPENGL_ES_2) + void updateDepthBuffer(); +#endif - Q_DISABLE_COPY(Surface3dRenderer) + Q_DISABLE_COPY(Surface3DRenderer) }; -QT_DATAVIS3D_END_NAMESPACE +QT_DATAVISUALIZATION_END_NAMESPACE #endif // SURFACE3DRENDERER_P_H diff --git a/src/datavisualization/engine/theme.cpp b/src/datavisualization/engine/theme.cpp new file mode 100644 index 00000000..d9f2974a --- /dev/null +++ b/src/datavisualization/engine/theme.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 "theme_p.h" + +#ifdef Q_OS_WIN +#include <windows.h> +#include <stdio.h> +#endif + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +Theme::Theme() + : m_baseColor(QColor(Qt::gray)), + m_heightColor(QColor(Qt::black)), + m_depthColor(QColor(Qt::black)), + m_backgroundColor(QColor(Qt::gray)), + m_windowColor(QColor(Qt::gray)), + m_textColor(QColor(Qt::white)), + m_textBackgroundColor(QColor(0x00, 0x00, 0x00, 0xa0)), + m_gridLine(QColor(Qt::black)), + m_highlightBarColor(QColor(Qt::red)), + m_highlightRowColor(QColor(Qt::darkRed)), + m_highlightColumnColor(QColor(Qt::darkMagenta)), + m_surfaceGradient(QLinearGradient(1, 1000, 0, 0)), + m_lightStrength(4.0f), + m_ambientStrength(0.3f), + m_highlightLightStrength(8.0f), + m_uniformColor(true), + m_labelBorders(false) +{ + // Default values for surface gradient +} + +Theme::~Theme() +{ +} + +QDataVis::Theme Theme::theme() +{ + return m_theme; +} + +void Theme::useTheme(QDataVis::Theme theme) +{ + m_theme = theme; + switch (theme) { + case QDataVis::ThemeQt: { + m_baseColor = QColor(QRgb(0x80c342)); + //m_heightColor = QColor(QRgb(0x)); + //m_depthColor = QColor(QRgb(0x)); + m_backgroundColor = QColor(QRgb(0xffffff)); + m_windowColor = QColor(QRgb(0xffffff)); + m_textColor = QColor(QRgb(0x35322f)); + m_textBackgroundColor = QColor(0xff, 0xff, 0xff, 0x99); + m_gridLine = QColor(QRgb(0xd7d6d5)); + m_highlightBarColor = QColor(QRgb(0x14aaff)); + m_highlightRowColor = QColor(QRgb(0x6400aa)); + m_highlightColumnColor = QColor(QRgb(0x6400aa)); + m_lightStrength = 5.0f; + m_ambientStrength = 0.5f; + m_highlightLightStrength = 5.0f; + m_uniformColor = true; + m_labelBorders = true; + break; + } + case QDataVis::ThemePrimaryColors: { + m_baseColor = QColor(QRgb(0xffe400)); + //m_heightColor = QColor(QRgb(0x)); + //m_depthColor = QColor(QRgb(0x)); + m_backgroundColor = QColor(QRgb(0xffffff)); + m_windowColor = QColor(QRgb(0xffffff)); + m_textColor = QColor(QRgb(0x000000)); + m_textBackgroundColor = QColor(0xff, 0xff, 0xff, 0x99); + m_gridLine = QColor(QRgb(0xd7d6d5)); + m_highlightBarColor = QColor(QRgb(0x27beee)); + m_highlightRowColor = QColor(QRgb(0xee1414)); + m_highlightColumnColor = QColor(QRgb(0xee1414)); + m_lightStrength = 5.0f; + m_ambientStrength = 0.5f; + m_highlightLightStrength = 5.0f; + m_uniformColor = true; + m_labelBorders = false; + break; + } + case QDataVis::ThemeDigia: { + m_baseColor = QColor(QRgb(0xcccccc)); + //m_heightColor = QColor(QRgb(0x)); + //m_depthColor = QColor(QRgb(0x)); + m_backgroundColor = QColor(QRgb(0xffffff)); + m_windowColor = QColor(QRgb(0xffffff)); + m_textColor = QColor(QRgb(0x000000)); + m_textBackgroundColor = QColor(0xff, 0xff, 0xff, 0x80); + m_gridLine = QColor(QRgb(0xd7d6d5)); + m_highlightBarColor = QColor(QRgb(0xfa0000)); + m_highlightRowColor = QColor(QRgb(0x555555)); + m_highlightColumnColor = QColor(QRgb(0x555555)); + m_lightStrength = 5.0f; + m_ambientStrength = 0.5f; + m_highlightLightStrength = 5.0f; + m_uniformColor = false; + m_labelBorders = false; + break; + } + case QDataVis::ThemeStoneMoss: { + m_baseColor = QColor(QRgb(0xbeb32b)); + //m_heightColor = QColor(QRgb(0x)); + //m_depthColor = QColor(QRgb(0x)); + m_backgroundColor = QColor(QRgb(0x4d4d4f)); + m_windowColor = QColor(QRgb(0x4d4d4f)); + m_textColor = QColor(QRgb(0xffffff)); + m_textBackgroundColor = QColor(0x4d, 0x4d, 0x4f, 0xcd); + m_gridLine = QColor(QRgb(0x3e3e40)); + m_highlightBarColor = QColor(QRgb(0xfbf6d6)); + m_highlightRowColor = QColor(QRgb(0x442f20)); + m_highlightColumnColor = QColor(QRgb(0x442f20)); + m_lightStrength = 5.0f; + m_ambientStrength = 0.5f; + m_highlightLightStrength = 5.0f; + m_uniformColor = true; + m_labelBorders = true; + break; + } + case QDataVis::ThemeArmyBlue: { + m_baseColor = QColor(QRgb(0x495f76)); + //m_heightColor = QColor(QRgb(0x)); + //m_depthColor = QColor(QRgb(0x)); + m_backgroundColor = QColor(QRgb(0xd5d6d7)); + m_windowColor = QColor(QRgb(0xd5d6d7)); + m_textColor = QColor(QRgb(0x000000)); + m_textBackgroundColor = QColor(0xd5, 0xd6, 0xd7, 0xcd); + m_gridLine = QColor(QRgb(0xaeadac)); + m_highlightBarColor = QColor(QRgb(0x2aa2f9)); + m_highlightRowColor = QColor(QRgb(0x103753)); + m_highlightColumnColor = QColor(QRgb(0x103753)); + m_lightStrength = 5.0f; + m_ambientStrength = 0.5f; + m_highlightLightStrength = 5.0f; + m_uniformColor = false; + m_labelBorders = false; + break; + } + case QDataVis::ThemeRetro: { + m_baseColor = QColor(QRgb(0x533b23)); + //m_heightColor = QColor(QRgb(0x)); + //m_depthColor = QColor(QRgb(0x)); + m_backgroundColor = QColor(QRgb(0xe9e2ce)); + m_windowColor = QColor(QRgb(0xe9e2ce)); + m_textColor = QColor(QRgb(0x000000)); + m_textBackgroundColor = QColor(0xe9, 0xe2, 0xce, 0xc0); + m_gridLine = QColor(QRgb(0xd0c0b0)); + m_highlightBarColor = QColor(QRgb(0x8ea317)); + m_highlightRowColor = QColor(QRgb(0xc25708)); + m_highlightColumnColor = QColor(QRgb(0xc25708)); + m_lightStrength = 5.0f; + m_ambientStrength = 0.5f; + m_highlightLightStrength = 5.0f; + m_uniformColor = false; + m_labelBorders = false; + break; + } + case QDataVis::ThemeEbony: { + m_baseColor = QColor(QRgb(0xffffff)); + //m_heightColor = QColor(QRgb(0x)); + //m_depthColor = QColor(QRgb(0x)); + m_backgroundColor = QColor(QRgb(0x000000)); + m_windowColor = QColor(QRgb(0x000000)); + m_textColor = QColor(QRgb(0xaeadac)); + m_textBackgroundColor = QColor(0x00, 0x00, 0x00, 0xcd); + m_gridLine = QColor(QRgb(0x35322f)); + m_highlightBarColor = QColor(QRgb(0xf5dc0d)); + m_highlightRowColor = QColor(QRgb(0xd72222)); + m_highlightColumnColor = QColor(QRgb(0xd72222)); + m_lightStrength = 5.0f; + m_ambientStrength = 0.5f; + m_highlightLightStrength = 5.0f; + m_uniformColor = true; + m_labelBorders = false; + break; + } + case QDataVis::ThemeIsabelle: { + m_baseColor = QColor(QRgb(0xf9d900)); + //m_heightColor = QColor(QRgb(0x)); + //m_depthColor = QColor(QRgb(0x)); + m_backgroundColor = QColor(QRgb(0x000000)); + m_windowColor = QColor(QRgb(0x000000)); + m_textColor = QColor(QRgb(0xaeadac)); + m_textBackgroundColor = QColor(0x00, 0x00, 0x00, 0xc0); + m_gridLine = QColor(QRgb(0x35322f)); + m_highlightBarColor = QColor(QRgb(0xfff7cc)); + m_highlightRowColor = QColor(QRgb(0xde0a0a)); + m_highlightColumnColor = QColor(QRgb(0xde0a0a)); + m_lightStrength = 5.0f; + m_ambientStrength = 0.5f; + m_highlightLightStrength = 5.0f; + m_uniformColor = true; + m_labelBorders = false; + break; + } + default: + break; + } + if (m_uniformColor) { + m_surfaceGradient.setColorAt(0.0, m_baseColor); + } else { + m_surfaceGradient.setColorAt(0.0, QColor(m_baseColor.redF() * 0.7, + m_baseColor.greenF() * 0.7, + m_baseColor.blueF() * 0.7)); + } + m_surfaceGradient.setColorAt(1.0, m_baseColor); +} + +void Theme::setFromTheme(Theme &theme) +{ + m_theme = theme.m_theme; + m_baseColor = theme.m_baseColor; + m_heightColor = theme.m_heightColor; + m_depthColor = theme.m_depthColor; + m_backgroundColor = theme.m_backgroundColor; + m_windowColor = theme.m_windowColor; + m_textColor = theme.m_textColor; + m_textBackgroundColor = theme.m_textBackgroundColor; + m_gridLine = theme.m_gridLine; + m_highlightBarColor = theme.m_highlightBarColor; + m_highlightRowColor = theme.m_highlightRowColor; + m_highlightColumnColor = theme.m_highlightColumnColor; + m_surfaceGradient = theme.m_surfaceGradient; + m_lightStrength = theme.m_lightStrength; + m_ambientStrength = theme.m_ambientStrength; + m_highlightLightStrength = theme.m_highlightLightStrength; + m_uniformColor = theme.m_uniformColor; + m_labelBorders = theme.m_labelBorders; +} + +QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavis3d/engine/theme_p.h b/src/datavisualization/engine/theme_p.h index 31c47941..ec689f63 100644 --- a/src/datavis3d/engine/theme_p.h +++ b/src/datavisualization/engine/theme_p.h @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -20,7 +20,7 @@ // W A R N I N G // ------------- // -// This file is not part of the QtDataVis3D API. It exists purely as an +// 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. // @@ -29,35 +29,35 @@ #ifndef THEME_P_H #define THEME_P_H -#include "datavis3dglobal_p.h" +#include "datavisualizationglobal_p.h" #include "q3dbars.h" #include <QLinearGradient> class QColor; -QT_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVISUALIZATION_BEGIN_NAMESPACE -class Theme +class QT_DATAVISUALIZATION_EXPORT Theme { public: explicit Theme(); ~Theme(); - void useColorTheme(QDataVis::ColorTheme theme); - QDataVis::ColorTheme colorTheme(); + void useTheme(QDataVis::Theme theme); + QDataVis::Theme theme(); void setFromTheme(Theme &theme); private: friend class Abstract3DController; friend class Abstract3DRenderer; - friend class Bars3dRenderer; - friend class Maps3DController; - friend class Surface3dRenderer; - friend class Surface3dController; + friend class Bars3DRenderer; + friend class Surface3DRenderer; + friend class Surface3DController; friend class Scatter3DRenderer; + friend class SelectionPointer; friend class Drawer; - QDataVis::ColorTheme m_colorTheme; + QDataVis::Theme m_theme; QColor m_baseColor; QColor m_heightColor; QColor m_depthColor; @@ -74,8 +74,9 @@ private: float m_ambientStrength; float m_highlightLightStrength; bool m_uniformColor; + bool m_labelBorders; }; -QT_DATAVIS3D_END_NAMESPACE +QT_DATAVISUALIZATION_END_NAMESPACE #endif diff --git a/src/datavis3d/global/datavis3dglobal_p.h b/src/datavisualization/global/datavisualizationglobal_p.h index d556c5e1..4da1023c 100644 --- a/src/datavis3d/global/datavis3dglobal_p.h +++ b/src/datavisualization/global/datavisualizationglobal_p.h @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -20,33 +20,35 @@ // W A R N I N G // ------------- // -// This file is not part of the QtDataVis3D API. It exists purely as an +// 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 DATAVIS3DGLOBAL_P_H -#define DATAVIS3DGLOBAL_P_H +#ifndef DATAVISUALIZATIONGLOBAL_P_H +#define DATAVISUALIZATIONGLOBAL_P_H -#include "qdatavis3dglobal.h" -#include "qdatavis3denums.h" +#include "qdatavisualizationglobal.h" +#include "qdatavisualizationenums.h" #include <QOpenGLFunctions> #include <QVector3D> #include <QDebug> -//#define ROTATE_ZOOM_SELECTION - -QT_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVISUALIZATION_BEGIN_NAMESPACE // Constants used in several files // Compensation for z position; move all objects to positive z, as shader can't handle negative values correctly const GLfloat zComp = 10.0f; +// Distance from camera to origin +const GLfloat cameraDistance = 6.0f; +// Size of font to be used in label texture rendering. Doesn't affect the actual font size. +const int textureFontSize = 50; // Default light position. To have shadows working correctly, light should be as far as camera, or a bit further // y position is added to the minimum height (or can be thought to be that much above or below the camera) const QVector3D defaultLightPos = QVector3D(0.0f, 0.5f, zComp); const GLfloat defaultRatio = 1.0f / 1.6f; // default aspect ratio 16:10 -QT_DATAVIS3D_END_NAMESPACE +QT_DATAVISUALIZATION_END_NAMESPACE -#endif // DATAVIS3DGLOBAL_P_H +#endif // DATAVISUALIZATIONGLOBAL_P_H diff --git a/src/datavisualization/global/global.pri b/src/datavisualization/global/global.pri new file mode 100644 index 00000000..0fd7c576 --- /dev/null +++ b/src/datavisualization/global/global.pri @@ -0,0 +1,4 @@ +HEADERS += \ + $$PWD/qdatavisualizationglobal.h \ + $$PWD/qdatavisualizationenums.h \ + $$PWD/datavisualizationglobal_p.h diff --git a/src/datavisualization/global/qdatavisualizationenums.h b/src/datavisualization/global/qdatavisualizationenums.h new file mode 100644 index 00000000..3d765ff2 --- /dev/null +++ b/src/datavisualization/global/qdatavisualizationenums.h @@ -0,0 +1,126 @@ +/**************************************************************************** +** +** 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 QDATAVISUALIZATIONENUMS_H +#define QDATAVISUALIZATIONENUMS_H + +#include <QtDataVisualization/qdatavisualizationglobal.h> +#include <QObject> + +// namespace must be declared without using macros for qdoc +namespace QtDataVisualization { + +class QT_DATAVISUALIZATION_EXPORT QDataVis : public QObject +{ + Q_OBJECT + Q_ENUMS(MeshStyle) + Q_ENUMS(CameraPreset) + Q_ENUMS(Theme) + Q_ENUMS(SelectionMode) + Q_ENUMS(ShadowQuality) + Q_ENUMS(LabelStyle) + +public: + enum InputState { + InputStateNone = 0, + InputStateOnScene, + InputStateOnOverview, + InputStateOnSlice, + InputStateRotating, + InputStateOnPinch + }; + + enum MeshStyle { + MeshStyleBars = 0, + MeshStylePyramids, + MeshStyleCones, + MeshStyleCylinders, + MeshStyleBevelBars, + MeshStyleSpheres, + MeshStyleDots + }; + + enum CameraPreset { + CameraPresetNone = -1, + CameraPresetFrontLow = 0, + CameraPresetFront, + CameraPresetFrontHigh, + CameraPresetLeftLow, + CameraPresetLeft, + CameraPresetLeftHigh, + CameraPresetRightLow, + CameraPresetRight, + CameraPresetRightHigh, + CameraPresetBehindLow, + CameraPresetBehind, + CameraPresetBehindHigh, + CameraPresetIsometricLeft, + CameraPresetIsometricLeftHigh, + CameraPresetIsometricRight, + CameraPresetIsometricRightHigh, + CameraPresetDirectlyAbove, + CameraPresetDirectlyAboveCW45, + CameraPresetDirectlyAboveCCW45, + CameraPresetFrontBelow, + CameraPresetLeftBelow, + CameraPresetRightBelow, + CameraPresetBehindBelow, + CameraPresetDirectlyBelow + }; + + enum Theme { + ThemeDefault = -1, + ThemeQt, + ThemePrimaryColors, + ThemeDigia, + ThemeStoneMoss, + ThemeArmyBlue, + ThemeRetro, + ThemeEbony, + ThemeIsabelle + }; + + enum SelectionMode { + SelectionModeNone = 0, + SelectionModeItem, + SelectionModeItemAndRow, + SelectionModeItemAndColumn, + SelectionModeItemRowAndColumn, + SelectionModeSliceRow, + SelectionModeSliceColumn + }; + + enum ShadowQuality { + ShadowQualityNone = 0, + ShadowQualityLow, + ShadowQualityMedium, + ShadowQualityHigh, + ShadowQualitySoftLow, + ShadowQualitySoftMedium, + ShadowQualitySoftHigh + }; + + enum LabelStyle { + LabelStyleOpaque = 0, + LabelStyleFromTheme, + LabelStyleTransparent + }; +}; +} + +#endif diff --git a/src/datavisualization/global/qdatavisualizationglobal.h b/src/datavisualization/global/qdatavisualizationglobal.h new file mode 100644 index 00000000..ac734960 --- /dev/null +++ b/src/datavisualization/global/qdatavisualizationglobal.h @@ -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 +** +****************************************************************************/ + +#ifndef QDATAVISUALIZATIONGLOBAL_H +#define QDATAVISUALIZATIONGLOBAL_H + +#include <qglobal.h> + +#define QT_DATAVISUALIZATION_VERSION_STR "0.0.1" +/* + QT_DATAVISUALIZATION_VERSION is (major << 16) + (minor << 8) + patch. +*/ +#define QT_DATAVISUALIZATION_VERSION 0x000001 +/* + can be used like #if (QT_DATAVISUALIZATION_VERSION >= QT_DATAVISUALIZATION_VERSION_CHECK(1, 1, 0)) +*/ +#define QT_DATAVISUALIZATION_VERSION_CHECK(major, minor, patch) ((major<<16)|(minor<<8)|(patch)) + +#if defined(QT_DATAVISUALIZATION_LIBRARY) +# define QT_DATAVISUALIZATION_EXPORT Q_DECL_EXPORT +#else +# define QT_DATAVISUALIZATION_EXPORT Q_DECL_IMPORT +#endif + +#if defined(BUILD_PRIVATE_UNIT_TESTS) && defined(QT_DATAVISUALIZATION_LIBRARY) +# define QT_DATAVISUALIZATION_AUTOTEST_EXPORT Q_DECL_EXPORT +#elif defined(BUILD_PRIVATE_UNIT_TESTS) && !defined(QT_DATAVISUALIZATION_LIBRARY) +# define QT_DATAVISUALIZATION_AUTOTEST_EXPORT Q_DECL_IMPORT +#else +# define QT_DATAVISUALIZATION_AUTOTEST_EXPORT +#endif + +#ifdef QT_DATAVISUALIZATION_STATICLIB +# undef QT_DATAVISUALIZATION_EXPORT +# undef QT_DATAVISUALIZATION_AUTOTEST_EXPORT +# define QT_DATAVISUALIZATION_EXPORT +# define QT_DATAVISUALIZATION_AUTOTEST_EXPORT +#endif + +#define QT_DATAVISUALIZATION_NAMESPACE QtDataVisualization + +#ifdef QT_DATAVISUALIZATION_NAMESPACE +# define QT_DATAVISUALIZATION_BEGIN_NAMESPACE namespace QT_DATAVISUALIZATION_NAMESPACE { +# define QT_DATAVISUALIZATION_END_NAMESPACE } +# define QT_DATAVISUALIZATION_USE_NAMESPACE using namespace QT_DATAVISUALIZATION_NAMESPACE; +#else +# define QT_DATAVISUALIZATION_BEGIN_NAMESPACE +# define QT_DATAVISUALIZATION_END_NAMESPACE +# define QT_DATAVISUALIZATION_USE_NAMESPACE +#endif + +#endif // QVIS3DGLOBAL_H diff --git a/src/datavisualization/global/qtdatavisualizationenums.qdoc b/src/datavisualization/global/qtdatavisualizationenums.qdoc new file mode 100644 index 00000000..fde6a258 --- /dev/null +++ b/src/datavisualization/global/qtdatavisualizationenums.qdoc @@ -0,0 +1,176 @@ +/**************************************************************************** +** +** 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 +** +****************************************************************************/ + +/*! + \namespace QtDataVisualization + \inmodule QtDataVisualization + \target QtDataVisualization Enums +*/ + +/*! + \enum QtDataVisualization::QDataVis::InputState + + Predefined input states for mouse and touch based input handlers. All states are not valid with all input handlers. + + \value InputStateNone + Default "no input received" state. + \value InputStateOnScene + Mouse or touch input received on the 3D scene. + \value InputStateOnOverview + Mouse or touch input received on the overview area. + \value InputStateOnSlice + Mouse or touch input received on the slice view area. + \value InputStateRotating + Rotation of the 3D geometry ongoing. + \value InputStateOnPinch + Pinch/punch multitouch input received. +*/ + +/*! + \enum QtDataVisualization::QDataVis::MeshStyle + + Predefined mesh types. All styles are not usable with all visualization types. + + \value MeshStyleBars + Basic cubic bar. + \value MeshStylePyramids + Four-sided pyramid. + \value MeshStyleCones + Basic cone. + \value MeshStyleCylinders + Basic cylinder. + \value MeshStyleBevelBars + Slightly beveled (rounded) cubic bar. + \value MeshStyleSpheres + Sphere. Not usable in Q3DBars. + \value MeshStyleDots + Triangular pyramid. Usable only with Q3DScatter. +*/ + +/*! + \enum QtDataVisualization::QDataVis::CameraPreset + + Predefined positions for camera. + + \value CameraPresetNone + Used to indicate a preset has not been set, or the scene has been rotated freely. + \value CameraPresetFrontLow + \value CameraPresetFront + \value CameraPresetFrontHigh + \value CameraPresetLeftLow + \value CameraPresetLeft + \value CameraPresetLeftHigh + \value CameraPresetRightLow + \value CameraPresetRight + \value CameraPresetRightHigh + \value CameraPresetBehindLow + \value CameraPresetBehind + \value CameraPresetBehindHigh + \value CameraPresetIsometricLeft + \value CameraPresetIsometricLeftHigh + \value CameraPresetIsometricRight + \value CameraPresetIsometricRightHigh + \value CameraPresetDirectlyAbove + \value CameraPresetDirectlyAboveCW45 + \value CameraPresetDirectlyAboveCCW45 + \value CameraPresetFrontBelow + In Q3DBars from CameraPresetFrontBelow onward these only work for graphs including negative + values. They act as Preset...Low for positive-only values. + \value CameraPresetLeftBelow + \value CameraPresetRightBelow + \value CameraPresetBehindBelow + \value CameraPresetDirectlyBelow + Acts as CameraPresetFrontLow for positive -only bars. +*/ + +/*! + \enum QtDataVisualization::QDataVis::Theme + + Predefined themes. + + \value ThemeDefault + Used only in QML to indicate a theme has not been set. + \value ThemeQt + \value ThemePrimaryColors + \value ThemeDigia + \value ThemeStoneMoss + \value ThemeArmyBlue + \value ThemeRetro + \value ThemeEbony + \value ThemeIsabelle +*/ + +/*! + \enum QtDataVisualization::QDataVis::SelectionMode + + Item selection modes. + + \value SelectionModeNone + Selection mode disabled. + \value SelectionModeItem + Selection selects a single item. + \value SelectionModeItemAndRow + Selection selects a single item and highlights the row it is on. In Q3DBars only. + \value SelectionModeItemAndColumn + Selection selects a single item and highlights the column it is on. In Q3DBars only. + \value SelectionModeItemRowAndColumn + Selection selects a single item and highlights the row and the column it is on. In + Q3DBars only. + \value SelectionModeSliceRow + Selection selects a single item and displays the row it is on in a separate view. The + original view is shrunk into upper left corner. Original view is restored by clicking + on it. In Q3DBars only. + \value SelectionModeSliceColumn + Selection selects a single item and displays the column it is on in a separate view. The + original view is shrunk into upper left corner. Original view is restored by clicking + on it. In Q3DBars only. +*/ + +/*! + \enum QtDataVisualization::QDataVis::ShadowQuality + + Quality of shadows. + + \value ShadowQualityNone + Shadows are disabled. + \value ShadowQualityLow + Shadows are rendered in low quality. + \value ShadowQualityMedium + Shadows are rendered in medium quality. + \value ShadowQualityHigh + Shadows are rendered in high quality. + \value ShadowQualitySoftLow + Shadows are rendered in low quality with softened edges. + \value ShadowQualitySoftMedium + Shadows are rendered in medium quality with softened edges. + \value ShadowQualitySoftHigh + Shadows are rendered in high quality with softened edges. +*/ + +/*! + \enum QtDataVisualization::QDataVis::LabelStyle + + Label styles. + + \value LabelStyleOpaque + Fully opaque background, using colors and borders from theme. + \value LabelStyleFromTheme + Use transparencies, colors and borders from theme. + \value LabelStyleTransparent + Fully transparent background, using text color from theme. +*/ diff --git a/src/datavisualization/input/input.pri b/src/datavisualization/input/input.pri new file mode 100644 index 00000000..5a4c4a76 --- /dev/null +++ b/src/datavisualization/input/input.pri @@ -0,0 +1,12 @@ +HEADERS += \ + $$PWD/qabstract3dinputhandler.h \ + $$PWD/q3dinputhandler.h \ + $$PWD/qtouch3dinputhandler.h \ + $$PWD/qabstract3dinputhandler_p.h \ + $$PWD/q3dinputhandler_p.h \ + $$PWD/qtouch3dinputhandler_p.h + +SOURCES += \ + $$PWD/qabstract3dinputhandler.cpp \ + $$PWD/q3dinputhandler.cpp \ + $$PWD/qtouch3dinputhandler.cpp diff --git a/src/datavisualization/input/q3dinputhandler.cpp b/src/datavisualization/input/q3dinputhandler.cpp new file mode 100644 index 00000000..5267568c --- /dev/null +++ b/src/datavisualization/input/q3dinputhandler.cpp @@ -0,0 +1,190 @@ +/**************************************************************************** +** +** 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 "datavisualizationglobal_p.h" +#include "q3dinputhandler.h" +#include "q3dcamera_p.h" +#include "q3dlight.h" + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +const int minZoomLevel = 10; +const int halfSizeZoomLevel = 50; +const int oneToOneZoomLevel = 100; +const int maxZoomLevel = 500; + +const int nearZoomRangeDivider = 12; +const int midZoomRangeDivider = 60; +const int farZoomRangeDivider = 120; + +const float rotationSpeed = 100.0f; + +/*! + * \class Q3DInputHandler + * \inmodule QtDataVisualization + * \brief Basic wheel mouse based input handler. + * \since 1.0.0 + * + * Q3DInputHandler is the basic input handler for wheel mouse type of input devices. + * + * Default input handler has the following functionalty: + * \table + * \header + * \li Mouse action \li Action + * \row + * \li Right button pressed \li Rotate graph within limits set for Q3DCamera + * \row + * \li Left click \li Select item under cursor or remove selection if none + * \row + * \li Mouse wheel \li Zoom in/out within default range (10...500%) + * \row + * \li Left click on secodanry view \li Return to primary view when in slice mode + * \note Slice mode is available in Q3DBars and Q3DSurface only + * \endtable + */ + +/*! + * Constructs the basic mouse input handler. An optional \a parent parameter can be given + * and is then passed to QObject constructor. + */ +Q3DInputHandler::Q3DInputHandler(QObject *parent) : + QAbstract3DInputHandler(parent) +{ +} + +/*! + * Destroys the input handler. + */ +Q3DInputHandler::~Q3DInputHandler() +{ +} + +// Input event listeners +/*! + * Override this to change handling of mouse press events. + * Mouse press event is given in the \a event and the mouse position in \a mousePos. + */ +void Q3DInputHandler::mousePressEvent(QMouseEvent *event, const QPoint &mousePos) +{ +#if defined(Q_OS_ANDROID) + Q_UNUSED(event); + Q_UNUSED(mousePos); +#else + if (Qt::LeftButton == event->button()) { + if (scene()->isSlicingActive()) { + if (scene()->isPointInPrimarySubView(mousePos)) { + setInputState(QDataVis::InputStateOnOverview); + } else if (scene()->isPointInSecondarySubView(mousePos)) { + setInputState(QDataVis::InputStateOnSlice); + } else { + setInputState(QDataVis::InputStateNone); + } + } else { + setInputState(QDataVis::InputStateOnScene); + // update mouse positions to prevent jumping when releasing or repressing a button + setInputPosition(mousePos); + } + } else if (Qt::MiddleButton == event->button()) { + // reset rotations + setInputPosition(QPoint(0, 0)); + } else if (Qt::RightButton == event->button()) { + // disable rotating when in slice view + if (!scene()->isSlicingActive()) + setInputState(QDataVis::InputStateRotating); + // update mouse positions to prevent jumping when releasing or repressing a button + setInputPosition(mousePos); + } +#endif +} + +/*! + * Override this to change handling of mouse release events. + * Mouse release event is given in the \a event and the mouse position in \a mousePos. + */ +void Q3DInputHandler::mouseReleaseEvent(QMouseEvent *event, const QPoint &mousePos) +{ + Q_UNUSED(event); +#if defined (Q_OS_ANDROID) + Q_UNUSED(mousePos); +#else + if (QDataVis::InputStateRotating == inputState()) { + // update mouse positions to prevent jumping when releasing or repressing a button + setInputPosition(mousePos); + } + setInputState(QDataVis::InputStateNone); +#endif +} + +/*! + * Override this to change handling of mouse move events. + * Mouse move event is given in the \a event and the mouse position in \a mousePos. + */ +void Q3DInputHandler::mouseMoveEvent(QMouseEvent *event, const QPoint &mousePos) +{ + Q_UNUSED(event); +#if defined (Q_OS_ANDROID) + Q_UNUSED(mousePos); +#else + if (QDataVis::InputStateRotating == inputState()) { + // Calculate mouse movement since last frame + qreal xRotation = scene()->activeCamera()->xRotation(); + qreal yRotation = scene()->activeCamera()->yRotation(); + float mouseMoveX = float(inputPosition().x() - mousePos.x()) + / (scene()->viewport().width() / rotationSpeed); + float mouseMoveY = float(inputPosition().y() - mousePos.y()) + / (scene()->viewport().height() / rotationSpeed); + // Apply to rotations + xRotation -= mouseMoveX; + yRotation -= mouseMoveY; + scene()->activeCamera()->setXRotation(xRotation); + scene()->activeCamera()->setYRotation(yRotation); + scene()->activeCamera()->d_ptr->updateViewMatrix(1.0f); + + setPreviousInputPos(inputPosition()); + setInputPosition(mousePos); + } +#endif +} + +/*! + * Override this to change handling of wheel events. + * The wheel event is given in the \a event. + */ +void Q3DInputHandler::wheelEvent(QWheelEvent *event) +{ + // disable zooming if in slice view + if (scene()->isSlicingActive()) + return; + + // Adjust zoom level based on what zoom range we're in. + int zoomLevel = scene()->activeCamera()->zoomLevel(); + if (zoomLevel > oneToOneZoomLevel) + zoomLevel += event->angleDelta().y() / nearZoomRangeDivider; + else if (zoomLevel > halfSizeZoomLevel) + zoomLevel += event->angleDelta().y() / midZoomRangeDivider; + else + zoomLevel += event->angleDelta().y() / farZoomRangeDivider; + if (zoomLevel > maxZoomLevel) + zoomLevel = maxZoomLevel; + else if (zoomLevel < minZoomLevel) + zoomLevel = minZoomLevel; + + scene()->activeCamera()->setZoomLevel(zoomLevel); +} + +QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavisualization/input/q3dinputhandler.h b/src/datavisualization/input/q3dinputhandler.h new file mode 100644 index 00000000..a7fa0573 --- /dev/null +++ b/src/datavisualization/input/q3dinputhandler.h @@ -0,0 +1,48 @@ +/**************************************************************************** +** +** 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 QDEFAULT3DINPUTHANDLER_H +#define QDEFAULT3DINPUTHANDLER_H + +#include <QtDataVisualization/qabstract3dinputhandler.h> + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +class Q3DInputHandler; // Workaround for qdoc bug, removing this will cause qdoc compiler to not find the class. + +class QT_DATAVISUALIZATION_EXPORT Q3DInputHandler : public QAbstract3DInputHandler +{ + Q_OBJECT + +public: + explicit Q3DInputHandler(QObject *parent = 0); + virtual ~Q3DInputHandler(); + + // Input event listeners + virtual void mousePressEvent(QMouseEvent *event, const QPoint &mousePos); + virtual void mouseReleaseEvent(QMouseEvent *event, const QPoint &mousePos); + virtual void mouseMoveEvent(QMouseEvent *event, const QPoint &mousePos); + virtual void wheelEvent(QWheelEvent *event); + +private: + Q_DISABLE_COPY(Q3DInputHandler) +}; + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif // QDEFAULT3DINPUTHANDLER_H diff --git a/src/datavis3d/engine/q3dmaps_p.h b/src/datavisualization/input/q3dinputhandler_p.h index 166ed8f7..af8bef5f 100644 --- a/src/datavis3d/engine/q3dmaps_p.h +++ b/src/datavisualization/input/q3dinputhandler_p.h @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -20,32 +20,32 @@ // W A R N I N G // ------------- // -// This file is not part of the QtDataVis3D API. It exists purely as an +// 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 Q3DMAPS_P_H -#define Q3DMAPS_P_H +#ifndef Q3DINPUTHANDLER_P_H +#define Q3DINPUTHANDLER_P_H -#include "maps3dcontroller_p.h" -#include "qdatavis3denums.h" +#include "datavisualizationglobal_p.h" -QT_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVISUALIZATION_BEGIN_NAMESPACE -class Q3DMaps; +class Q3DInputHandler; -class Q3DMapsPrivate : public QObject +class Q3DInputHandlerPrivate { public: - Q3DMapsPrivate(Q3DMaps *q, const QRect &rect); - ~Q3DMapsPrivate(); + Q3DInputHandlerPrivate(Q3DInputHandler *q); + ~Q3DInputHandlerPrivate(); + +public: + Q3DInputHandler *q_ptr; - Q3DMaps *q_ptr; - Maps3DController *m_shared; }; -QT_DATAVIS3D_END_NAMESPACE +QT_DATAVISUALIZATION_END_NAMESPACE -#endif +#endif // Q3DINPUTHANDLER_P_H diff --git a/src/datavisualization/input/qabstract3dinputhandler.cpp b/src/datavisualization/input/qabstract3dinputhandler.cpp new file mode 100644 index 00000000..e111ff42 --- /dev/null +++ b/src/datavisualization/input/qabstract3dinputhandler.cpp @@ -0,0 +1,210 @@ +/**************************************************************************** +** +** 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 "qabstract3dinputhandler_p.h" + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +/*! + \class QAbstract3DInputHandler + \inmodule QtDataVisualization + \brief Baseclass for implementations of input handlers. + \since 1.0.0 + + QAbstract3DInputHandler is a baseclass that is subclassed by different input handling implementations + that take input events and translate those to camera and light movements. Input handlers also translate + raw input events to slicing and selection events in the scene. +*/ + +/*! + * Constructs the baseclass. An optional \a parent parameter can be given + * and is then passed to QObject constructor. + */ +QAbstract3DInputHandler::QAbstract3DInputHandler(QObject *parent) : + QObject(parent), + d_ptr(new QAbstract3DInputHandlerPrivate(this)) +{ +} + +/*! + * Destroys the baseclass. + */ +QAbstract3DInputHandler::~QAbstract3DInputHandler() +{ +} + +// Input event listeners +/*! + * Override this to handle mouse double click events. + * Mouse double click event is given in the \a event. + */ +void QAbstract3DInputHandler::mouseDoubleClickEvent(QMouseEvent *event) +{ + Q_UNUSED(event); +} + +/*! + * Override this to handle touch input events. + * Touch event is given in the \a event. + */ +void QAbstract3DInputHandler::touchEvent(QTouchEvent *event) +{ + Q_UNUSED(event); +} + +/*! + * Override this to handle mouse press events. + * Mouse press event is given in the \a event and the mouse position in \a mousePos. + */ +void QAbstract3DInputHandler::mousePressEvent(QMouseEvent *event, const QPoint &mousePos) +{ + Q_UNUSED(event); + Q_UNUSED(mousePos); +} + +/*! + * Override this to handle mouse release events. + * Mouse release event is given in the \a event and the mouse position in \a mousePos. + */ +void QAbstract3DInputHandler::mouseReleaseEvent(QMouseEvent *event, const QPoint &mousePos) +{ + Q_UNUSED(event); + Q_UNUSED(mousePos); +} + +/*! + * Override this to handle mouse move events. + * Mouse move event is given in the \a event and the mouse position in \a mousePos. + */ +void QAbstract3DInputHandler::mouseMoveEvent(QMouseEvent *event, const QPoint &mousePos) +{ + Q_UNUSED(event); + Q_UNUSED(mousePos); +} + +/*! + * Override this to handle wheel events. + * Wheel event is given in the \a event. + */ +void QAbstract3DInputHandler::wheelEvent(QWheelEvent *event) +{ + Q_UNUSED(event); +} + +// Property get/set +/*! + * \property QAbstract3DInputHandler::inputState + * + * Current enumerated input state based on the processed input events. + * When the state changes inputStateChanged() is emitted. + */ +QDataVis::InputState QAbstract3DInputHandler::inputState() +{ + return d_ptr->m_inputState; +} + +void QAbstract3DInputHandler::setInputState(QDataVis::InputState inputState) +{ + if (inputState != d_ptr->m_inputState) { + d_ptr->m_inputState = inputState; + emit inputStateChanged(inputState); + } +} + +/*! + * \property QAbstract3DInputHandler::inputPosition + * + * Last input position based on the processed input events. + */ +QPoint QAbstract3DInputHandler::inputPosition() const +{ + return d_ptr->m_inputPosition; +} + +void QAbstract3DInputHandler::setInputPosition(const QPoint &position) +{ + if (position != d_ptr->m_inputPosition) { + d_ptr->m_inputPosition = position; + emit positionChanged(position); + } +} + +/*! + * \return the manhattan length between last two input positions. + */ +int QAbstract3DInputHandler::prevDistance() const +{ + return d_ptr->m_prevDistance; +} + +/*! + * Sets the \a distance (manhattan length) between last two input positions. + */ +void QAbstract3DInputHandler::setPrevDistance(int distance) +{ + d_ptr->m_prevDistance = distance; +} + +/*! + * \property QAbstract3DInputHandler::scene + * + * The 3D scene this abstract inputhandler is controlling. Only one scene can be controlled by one input handler. + */ +Q3DScene *QAbstract3DInputHandler::scene() const +{ + return d_ptr->m_scene; +} + +void QAbstract3DInputHandler::setScene(Q3DScene *scene) +{ + d_ptr->m_scene = scene; +} + +/*! + * Sets the previous input position to the point given by \a position. + */ +void QAbstract3DInputHandler::setPreviousInputPos(const QPoint &position) +{ + d_ptr->m_previousInputPos = position; +} + +/*! + * Returns the previous input position. + * \return Previous input position. + */ +QPoint QAbstract3DInputHandler::previousInputPos() const +{ + return d_ptr->m_previousInputPos; +} + + +QAbstract3DInputHandlerPrivate::QAbstract3DInputHandlerPrivate(QAbstract3DInputHandler *q) : + q_ptr(q), + m_prevDistance(0), + m_previousInputPos(QPoint(0,0)), + m_inputState(QDataVis::InputStateNone), + m_inputPosition(QPoint(0,0)), + m_scene(0) +{ +} + +QAbstract3DInputHandlerPrivate::~QAbstract3DInputHandlerPrivate() +{ + +} + +QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavisualization/input/qabstract3dinputhandler.h b/src/datavisualization/input/qabstract3dinputhandler.h new file mode 100644 index 00000000..d7bf3aee --- /dev/null +++ b/src/datavisualization/input/qabstract3dinputhandler.h @@ -0,0 +1,82 @@ +/**************************************************************************** +** +** 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 QABSTRACT3DINPUTHANDLER_H +#define QABSTRACT3DINPUTHANDLER_H + +#include <QtDataVisualization/qdatavisualizationenums.h> +#include <QtDataVisualization/q3dscene.h> +#include <QMouseEvent> + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +class QAbstract3DInputHandlerPrivate; + +class QT_DATAVISUALIZATION_EXPORT QAbstract3DInputHandler : public QObject +{ + Q_OBJECT + Q_PROPERTY(QtDataVisualization::QDataVis::InputState inputState READ inputState WRITE setInputState NOTIFY inputStateChanged) + Q_PROPERTY(QPoint inputPosition READ inputPosition WRITE setInputPosition NOTIFY positionChanged) + Q_PROPERTY(Q3DScene *scene READ scene WRITE setScene NOTIFY sceneChanged) + +public: + explicit QAbstract3DInputHandler(QObject *parent = 0); + virtual ~QAbstract3DInputHandler(); + + // Input event listeners + virtual void mouseDoubleClickEvent(QMouseEvent *event); + virtual void touchEvent(QTouchEvent *event); + virtual void mousePressEvent(QMouseEvent *event, const QPoint &mousePos); + virtual void mouseReleaseEvent(QMouseEvent *event, const QPoint &mousePos); + virtual void mouseMoveEvent(QMouseEvent *event, const QPoint &mousePos); + virtual void wheelEvent(QWheelEvent *event); + +public: + // TODO: Check if the inputState needs to be visible outside of subclasses in the final architecture + QDataVis::InputState inputState(); + void setInputState(QDataVis::InputState inputState); + + QPoint inputPosition() const; + void setInputPosition(const QPoint &position); + + Q3DScene *scene() const; + void setScene(Q3DScene *scene); + +signals: + void positionChanged(const QPoint &position); + void inputStateChanged(QDataVis::InputState state); + void sceneChanged(const Q3DScene *scene); + +protected: + void setPrevDistance(int distance); + int prevDistance() const; + void setPreviousInputPos(const QPoint &position); + QPoint previousInputPos() const; + +private: + Q_DISABLE_COPY(QAbstract3DInputHandler) + + QScopedPointer<QAbstract3DInputHandlerPrivate> d_ptr; + + friend class Abstract3DController; + friend class QTouch3DInputHandlerPrivate; +}; + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif // QABSTRACT3DINPUTHANDLER_H diff --git a/src/datavisualization/input/qabstract3dinputhandler_p.h b/src/datavisualization/input/qabstract3dinputhandler_p.h new file mode 100644 index 00000000..cad1c667 --- /dev/null +++ b/src/datavisualization/input/qabstract3dinputhandler_p.h @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** 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 QABSTRACT3DINPUTHANDLER_P_H +#define QABSTRACT3DINPUTHANDLER_P_H + +#include "datavisualizationglobal_p.h" +#include "qabstract3dinputhandler.h" +#include <QRect> + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +class QAbstract3DInputHandler; +class Q3DScene; + +class QAbstract3DInputHandlerPrivate +{ +public: + QAbstract3DInputHandlerPrivate(QAbstract3DInputHandler *q); + ~QAbstract3DInputHandlerPrivate(); + +public: + QAbstract3DInputHandler *q_ptr; + int m_prevDistance; + QPoint m_previousInputPos; + + GLfloat m_defaultXRotation; + GLfloat m_defaultYRotation; + +private: + QDataVis::InputState m_inputState; + QPoint m_inputPosition; + QRect m_mainViewPort; + + // TODO: Check if this could be avoided with signals/slots or some other way. + Q3DScene *m_scene; + bool m_isDefaultHandler; + + friend class QAbstract3DInputHandler; + friend class Abstract3DController; +}; + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif // QABSTRACT3DINPUTHANDLER_P_H diff --git a/src/datavisualization/input/qtouch3dinputhandler.cpp b/src/datavisualization/input/qtouch3dinputhandler.cpp new file mode 100644 index 00000000..fd079e88 --- /dev/null +++ b/src/datavisualization/input/qtouch3dinputhandler.cpp @@ -0,0 +1,209 @@ +/**************************************************************************** +** +** 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 "qtouch3dinputhandler_p.h" +#include "q3dcamera_p.h" +#include <QTimer> +#include <qmath.h> + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +const qreal maxTapAndHoldJitter = 20; +const int maxPinchJitter = 10; +#if defined (Q_OS_ANDROID) +const int maxSelectionJitter = 10; +#else +const int maxSelectionJitter = 5; +#endif +const int tapAndHoldTime = 250; +const float rotationSpeed = 200.0f; +const int minZoomLevel = 10; +const int maxZoomLevel = 500; + +/*! + * \class QTouch3DInputHandler + * \inmodule QtDataVisualization + * \brief Basic touch display based input handler. + * \since 1.0.0 + * + * QTouch3DInputHandler is the basic input handler for touch screen devices. + * + * Default touch input handler has the following functionalty: + * \table + * \header + * \li Gesture \li Action + * \row + * \li Touch-And-Move \li Rotate graph within limits set for Q3DCamera + * \row + * \li Tap \li Select item under pointer or remove selection if none + * \row + * \li Tap-And-Hold \li Select item under pointer or remove selection if none + * \row + * \li Pinch \li Zoom in/out within default range (10...500%) + * \row + * \li Tap on secondary view \li Return to primary view when in slice mode + * \note Slice mode is available in Q3DBars and Q3DSurface only + * \endtable + */ + +/*! + * Constructs the basic touch display input handler. An optional \a parent parameter can be given + * and is then passed to QObject constructor. + */ +QTouch3DInputHandler::QTouch3DInputHandler(QObject *parent) + : Q3DInputHandler(parent), + d_ptr(new QTouch3DInputHandlerPrivate(this)) +{ +} + +/*! + * Destroys the input handler. + */ +QTouch3DInputHandler::~QTouch3DInputHandler() +{ +} + +/*! + * Override this to change handling of touch events. + * Touch event is given in the \a event. + */ +void QTouch3DInputHandler::touchEvent(QTouchEvent *event) +{ + QList<QTouchEvent::TouchPoint> points; + points = event->touchPoints(); + + if (!scene()->isSlicingActive() && points.count() == 2) { + d_ptr->m_holdTimer->stop(); + QPointF distance = points.at(0).pos() - points.at(1).pos(); + d_ptr->handlePinchZoom(distance.manhattanLength()); + } else if (points.count() == 1) { + QPointF pointerPos = points.at(0).pos(); + if (event->type() == QEvent::TouchBegin) { + if (scene()->isSlicingActive()) { + if (scene()->isPointInPrimarySubView(pointerPos.toPoint())) + setInputState(QDataVis::InputStateOnOverview); + else if (scene()->isPointInSecondarySubView(pointerPos.toPoint())) + setInputState(QDataVis::InputStateOnSlice); + else + setInputState(QDataVis::InputStateNone); + } else { + // Handle possible tap-and-hold selection + d_ptr->m_startHoldPos = pointerPos; + d_ptr->m_touchHoldPos = d_ptr->m_startHoldPos; + d_ptr->m_holdTimer->start(); + // Start rotating + setInputState(QDataVis::InputStateRotating); + setInputPosition(pointerPos.toPoint()); + } + } else if (event->type() == QEvent::TouchEnd) { + d_ptr->m_holdTimer->stop(); + // Handle possible selection + d_ptr->handleSelection(pointerPos); + } else if (event->type() == QEvent::TouchUpdate) { + if (!scene()->isSlicingActive()) { + d_ptr->m_touchHoldPos = pointerPos; + // Handle rotation + d_ptr->handleRotation(pointerPos); + } + } + } else { + d_ptr->m_holdTimer->stop(); + } +} + +QTouch3DInputHandlerPrivate::QTouch3DInputHandlerPrivate(QTouch3DInputHandler *q) + : q_ptr(q), + m_holdTimer(0) +{ + m_holdTimer = new QTimer(); + m_holdTimer->setSingleShot(true); + m_holdTimer->setInterval(tapAndHoldTime); + connect(m_holdTimer, &QTimer::timeout, this, &QTouch3DInputHandlerPrivate::handleTapAndHold); +} + +QTouch3DInputHandlerPrivate::~QTouch3DInputHandlerPrivate() +{ + m_holdTimer->stop(); + delete m_holdTimer; +} + +void QTouch3DInputHandlerPrivate::handlePinchZoom(qreal distance) +{ + int newDistance = distance; + int prevDist = q_ptr->prevDistance(); + if (prevDist > 0 && qAbs(prevDist - newDistance) < maxPinchJitter) + return; + q_ptr->setInputState(QDataVis::InputStateOnPinch); + Q3DCamera *camera = q_ptr->scene()->activeCamera(); + int zoomLevel = camera->zoomLevel(); + qreal zoomRate = qSqrt(qSqrt(zoomLevel)); + if (newDistance > prevDist) + zoomLevel += zoomRate; + else + zoomLevel -= zoomRate; + if (zoomLevel > maxZoomLevel) + zoomLevel = maxZoomLevel; + else if (zoomLevel < minZoomLevel) + zoomLevel = minZoomLevel; + camera->setZoomLevel(zoomLevel); + q_ptr->setPrevDistance(newDistance); +} + +void QTouch3DInputHandlerPrivate::handleTapAndHold() +{ + QPointF distance = m_startHoldPos - m_touchHoldPos; + if (distance.manhattanLength() < maxTapAndHoldJitter) { + q_ptr->setInputPosition(m_touchHoldPos.toPoint()); + q_ptr->setInputState(QDataVis::InputStateOnScene); + } +} + +void QTouch3DInputHandlerPrivate::handleSelection(const QPointF &position) +{ + QPointF distance = m_startHoldPos - position; + if (distance.manhattanLength() < maxSelectionJitter) + q_ptr->setInputState(QDataVis::InputStateOnScene); + else + q_ptr->setInputState(QDataVis::InputStateNone); + q_ptr->setPreviousInputPos(position.toPoint()); +} + +void QTouch3DInputHandlerPrivate::handleRotation(const QPointF &position) +{ + if (QDataVis::InputStateRotating == q_ptr->inputState()) { + Q3DScene *scene = q_ptr->scene(); + Q3DCamera *camera = scene->activeCamera(); + float xRotation = camera->xRotation(); + float yRotation = camera->yRotation(); + QPointF inputPos = q_ptr->inputPosition(); + float mouseMoveX = float(inputPos.x() - position.x()) + / (scene->viewport().width() / rotationSpeed); + float mouseMoveY = float(inputPos.y() - position.y()) + / (scene->viewport().height() / rotationSpeed); + xRotation -= mouseMoveX; + yRotation -= mouseMoveY; + camera->setXRotation(xRotation); + camera->setYRotation(yRotation); + camera->d_ptr->updateViewMatrix(1.0f); + + q_ptr->setPreviousInputPos(inputPos.toPoint()); + q_ptr->setInputPosition(position.toPoint()); + } +} + +QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavisualization/input/qtouch3dinputhandler.h b/src/datavisualization/input/qtouch3dinputhandler.h new file mode 100644 index 00000000..1c366926 --- /dev/null +++ b/src/datavisualization/input/qtouch3dinputhandler.h @@ -0,0 +1,47 @@ +/**************************************************************************** +** +** 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 QTOUCH3DINPUTHANDLER_H +#define QTOUCH3DINPUTHANDLER_H + +#include <QtDataVisualization/q3dinputhandler.h> + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +class QTouch3DInputHandlerPrivate; + +class QT_DATAVISUALIZATION_EXPORT QTouch3DInputHandler : public Q3DInputHandler +{ + Q_OBJECT + +public: + explicit QTouch3DInputHandler(QObject *parent = 0); + virtual ~QTouch3DInputHandler(); + + // Input event listeners + virtual void touchEvent(QTouchEvent *event); + +private: + Q_DISABLE_COPY(QTouch3DInputHandler) + + QScopedPointer<QTouch3DInputHandlerPrivate> d_ptr; +}; + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif // QTOUCH3DINPUTHANDLER_H diff --git a/src/datavisualization/input/qtouch3dinputhandler_p.h b/src/datavisualization/input/qtouch3dinputhandler_p.h new file mode 100644 index 00000000..1c5b81c7 --- /dev/null +++ b/src/datavisualization/input/qtouch3dinputhandler_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 +** +****************************************************************************/ + +#ifndef QTOUCH3DINPUTHANDLER_P_H +#define QTOUCH3DINPUTHANDLER_P_H + +#include "qtouch3dinputhandler.h" + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +class QAbstract3DInputHandler; + +class QTouch3DInputHandlerPrivate : public QObject +{ + Q_OBJECT + +public: + QTouch3DInputHandlerPrivate(QTouch3DInputHandler *q); + ~QTouch3DInputHandlerPrivate(); + + void handlePinchZoom(qreal distance); + void handleTapAndHold(); + void handleSelection(const QPointF &position); + void handleRotation(const QPointF &position); + +public: + QTouch3DInputHandler *q_ptr; + QTimer *m_holdTimer; + QPointF m_startHoldPos; + QPointF m_touchHoldPos; +}; + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif // QTOUCH3DINPUTHANDLER_H diff --git a/src/datavis3d/utils/abstractobjecthelper.cpp b/src/datavisualization/utils/abstractobjecthelper.cpp index d54a50c7..d47f2fe6 100644 --- a/src/datavis3d/utils/abstractobjecthelper.cpp +++ b/src/datavisualization/utils/abstractobjecthelper.cpp @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -20,7 +20,7 @@ #include <QDebug> -QT_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVISUALIZATION_BEGIN_NAMESPACE AbstractObjectHelper::AbstractObjectHelper() : m_vertexbuffer(0), @@ -78,4 +78,4 @@ GLuint AbstractObjectHelper::indicesType() return m_indicesType; } -QT_DATAVIS3D_END_NAMESPACE +QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavis3d/utils/abstractobjecthelper_p.h b/src/datavisualization/utils/abstractobjecthelper_p.h index a4d701fa..a6de6941 100644 --- a/src/datavis3d/utils/abstractobjecthelper_p.h +++ b/src/datavisualization/utils/abstractobjecthelper_p.h @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -20,7 +20,7 @@ // W A R N I N G // ------------- // -// This file is not part of the QtDataVis3D API. It exists purely as an +// 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. // @@ -29,10 +29,10 @@ #ifndef ABSTRACTOBJECTHELPER_H #define ABSTRACTOBJECTHELPER_H -#include "datavis3dglobal_p.h" +#include "datavisualizationglobal_p.h" #include <QOpenGLFunctions> -QT_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVISUALIZATION_BEGIN_NAMESPACE class AbstractObjectHelper: protected QOpenGLFunctions { @@ -60,6 +60,6 @@ public: GLuint m_indicesType; }; -QT_DATAVIS3D_END_NAMESPACE +QT_DATAVISUALIZATION_END_NAMESPACE #endif // ABSTRACTOBJECTHELPER_H diff --git a/src/datavis3d/utils/camerahelper.cpp b/src/datavisualization/utils/camerahelper.cpp index 5ae91adb..29ed4d57 100644 --- a/src/datavis3d/utils/camerahelper.cpp +++ b/src/datavisualization/utils/camerahelper.cpp @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -22,7 +22,7 @@ #include <QMatrix4x4> #include <QVector3D> -QT_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVISUALIZATION_BEGIN_NAMESPACE CameraHelper::CameraHelper(QObject *parent) : QObject(parent), @@ -158,123 +158,123 @@ QPointF CameraHelper::getCameraRotations() void CameraHelper::setCameraPreset(QDataVis::CameraPreset preset) { switch (preset) { - case QDataVis::PresetFrontLow: { - qDebug("PresetFrontLow"); + case QDataVis::CameraPresetFrontLow: { + qDebug("CameraPresetFrontLow"); CameraHelper::setCameraRotation(QPointF(0.0f, 0.0f)); break; } - case QDataVis::PresetFront: { - qDebug("PresetFront"); + case QDataVis::CameraPresetFront: { + qDebug("CameraPresetFront"); CameraHelper::setCameraRotation(QPointF(0.0f, 22.5f)); break; } - case QDataVis::PresetFrontHigh: { - qDebug("PresetFrontHigh"); + case QDataVis::CameraPresetFrontHigh: { + qDebug("CameraPresetFrontHigh"); CameraHelper::setCameraRotation(QPointF(0.0f, 45.0f)); break; } - case QDataVis::PresetLeftLow: { - qDebug("PresetLeftLow"); + case QDataVis::CameraPresetLeftLow: { + qDebug("CameraPresetLeftLow"); CameraHelper::setCameraRotation(QPointF(90.0f, 0.0f)); break; } - case QDataVis::PresetLeft: { - qDebug("PresetLeft"); + case QDataVis::CameraPresetLeft: { + qDebug("CameraPresetLeft"); CameraHelper::setCameraRotation(QPointF(90.0f, 22.5f)); break; } - case QDataVis::PresetLeftHigh: { - qDebug("PresetLeftHigh"); + case QDataVis::CameraPresetLeftHigh: { + qDebug("CameraPresetLeftHigh"); CameraHelper::setCameraRotation(QPointF(90.0f, 45.0f)); break; } - case QDataVis::PresetRightLow: { - qDebug("PresetRightLow"); + case QDataVis::CameraPresetRightLow: { + qDebug("CameraPresetRightLow"); CameraHelper::setCameraRotation(QPointF(-90.0f, 0.0f)); break; } - case QDataVis::PresetRight: { - qDebug("PresetRight"); + case QDataVis::CameraPresetRight: { + qDebug("CameraPresetRight"); CameraHelper::setCameraRotation(QPointF(-90.0f, 22.5f)); break; } - case QDataVis::PresetRightHigh: { - qDebug("PresetRightHigh"); + case QDataVis::CameraPresetRightHigh: { + qDebug("CameraPresetRightHigh"); CameraHelper::setCameraRotation(QPointF(-90.0f, 45.0f)); break; } - case QDataVis::PresetBehindLow: { - qDebug("PresetBehindLow"); + case QDataVis::CameraPresetBehindLow: { + qDebug("CameraPresetBehindLow"); CameraHelper::setCameraRotation(QPointF(180.0f, 0.0f)); break; } - case QDataVis::PresetBehind: { - qDebug("PresetBehind"); + case QDataVis::CameraPresetBehind: { + qDebug("CameraPresetBehind"); CameraHelper::setCameraRotation(QPointF(180.0f, 22.5f)); break; } - case QDataVis::PresetBehindHigh: { - qDebug("PresetBehindHigh"); + case QDataVis::CameraPresetBehindHigh: { + qDebug("CameraPresetBehindHigh"); CameraHelper::setCameraRotation(QPointF(180.0f, 45.0f)); break; } - case QDataVis::PresetIsometricLeft: { - qDebug("PresetIsometricLeft"); + case QDataVis::CameraPresetIsometricLeft: { + qDebug("CameraPresetIsometricLeft"); CameraHelper::setCameraRotation(QPointF(45.0f, 22.5f)); break; } - case QDataVis::PresetIsometricLeftHigh: { - qDebug("PresetIsometricLeftHigh"); + case QDataVis::CameraPresetIsometricLeftHigh: { + qDebug("CameraPresetIsometricLeftHigh"); CameraHelper::setCameraRotation(QPointF(45.0f, 45.0f)); break; } - case QDataVis::PresetIsometricRight: { - qDebug("PresetIsometricRight"); + case QDataVis::CameraPresetIsometricRight: { + qDebug("CameraPresetIsometricRight"); CameraHelper::setCameraRotation(QPointF(-45.0f, 22.5f)); break; } - case QDataVis::PresetIsometricRightHigh: { - qDebug("PresetIsometricRightHigh"); + case QDataVis::CameraPresetIsometricRightHigh: { + qDebug("CameraPresetIsometricRightHigh"); CameraHelper::setCameraRotation(QPointF(-45.0f, 45.0f)); break; } - case QDataVis::PresetDirectlyAbove: { - qDebug("PresetDirectlyAbove"); + case QDataVis::CameraPresetDirectlyAbove: { + qDebug("CameraPresetDirectlyAbove"); CameraHelper::setCameraRotation(QPointF(0.0f, 90.0f)); break; } - case QDataVis::PresetDirectlyAboveCW45: { - qDebug("PresetDirectlyAboveCW45"); + case QDataVis::CameraPresetDirectlyAboveCW45: { + qDebug("CameraPresetDirectlyAboveCW45"); CameraHelper::setCameraRotation(QPointF(-45.0f, 90.0f)); break; } - case QDataVis::PresetDirectlyAboveCCW45: { - qDebug("PresetDirectlyAboveCCW45"); + case QDataVis::CameraPresetDirectlyAboveCCW45: { + qDebug("CameraPresetDirectlyAboveCCW45"); CameraHelper::setCameraRotation(QPointF(45.0f, 90.0f)); break; } - case QDataVis::PresetFrontBelow: { - qDebug("PresetFrontBelow"); + case QDataVis::CameraPresetFrontBelow: { + qDebug("CameraPresetFrontBelow"); CameraHelper::setCameraRotation(QPointF(0.0f, -45.0f)); break; } - case QDataVis::PresetLeftBelow: { - qDebug("PresetLeftBelow"); + case QDataVis::CameraPresetLeftBelow: { + qDebug("CameraPresetLeftBelow"); CameraHelper::setCameraRotation(QPointF(90.0f, -45.0f)); break; } - case QDataVis::PresetRightBelow: { - qDebug("PresetRightBelow"); + case QDataVis::CameraPresetRightBelow: { + qDebug("CameraPresetRightBelow"); CameraHelper::setCameraRotation(QPointF(-90.0f, -45.0f)); break; } - case QDataVis::PresetBehindBelow: { - qDebug("PresetBehindBelow"); + case QDataVis::CameraPresetBehindBelow: { + qDebug("CameraPresetBehindBelow"); CameraHelper::setCameraRotation(QPointF(180.0f, -45.0f)); break; } - case QDataVis::PresetDirectlyBelow: { - qDebug("PresetDirectlyBelow"); + case QDataVis::CameraPresetDirectlyBelow: { + qDebug("CameraPresetDirectlyBelow"); CameraHelper::setCameraRotation(QPointF(0.0f, -90.0f)); break; } @@ -283,4 +283,4 @@ void CameraHelper::setCameraPreset(QDataVis::CameraPreset preset) } } -QT_DATAVIS3D_END_NAMESPACE +QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavis3d/utils/camerahelper_p.h b/src/datavisualization/utils/camerahelper_p.h index 3b8c0c9c..1ef4d257 100644 --- a/src/datavis3d/utils/camerahelper_p.h +++ b/src/datavisualization/utils/camerahelper_p.h @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -20,7 +20,7 @@ // W A R N I N G // ------------- // -// This file is not part of the QtDataVis3D API. It exists purely as an +// 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. // @@ -29,7 +29,7 @@ #ifndef CAMERAPOSITIONER_P_H #define CAMERAPOSITIONER_P_H -#include "datavis3dglobal_p.h" +#include "datavisualizationglobal_p.h" #include "q3dbars.h" #include <QObject> @@ -38,7 +38,7 @@ class QVector3D; class QPoint; class QPointF; -QT_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVISUALIZATION_BEGIN_NAMESPACE class CameraHelper : public QObject { @@ -85,6 +85,6 @@ public: void setCameraPreset(QDataVis::CameraPreset preset); }; -QT_DATAVIS3D_END_NAMESPACE +QT_DATAVISUALIZATION_END_NAMESPACE #endif diff --git a/src/datavis3d/utils/meshloader.cpp b/src/datavisualization/utils/meshloader.cpp index ee2f12a6..119cde3a 100644 --- a/src/datavis3d/utils/meshloader.cpp +++ b/src/datavisualization/utils/meshloader.cpp @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -26,7 +26,7 @@ #include <QDebug> -QT_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVISUALIZATION_BEGIN_NAMESPACE QString slashTag = QStringLiteral("/"); @@ -122,4 +122,4 @@ bool MeshLoader::loadOBJ(const QString &path, return true; } -QT_DATAVIS3D_END_NAMESPACE +QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavis3d/utils/meshloader_p.h b/src/datavisualization/utils/meshloader_p.h index acbfb037..48551fff 100644 --- a/src/datavis3d/utils/meshloader_p.h +++ b/src/datavisualization/utils/meshloader_p.h @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -20,7 +20,7 @@ // W A R N I N G // ------------- // -// This file is not part of the QtDataVis3D API. It exists purely as an +// 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. // @@ -29,12 +29,12 @@ #ifndef MESHLOADER_P_H #define MESHLOADER_P_H -#include "datavis3dglobal_p.h" +#include "datavisualizationglobal_p.h" class QVector2D; class QVector3D; -QT_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVISUALIZATION_BEGIN_NAMESPACE class MeshLoader { @@ -46,6 +46,6 @@ class MeshLoader // TODO: add loaders for other formats? }; -QT_DATAVIS3D_END_NAMESPACE +QT_DATAVISUALIZATION_END_NAMESPACE #endif diff --git a/src/datavis3d/utils/objecthelper.cpp b/src/datavisualization/utils/objecthelper.cpp index cbd1e960..9660c215 100644 --- a/src/datavis3d/utils/objecthelper.cpp +++ b/src/datavisualization/utils/objecthelper.cpp @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -23,7 +23,7 @@ #include <QDebug> -QT_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVISUALIZATION_BEGIN_NAMESPACE ObjectHelper::ObjectHelper(const QString &objectFile) : m_objectFile(objectFile) @@ -98,4 +98,4 @@ void ObjectHelper::load() m_meshDataLoaded = true; } -QT_DATAVIS3D_END_NAMESPACE +QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavis3d/utils/objecthelper_p.h b/src/datavisualization/utils/objecthelper_p.h index ba9fc2f3..9d643fdd 100644 --- a/src/datavis3d/utils/objecthelper_p.h +++ b/src/datavisualization/utils/objecthelper_p.h @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -20,7 +20,7 @@ // W A R N I N G // ------------- // -// This file is not part of the QtDataVis3D API. It exists purely as an +// 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. // @@ -29,11 +29,11 @@ #ifndef OBJECTHELPER_P_H #define OBJECTHELPER_P_H -#include "datavis3dglobal_p.h" +#include "datavisualizationglobal_p.h" #include "abstractobjecthelper_p.h" #include <QOpenGLFunctions> -QT_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVISUALIZATION_BEGIN_NAMESPACE class ObjectHelper : public AbstractObjectHelper { @@ -49,6 +49,6 @@ private: QString m_objectFile; }; -QT_DATAVIS3D_END_NAMESPACE +QT_DATAVISUALIZATION_END_NAMESPACE #endif diff --git a/src/datavis3d/utils/shaderhelper.cpp b/src/datavisualization/utils/shaderhelper.cpp index c8716910..7df1736c 100644 --- a/src/datavis3d/utils/shaderhelper.cpp +++ b/src/datavisualization/utils/shaderhelper.cpp @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -20,7 +20,7 @@ #include <QOpenGLShader> -QT_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVISUALIZATION_BEGIN_NAMESPACE ShaderHelper::ShaderHelper(QObject *parent, const QString &vertexShader, @@ -86,6 +86,18 @@ void ShaderHelper::initialize() m_initialized = true; } +bool ShaderHelper::testCompile() +{ + if (m_program) + delete m_program; + m_program = new QOpenGLShaderProgram(m_caller); + if (!m_program->addShaderFromSourceFile(QOpenGLShader::Vertex, m_vertexShaderFile)) + return false; + if (!m_program->addShaderFromSourceFile(QOpenGLShader::Fragment, m_fragmentShaderFile)) + return false; + return true; +} + void ShaderHelper::bind() { m_program->bind(); @@ -226,4 +238,4 @@ GLuint ShaderHelper::normalAtt() return m_normalAttr; } -QT_DATAVIS3D_END_NAMESPACE +QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavis3d/utils/shaderhelper_p.h b/src/datavisualization/utils/shaderhelper_p.h index 97fcf8a0..73e5b9ee 100644 --- a/src/datavis3d/utils/shaderhelper_p.h +++ b/src/datavisualization/utils/shaderhelper_p.h @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -20,7 +20,7 @@ // W A R N I N G // ------------- // -// This file is not part of the QtDataVis3D API. It exists purely as an +// 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. // @@ -29,12 +29,12 @@ #ifndef SHADERHELPER_P_H #define SHADERHELPER_P_H -#include "datavis3dglobal_p.h" +#include "datavisualizationglobal_p.h" #include <QOpenGLFunctions> class QOpenGLShaderProgram; -QT_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVISUALIZATION_BEGIN_NAMESPACE class ShaderHelper { @@ -50,6 +50,7 @@ class ShaderHelper void setTextures(const QString &texture, const QString &depthTexture); void initialize(); + bool testCompile(); void bind(); void release(); void setUniformValue(GLuint uniform, const QVector3D &value); @@ -105,6 +106,6 @@ class ShaderHelper GLboolean m_initialized; }; -QT_DATAVIS3D_END_NAMESPACE +QT_DATAVISUALIZATION_END_NAMESPACE #endif diff --git a/src/datavisualization/utils/surfaceobject.cpp b/src/datavisualization/utils/surfaceobject.cpp new file mode 100644 index 00000000..f78fcec3 --- /dev/null +++ b/src/datavisualization/utils/surfaceobject.cpp @@ -0,0 +1,346 @@ +/**************************************************************************** +** +** 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 "surfaceobject_p.h" +#include "abstractobjecthelper_p.h" + +#include <QVector3D> +#include <QVector2D> + +#include <QDebug> + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +SurfaceObject::SurfaceObject() +{ + m_indicesType = GL_UNSIGNED_INT; + initializeOpenGLFunctions(); + glGenBuffers(1, &m_vertexbuffer); + glGenBuffers(1, &m_normalbuffer); + glGenBuffers(1, &m_uvbuffer); + glGenBuffers(1, &m_elementbuffer); + glGenBuffers(1, &m_gridElementbuffer); +} + +SurfaceObject::~SurfaceObject() +{ + glDeleteBuffers(1, &m_gridElementbuffer); +} + +void SurfaceObject::setUpSmoothData(const QSurfaceDataArray &dataArray, const QRect &space, + GLfloat yRange, GLfloat yMin, bool changeGeometry) +{ + m_columns = space.width(); + m_rows = space.height(); + int totalSize = m_rows * m_columns; + GLfloat xMin = dataArray.at(0)->at(0).x(); + GLfloat zMin = dataArray.at(0)->at(0).z(); + GLfloat xNormalizer = (dataArray.at(0)->last().x() - xMin) / 2.0f; + GLfloat yNormalizer = yRange / 2.0f; + GLfloat zNormalizer = (dataArray.last()->at(0).z() - zMin) / -2.0f; + GLfloat uvX = 1.0 / GLfloat(m_columns - 1); + GLfloat uvY = 1.0 / GLfloat(m_rows - 1); + + m_surfaceType = SurfaceSmooth; + + // Create/populate vertice table + if (changeGeometry) + m_vertices.resize(totalSize); + + QVector<QVector2D> uvs; + if (changeGeometry) + uvs.resize(totalSize); + int totalIndex = 0; + for (int i = 0; i < m_rows; i++) { + const QSurfaceDataRow &p = *dataArray.at(i); + for (int j = 0; j < m_columns; j++) { + const QSurfaceDataItem &data = p.at(j); + float normalizedX = ((data.x() - xMin) / xNormalizer); + float normalizedY = ((data.y() - yMin) / yNormalizer); + float normalizedZ = ((data.z() - zMin) / zNormalizer); + m_vertices[totalIndex] = QVector3D(normalizedX - 1.0f, normalizedY - 1.0f, normalizedZ + 1.0f); + if (changeGeometry) + uvs[totalIndex] = QVector2D(GLfloat(j) * uvX, GLfloat(i) * uvY); + totalIndex++; + } + } + + // Create normals + int rowLimit = m_rows - 1; + int colLimit = m_columns - 1; + int rowColLimit = rowLimit * m_columns; + int totalLimit = totalSize - 1; + if (changeGeometry) + m_normals.resize(totalSize); + + totalIndex = 0; + for (int row = 0; row < rowColLimit; row += m_columns) { + for (int j = 0; j < colLimit; j++) { + m_normals[totalIndex++] = normal(m_vertices.at(row + j), + m_vertices.at(row + j + 1), + m_vertices.at(row + m_columns + j)); + } + int p = row + colLimit; + m_normals[totalIndex++] = normal(m_vertices.at(p), + m_vertices.at(p + m_columns), + m_vertices.at(p - 1)); + } + for (int j = rowColLimit; j < totalLimit; j++) { + m_normals[totalIndex++] = normal(m_vertices.at(j), + m_vertices.at(j - m_columns), + m_vertices.at(j + 1)); + } + int p = m_rows * colLimit; + m_normals[totalIndex++] = normal(m_vertices.at(p), + m_vertices.at(p - 1), + m_vertices.at(p - m_columns - 1)); + + // Create indices table + GLint *indices = 0; + if (changeGeometry) { + m_indexCount = 6 * colLimit * rowLimit; + indices = new GLint[m_indexCount]; + p = 0; + for (int row = 0; row < rowLimit * m_columns; row += m_columns) { + for (int j = 0; j < colLimit; j++) { + // Left triangle + indices[p++] = row + j + 1; + indices[p++] = row + m_columns + j; + indices[p++] = row + j; + + // Right triangle + indices[p++] = row + m_columns + j + 1; + indices[p++] = row + m_columns + j; + indices[p++] = row + j + 1; + } + } + } + + // Create line element indices + GLint *gridIndices = 0; + if (changeGeometry) { + m_gridIndexCount = 2 * m_columns * rowLimit + 2 * m_rows * colLimit; + gridIndices = new GLint[m_gridIndexCount]; + p = 0; + for (int i = 0, row = 0; i < m_rows; i++, row += m_columns) { + for (int j = 0; j < colLimit; j++) { + gridIndices[p++] = row + j; + gridIndices[p++] = row + j + 1; + } + } + for (int i = 0, row = 0; i < rowLimit; i++, row += m_columns) { + for (int j = 0; j < m_columns; j++) { + gridIndices[p++] = row + j; + gridIndices[p++] = row + j + m_columns; + } + } + } + + createBuffers(m_vertices, uvs, m_normals, indices, gridIndices, changeGeometry); + + delete[] indices; + delete[] gridIndices; +} + + +void SurfaceObject::setUpData(const QSurfaceDataArray &dataArray, const QRect &space, + GLfloat yRange, GLfloat yMin, bool changeGeometry) +{ + m_columns = space.width(); + m_rows = space.height(); + int totalSize = m_rows * m_columns * 2; + GLfloat xMin = dataArray.at(0)->at(0).x(); + GLfloat zMin = dataArray.at(0)->at(0).z(); + GLfloat xNormalizer = (dataArray.at(0)->last().x() - xMin) / 2.0f; + GLfloat yNormalizer = yRange / 2.0f; + GLfloat zNormalizer = (dataArray.last()->at(0).z() - zMin) / -2.0f; + GLfloat uvX = 1.0 / GLfloat(m_columns - 1); + GLfloat uvY = 1.0 / GLfloat(m_rows - 1); + + m_surfaceType = SurfaceFlat; + + // Create vertice table + if (changeGeometry) + m_vertices.resize(totalSize); + + QVector<QVector2D> uvs; + if (changeGeometry) + uvs.resize(totalSize); + + int totalIndex = 0; + int rowLimit = m_rows - 1; + int colLimit = m_columns - 1; + int doubleColumns = m_columns * 2 - 2; + int rowColLimit = rowLimit * doubleColumns; + + for (int i = 0; i < m_rows; i++) { + const QSurfaceDataRow &row = *dataArray.at(i); + for (int j = 0; j < m_columns; j++) { + const QSurfaceDataItem &data = row.at(j); + float normalizedX = ((data.x() - xMin) / xNormalizer); + float normalizedY = ((data.y() - yMin) / yNormalizer); + float normalizedZ = ((data.z() - zMin) / zNormalizer); + m_vertices[totalIndex] = QVector3D(normalizedX - 1.0f, normalizedY - 1.0f, normalizedZ + 1.0f); + if (changeGeometry) + uvs[totalIndex] = QVector2D(GLfloat(j) * uvX, GLfloat(i) * uvY); + + totalIndex++; + + if (j > 0 && j < colLimit) { + m_vertices[totalIndex] = m_vertices[totalIndex - 1]; + if (changeGeometry) + uvs[totalIndex] = uvs[totalIndex - 1]; + totalIndex++; + } + } + } + + // Create normals & indices table + GLint *indices = 0; + int p = 0; + if (changeGeometry) { + int normalCount = 2 * colLimit * rowLimit; + m_indexCount = 3 * normalCount; + indices = new GLint[m_indexCount]; + m_normals.resize(normalCount); + } + + totalIndex = 0; + for (int row = 0, upperRow = doubleColumns; + row < rowColLimit; + row += doubleColumns, upperRow += doubleColumns) { + for (int j = 0; j < doubleColumns; j += 2) { + // Normal for the left triangle + m_normals[totalIndex++] = normal(m_vertices.at(row + j), + m_vertices.at(row + j + 1), + m_vertices.at(upperRow + j)); + + // Normal for the right triangle + m_normals[totalIndex++] = normal(m_vertices.at(row + j + 1), + m_vertices.at(upperRow + j + 1), + m_vertices.at(upperRow + j)); + + if (changeGeometry) { + // Left triangle + indices[p++] = row + j + 1; + indices[p++] = upperRow + j; + indices[p++] = row + j; + + // Right triangle + indices[p++] = upperRow + j + 1; + indices[p++] = upperRow + j; + indices[p++] = row + j + 1; + } + } + } + + // Create grid line element indices + GLint *gridIndices = 0; + if (changeGeometry) { + m_gridIndexCount = 2 * m_columns * rowLimit + 2 * m_rows * colLimit; + gridIndices = new GLint[m_gridIndexCount]; + p = 0; + int fullRowLimit = m_rows * doubleColumns; + for (int row = 0; row < fullRowLimit; row += doubleColumns) { + for (int j = 0; j < doubleColumns; j += 2) { + gridIndices[p++] = row + j; + gridIndices[p++] = row + j + 1; + + if (row < rowColLimit) { + gridIndices[p++] = row + j; + gridIndices[p++] = row + j + doubleColumns; + } + } + } + for (int i = doubleColumns - 1; i < rowColLimit; i += doubleColumns) { + gridIndices[p++] = i; + gridIndices[p++] = i + doubleColumns; + } + } + + createBuffers(m_vertices, uvs, m_normals, indices, gridIndices, changeGeometry); + + delete[] indices; + delete[] gridIndices; +} + +void SurfaceObject::createBuffers(const QVector<QVector3D> &vertices, const QVector<QVector2D> &uvs, + const QVector<QVector3D> &normals, const GLint *indices, + const GLint *gridIndices, bool changeGeometry) +{ + // Move to buffers + glBindBuffer(GL_ARRAY_BUFFER, m_vertexbuffer); + glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(QVector3D), + &vertices.at(0), GL_DYNAMIC_DRAW); + + glBindBuffer(GL_ARRAY_BUFFER, m_normalbuffer); + glBufferData(GL_ARRAY_BUFFER, normals.size() * sizeof(QVector3D), + &normals.at(0), GL_DYNAMIC_DRAW); + + if (changeGeometry) { + if (uvs.size()) { + glBindBuffer(GL_ARRAY_BUFFER, m_uvbuffer); + glBufferData(GL_ARRAY_BUFFER, uvs.size() * sizeof(QVector2D), + &uvs.at(0), GL_STATIC_DRAW); + } + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_elementbuffer); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_indexCount * sizeof(GLint), + indices, GL_STATIC_DRAW); + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_gridElementbuffer); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_gridIndexCount * sizeof(GLint), + gridIndices, GL_STATIC_DRAW); + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + } + + glBindBuffer(GL_ARRAY_BUFFER, 0); + + m_meshDataLoaded = true; +} + +GLuint SurfaceObject::gridElementBuf() +{ + if (!m_meshDataLoaded) + qFatal("No loaded object"); + return m_gridElementbuffer; +} + +GLuint SurfaceObject::gridIndexCount() +{ + return m_gridIndexCount; +} + +QVector3D SurfaceObject::vertexAt(int column, int row) +{ + int pos = 0; + if (m_surfaceType == SurfaceFlat) + pos = row * (m_columns * 2 - 2) + column * 2 - (column > 0); + else + pos = row * m_columns + column; + return m_vertices.at(pos); +} + +QVector3D SurfaceObject::normal(const QVector3D &a, const QVector3D &b, const QVector3D &c) +{ + QVector3D v1 = b - a; + QVector3D v2 = c - a; + return QVector3D::crossProduct(v1, v2); +} + +QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavis3d/utils/surfaceobject_p.h b/src/datavisualization/utils/surfaceobject_p.h index 729757c4..4f30f7c0 100644 --- a/src/datavis3d/utils/surfaceobject_p.h +++ b/src/datavisualization/utils/surfaceobject_p.h @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -20,7 +20,7 @@ // W A R N I N G // ------------- // -// This file is not part of the QtDataVis3D API. It exists purely as an +// 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. // @@ -29,11 +29,14 @@ #ifndef SURFACEOBJECT_P_H #define SURFACEOBJECT_P_H -#include "datavis3dglobal_p.h" +#include "datavisualizationglobal_p.h" #include "abstractobjecthelper_p.h" +#include "qsurfacedataproxy.h" + #include <QOpenGLFunctions> +#include <QRect> -QT_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVISUALIZATION_BEGIN_NAMESPACE class SurfaceObject : public AbstractObjectHelper { @@ -41,10 +44,13 @@ public: SurfaceObject(); ~SurfaceObject(); - void setUpData(QList<qreal> series, int columns, int rows, GLfloat yRange, bool changeGeometry); - void setUpSmoothData(QList<qreal> series, int columns, int rows, GLfloat yRange, bool changeGeometry); + void setUpData(const QSurfaceDataArray &dataArray, const QRect &space, GLfloat yRange, + GLfloat yMin, bool changeGeometry); + void setUpSmoothData(const QSurfaceDataArray &dataArray, const QRect &space, GLfloat yRange, + GLfloat yMin, bool changeGeometry); GLuint gridElementBuf(); GLuint gridIndexCount(); + QVector3D vertexAt(int column, int row); private: QVector3D normal(const QVector3D &a, const QVector3D &b, const QVector3D &c); @@ -53,13 +59,18 @@ private: const GLint *gridIndices, bool changeGeometry); private: - QList<qreal> m_series; - int m_dataWidth; - int m_dataDepth; - GLfloat m_yRange; + enum SurfaceType { + SurfaceSmooth, + SurfaceFlat + }; + int m_surfaceType; + int m_columns; + int m_rows; GLuint m_gridElementbuffer; GLuint m_gridIndexCount; + QVector<QVector3D> m_vertices; + QVector<QVector3D> m_normals; }; -QT_DATAVIS3D_END_NAMESPACE +QT_DATAVISUALIZATION_END_NAMESPACE #endif // SURFACEOBJECT_P_H diff --git a/src/datavis3d/utils/texturehelper.cpp b/src/datavisualization/utils/texturehelper.cpp index 1773c0f8..25fe17ac 100644 --- a/src/datavis3d/utils/texturehelper.cpp +++ b/src/datavisualization/utils/texturehelper.cpp @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -23,7 +23,7 @@ #include <QDebug> -QT_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVISUALIZATION_BEGIN_NAMESPACE TextureHelper::TextureHelper() { @@ -34,66 +34,49 @@ TextureHelper::~TextureHelper() { } -GLuint TextureHelper::create2DTexture(const QImage &image, bool useTrilinearFiltering, bool convert) +GLuint TextureHelper::create2DTexture(const QImage &image, bool useTrilinearFiltering, + bool convert, bool smoothScale) { if (image.isNull()) return 0; - QImage texImage; + QImage texImage = image; #if defined(Q_OS_ANDROID) GLuint temp; //qDebug() << "old size" << image.size(); GLuint imageWidth = Utils::getNearestPowerOfTwo(image.width(), temp); - //qDebug() << "new width" << imageWidth << "padding" << temp; GLuint imageHeight = Utils::getNearestPowerOfTwo(image.height(), temp); - //qDebug() << "new height" << imageHeight << "padding" << temp; - texImage = image.scaled(imageWidth, imageHeight, Qt::IgnoreAspectRatio, - Qt::SmoothTransformation); + if (smoothScale) { + texImage = image.scaled(imageWidth, imageHeight, Qt::IgnoreAspectRatio, + Qt::SmoothTransformation); + } else { + texImage = image.scaled(imageWidth, imageHeight, Qt::IgnoreAspectRatio); + } //qDebug() << "new size" << texImage.size(); -#else - texImage = image; #endif GLuint textureId; glGenTextures(1, &textureId); glBindTexture(GL_TEXTURE_2D, textureId); - if (convert) { - QImage glTexture = convertToGLFormat(texImage); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, glTexture.width(), glTexture.height(), - 0, GL_RGBA, GL_UNSIGNED_BYTE, glTexture.bits()); - } else { - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texImage.width(), texImage.height(), - 0, GL_RGBA, GL_UNSIGNED_BYTE, texImage.bits()); - } - if (useTrilinearFiltering) { + if (convert) + texImage = convertToGLFormat(texImage); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texImage.width(), texImage.height(), + 0, GL_RGBA, GL_UNSIGNED_BYTE, texImage.bits()); + if (smoothScale) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + else + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + if (useTrilinearFiltering) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glGenerateMipmap(GL_TEXTURE_2D); } else { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); } glBindTexture(GL_TEXTURE_2D, 0); return textureId; } -GLuint TextureHelper::create2DTexture(const uchar *image, int width, int height) -{ - GLuint textureId; - glGenTextures(1, &textureId); - glBindTexture(GL_TEXTURE_2D, textureId); - - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, - 0, GL_RGBA, GL_UNSIGNED_BYTE, image); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - - glBindTexture(GL_TEXTURE_2D, 0); - return textureId; -} - GLuint TextureHelper::createCubeMapTexture(const QImage &image, bool useTrilinearFiltering) { if (image.isNull()) @@ -105,13 +88,12 @@ GLuint TextureHelper::createCubeMapTexture(const QImage &image, bool useTrilinea QImage glTexture = convertToGLFormat(image); glTexImage2D(GL_TEXTURE_CUBE_MAP, 0, GL_RGBA, glTexture.width(), glTexture.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, glTexture.bits()); + glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); if (useTrilinearFiltering) { - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glGenerateMipmap(GL_TEXTURE_CUBE_MAP); } else { glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR); } glBindTexture(GL_TEXTURE_2D, 0); return textureId; @@ -391,4 +373,4 @@ QRgb TextureHelper::qt_gl_convertToGLFormatHelper(QRgb src_pixel, GLenum texture } } -QT_DATAVIS3D_END_NAMESPACE +QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavis3d/utils/texturehelper_p.h b/src/datavisualization/utils/texturehelper_p.h index e8f17d33..f7779b59 100644 --- a/src/datavis3d/utils/texturehelper_p.h +++ b/src/datavisualization/utils/texturehelper_p.h @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -20,7 +20,7 @@ // W A R N I N G // ------------- // -// This file is not part of the QtDataVis3D API. It exists purely as an +// 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. // @@ -29,11 +29,11 @@ #ifndef TEXTUREHELPER_P_H #define TEXTUREHELPER_P_H -#include "datavis3dglobal_p.h" +#include "datavisualizationglobal_p.h" #include <QOpenGLFunctions> #include <QRgb> -QT_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVISUALIZATION_BEGIN_NAMESPACE class TextureHelper : protected QOpenGLFunctions { @@ -43,8 +43,7 @@ class TextureHelper : protected QOpenGLFunctions // Ownership of created texture is transferred to caller GLuint create2DTexture(const QImage &image, bool useTrilinearFiltering = false, - bool convert = true); - GLuint create2DTexture(const uchar *image, int width, int height); + bool convert = true, bool smoothScale = true); GLuint createCubeMapTexture(const QImage &image, bool useTrilinearFiltering = false); // Returns selection framebuffer and inserts generated texture id to texture parameters GLuint createSelectionBuffer(const QSize &size, GLuint &texture, GLuint &depthTexture); @@ -61,12 +60,11 @@ class TextureHelper : protected QOpenGLFunctions void convertToGLFormatHelper(QImage &dstImage, const QImage &srcImage, GLenum texture_format); QRgb qt_gl_convertToGLFormatHelper(QRgb src_pixel, GLenum texture_format); - friend class Bars3dRenderer; - friend class Maps3DController; - friend class Surface3dRenderer; + friend class Bars3DRenderer; + friend class Surface3DRenderer; friend class Scatter3DRenderer; }; -QT_DATAVIS3D_END_NAMESPACE +QT_DATAVISUALIZATION_END_NAMESPACE #endif diff --git a/src/datavisualization/utils/utils.cpp b/src/datavisualization/utils/utils.cpp new file mode 100644 index 00000000..947dbfba --- /dev/null +++ b/src/datavisualization/utils/utils.cpp @@ -0,0 +1,263 @@ +/**************************************************************************** +** +** 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 "utils_p.h" + +#include <QVector3D> +#include <QColor> +#include <QPainter> +#include <QPoint> +#include <QImage> +#include <QRegExp> +#include <qmath.h> + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +#define NUM_IN_POWER(y, x) for (;y<x;y<<=1) +#define MIN_POWER 32 + +GLuint Utils::getNearestPowerOfTwo(GLuint value, GLuint &padding) +{ + GLuint powOfTwoValue = MIN_POWER; + NUM_IN_POWER(powOfTwoValue, value); + padding = powOfTwoValue - value; + return powOfTwoValue; +} + +QVector3D Utils::vectorFromColor(const QColor &color) +{ + return QVector3D(color.redF(), color.greenF(), color.blueF()); +} + +QImage Utils::printTextToImage(const QFont &font, const QString &text, const QColor &bgrColor, + const QColor &txtColor, QDataVis::LabelStyle style, + bool borders, int maxLabelWidth) +{ + GLuint paddingWidth = 20; + GLuint paddingHeight = 20; + // Calculate text dimensions + QFont valueFont = font; + valueFont.setPointSize(textureFontSize); + QFontMetrics valueFM(valueFont); + int valueStrWidth = valueFM.width(text); + if (maxLabelWidth && QDataVis::LabelStyleTransparent != style) + valueStrWidth = maxLabelWidth; + int valueStrHeight = valueFM.height(); + valueStrWidth += paddingWidth / 2; // Fix clipping problem with skewed fonts (italic or italic-style) + QSize labelSize; + +#if defined(Q_OS_ANDROID) + // Android can't handle textures with dimensions not in power of 2. Resize labels accordingly. + // Add some padding before converting to power of two to avoid too tight fit + GLuint prePadding = 5; + // Android needs to use this always (when given) because of the power of 2 -issue. + if (maxLabelWidth) + valueStrWidth = maxLabelWidth + paddingWidth / 2; + labelSize = QSize(valueStrWidth + prePadding, valueStrHeight + prePadding); + //qDebug() << "label size before padding" << text << labelSize; + labelSize.setWidth(getNearestPowerOfTwo(labelSize.width(), paddingWidth)); + labelSize.setHeight(getNearestPowerOfTwo(labelSize.height(), paddingHeight)); + //qDebug() << "label size after padding" << labelSize << paddingWidth << paddingHeight; +#else + if (QDataVis::LabelStyleTransparent == style) + labelSize = QSize(valueStrWidth, valueStrHeight); + else + labelSize = QSize(valueStrWidth + paddingWidth * 2, valueStrHeight + paddingHeight * 2); +#endif + + // Create image + QImage image = QImage(labelSize, QImage::Format_ARGB32); + image.fill(Qt::transparent); + + // Init painter + QPainter painter(&image); + // Paint text + painter.setRenderHint(QPainter::Antialiasing, true); + painter.setCompositionMode(QPainter::CompositionMode_Source); + painter.setFont(valueFont); + switch (style) { + case QDataVis::LabelStyleTransparent: { + painter.setPen(txtColor); +#if defined(Q_OS_ANDROID) + painter.drawText((labelSize.width() - valueStrWidth) / 2.0f, + (labelSize.height() - valueStrHeight) / 2.0f, + valueStrWidth, valueStrHeight, + Qt::AlignCenter | Qt::AlignVCenter, + text); +#else + painter.drawText(0, 0, + valueStrWidth, valueStrHeight, + Qt::AlignCenter | Qt::AlignVCenter, + text); +#endif + break; + } + case QDataVis::LabelStyleFromTheme: { + painter.setBrush(QBrush(bgrColor)); + if (borders) { + painter.setPen(QPen(QBrush(txtColor), 5, Qt::SolidLine, Qt::SquareCap, Qt::RoundJoin)); + painter.drawRoundedRect(5, 5, labelSize.width() - 10, labelSize.height() - 10, + 10.0, 10.0); + } else { + painter.setPen(bgrColor); + painter.drawRoundedRect(0, 0, labelSize.width(), labelSize.height(), 10.0, 10.0); + } + painter.setPen(txtColor); + painter.drawText((labelSize.width() - valueStrWidth) / 2.0f, + (labelSize.height() - valueStrHeight) / 2.0f, + valueStrWidth, valueStrHeight, + Qt::AlignCenter | Qt::AlignVCenter, + text); + break; + } + case QDataVis::LabelStyleOpaque: { + QColor labelColor = QColor(bgrColor); + labelColor.setAlphaF(1.0); + painter.setBrush(QBrush(labelColor)); + if (borders) { + painter.setPen(QPen(QBrush(txtColor), 7, Qt::SolidLine, Qt::SquareCap, Qt::MiterJoin)); + painter.drawRect(7, 7, labelSize.width() - 14, labelSize.height() - 14); + } else { + painter.setPen(labelColor); + painter.drawRect(0, 0, labelSize.width(), labelSize.height()); + } + painter.setPen(txtColor); + painter.drawText((labelSize.width() - valueStrWidth) / 2.0f, + (labelSize.height() - valueStrHeight) / 2.0f, + valueStrWidth, valueStrHeight, + Qt::AlignCenter | Qt::AlignVCenter, + text); + break; + } + } + return image; +} + +QVector3D Utils::getSelection(QPoint mousepos, int height) +{ + QVector3D selectedColor; + + //#if defined(QT_OPENGL_ES_2) + // This is the only one that works with ANGLE (ES 2.0) + // Item count will be limited to 256*256*256 + GLubyte pixel[4]; + glReadPixels(mousepos.x(), height - mousepos.y(), 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, + (void *)pixel); + + //qDebug() << "rgba" << pixel[0] << pixel[1] << pixel[2] << pixel[3] << "mousepos:" << mousepos << "height:" << height; + + //#else + // These work with desktop OpenGL + // They offer a lot higher possible object count and a possibility to use object ids + //GLuint pixel[3]; + //glReadPixels(mousepos.x(), height - mousepos.y(), 1, 1, + // GL_RGB, GL_UNSIGNED_INT, (void *)pixel); + //qDebug() << "rgba" << pixel[0] << pixel[1] << pixel[2];// << pixel[3]; + + //GLfloat pixel3[3]; + //glReadPixels(mousepos.x(), height - mousepos.y(), 1, 1, + // GL_RGB, GL_FLOAT, (void *)pixel3); + //qDebug() << "rgba" << pixel3[0] << pixel3[1] << pixel3[2];// << pixel[3]; + //#endif + selectedColor = QVector3D(pixel[0], pixel[1], pixel[2]); + //qDebug() << selectedColor; + + return selectedColor; +} + +Utils::ParamType Utils::mapFormatCharToParamType(const QChar &formatChar) +{ + ParamType retVal = ParamTypeUnknown; + if (formatChar == QLatin1Char('d') + || formatChar == QLatin1Char('i') + || formatChar == QLatin1Char('c')) { + retVal = ParamTypeInt; + } else if (formatChar == QLatin1Char('u') + || formatChar == QLatin1Char('o') + || formatChar == QLatin1Char('x') + || formatChar == QLatin1Char('X')) { + retVal = ParamTypeUInt; + } else if (formatChar == QLatin1Char('f') + || formatChar == QLatin1Char('F') + || formatChar == QLatin1Char('e') + || formatChar == QLatin1Char('E') + || formatChar == QLatin1Char('g') + || formatChar == QLatin1Char('G')) { + retVal = ParamTypeReal; + } + + return retVal; +} + +Utils::ParamType Utils::findFormatParamType(const QString &format) +{ + static QRegExp formatMatcher(QStringLiteral("%[\\-\\+#\\s\\d\\.lhjztL]*([dicuoxfegXFEG])")); + + if (formatMatcher.indexIn(format, 0) != -1) { + QString capStr = formatMatcher.cap(1); + if (capStr.isEmpty()) + return ParamTypeUnknown; + else + return mapFormatCharToParamType(capStr.at(0)); + } + + return ParamTypeUnknown; +} + +QString Utils::formatLabel(const QByteArray &format, ParamType paramType, qreal value) +{ + switch (paramType) { + case ParamTypeInt: + return QString().sprintf(format, (qint64)value); + case ParamTypeUInt: + return QString().sprintf(format, (quint64)value); + case ParamTypeReal: + return QString().sprintf(format, value); + default: + return QString::fromUtf8(format); // To detect errors + } +} + +QString Utils::defaultLabelFormat() +{ + static const QString defaultFormat(QStringLiteral("%.2f")); + return defaultFormat; +} + +qreal Utils::wrapValue(qreal value, qreal min, qreal max) +{ + if (value > max) { + value = min + (value - max); + + // In case single wrap fails, jump to opposite end. + if (value > max) + value = min; + } + + if (value < min) { + value = max + (value - min); + + // In case single wrap fails, jump to opposite end. + if (value < min) + value = max; + } + + return value; +} + +QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavis3d/utils/utils.pri b/src/datavisualization/utils/utils.pri index cef5ebf0..cef5ebf0 100644 --- a/src/datavis3d/utils/utils.pri +++ b/src/datavisualization/utils/utils.pri diff --git a/src/datavis3d/utils/utils_p.h b/src/datavisualization/utils/utils_p.h index fe7d6081..e74b590d 100644 --- a/src/datavis3d/utils/utils_p.h +++ b/src/datavisualization/utils/utils_p.h @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -20,7 +20,7 @@ // W A R N I N G // ------------- // -// This file is not part of the QtDataVis3D API. It exists purely as an +// 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. // @@ -29,7 +29,7 @@ #ifndef UTILS_P_H #define UTILS_P_H -#include "datavis3dglobal_p.h" +#include "datavisualizationglobal_p.h" #include "q3dbars.h" class QVector3D; @@ -39,11 +39,18 @@ class QString; class QPoint; class QImage; -QT_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVISUALIZATION_BEGIN_NAMESPACE class Utils { - public: +public: + enum ParamType { + ParamTypeUnknown = 0, + ParamTypeInt, + ParamTypeUInt, + ParamTypeReal + }; + static GLuint getNearestPowerOfTwo(GLuint value, GLuint &padding); static QVector3D vectorFromColor(const QColor &color); static void printText(QPainter *painter, const QString &text, const QSize &position, @@ -52,10 +59,21 @@ class Utils const QString &text, const QColor &bgrColor, const QColor &txtColor, - QDataVis::LabelTransparency transparency); + QDataVis::LabelStyle style, + bool borders = false, + int maxLabelWidth = 0); static QVector3D getSelection(QPoint mousepos, int height); + + static ParamType findFormatParamType(const QString &format); + static QString formatLabel(const QByteArray &format, ParamType paramType, qreal value); + static QString defaultLabelFormat(); + + static qreal wrapValue(qreal value, qreal min, qreal max); + +private: + static ParamType mapFormatCharToParamType(const QChar &formatChar); }; -QT_DATAVIS3D_END_NAMESPACE +QT_DATAVISUALIZATION_END_NAMESPACE #endif diff --git a/src/datavis3d/utils/vertexindexer.cpp b/src/datavisualization/utils/vertexindexer.cpp index 6efba116..63b9faaf 100644 --- a/src/datavis3d/utils/vertexindexer.cpp +++ b/src/datavisualization/utils/vertexindexer.cpp @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -23,7 +23,7 @@ #include <QDebug> -QT_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVISUALIZATION_BEGIN_NAMESPACE int unique_vertices = 0; @@ -150,4 +150,4 @@ void VertexIndexer::indexVBO_TBN(const QVector<QVector3D> &in_vertices, //qDebug() << "unique vertices" << unique_vertices; } -QT_DATAVIS3D_END_NAMESPACE +QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavis3d/utils/vertexindexer_p.h b/src/datavisualization/utils/vertexindexer_p.h index 3ca62236..0cf1857b 100644 --- a/src/datavis3d/utils/vertexindexer_p.h +++ b/src/datavisualization/utils/vertexindexer_p.h @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -20,7 +20,7 @@ // W A R N I N G // ------------- // -// This file is not part of the QtDataVis3D API. It exists purely as an +// 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. // @@ -29,13 +29,13 @@ #ifndef VERTEXINDEXER_P_H #define VERTEXINDEXER_P_H -#include "datavis3dglobal_p.h" +#include "datavisualizationglobal_p.h" #include <QVector> #include <QVector2D> #include <QVector3D> -QT_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVISUALIZATION_BEGIN_NAMESPACE class VertexIndexer { @@ -83,6 +83,6 @@ class VertexIndexer unsigned short &result); }; -QT_DATAVIS3D_END_NAMESPACE +QT_DATAVISUALIZATION_END_NAMESPACE #endif diff --git a/src/datavisualizationqml2/abstractdeclarative.cpp b/src/datavisualizationqml2/abstractdeclarative.cpp new file mode 100644 index 00000000..e853ff9c --- /dev/null +++ b/src/datavisualizationqml2/abstractdeclarative.cpp @@ -0,0 +1,189 @@ +/**************************************************************************** +** +** 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 "abstractdeclarative_p.h" +#include "q3dvalueaxis.h" +#include "theme_p.h" + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +AbstractDeclarative::AbstractDeclarative(QQuickItem *parent) : + QQuickItem(parent) +{ +} + +AbstractDeclarative::~AbstractDeclarative() +{ +} + +Q3DScene* AbstractDeclarative::scene() const +{ + return m_controller->scene(); +} + +void AbstractDeclarative::setTheme(QDataVis::Theme theme) +{ + // TODO: Implement correctly once "user-modifiable themes" (QTRD-2120) is implemented + m_controller->setTheme(theme); +} + +QDataVis::Theme AbstractDeclarative::theme() const +{ + return m_controller->theme().theme(); +} + +void AbstractDeclarative::setSelectionMode(QDataVis::SelectionMode mode) +{ + m_controller->setSelectionMode(mode); +} + +QDataVis::SelectionMode AbstractDeclarative::selectionMode() const +{ + return m_controller->selectionMode(); +} + +void AbstractDeclarative::setFont(const QFont &font) +{ + m_controller->setFont(font); +} + +QFont AbstractDeclarative::font() const +{ + return m_controller->font(); +} + +void AbstractDeclarative::setLabelStyle(QDataVis::LabelStyle style) +{ + m_controller->setLabelStyle(style); +} + +QDataVis::LabelStyle AbstractDeclarative::labelStyle() const +{ + return m_controller->labelStyle(); +} + +void AbstractDeclarative::setGridVisible(bool visible) +{ + m_controller->setGridEnabled(visible); +} + +bool AbstractDeclarative::isGridVisible() const +{ + return m_controller->gridEnabled(); +} + +void AbstractDeclarative::setBackgroundVisible(bool visible) +{ + m_controller->setBackgroundEnabled(visible); +} + +bool AbstractDeclarative::isBackgroundVisible() const +{ + return m_controller->backgroundEnabled(); +} + +void AbstractDeclarative::setShadowQuality(QDataVis::ShadowQuality quality) +{ + m_controller->setShadowQuality(quality); +} + +QDataVis::ShadowQuality AbstractDeclarative::shadowQuality() const +{ + return m_controller->shadowQuality(); +} + +void AbstractDeclarative::setItemLabelFormat(const QString &format) +{ + m_controller->activeDataProxy()->setItemLabelFormat(format); +} + +QString AbstractDeclarative::itemLabelFormat() const +{ + return m_controller->activeDataProxy()->itemLabelFormat(); +} + +void AbstractDeclarative::setSharedController(Abstract3DController *controller) +{ + Q_ASSERT(controller); + m_controller = controller; + QObject::connect(m_controller, &Abstract3DController::shadowQualityChanged, this, + &AbstractDeclarative::handleShadowQualityUpdate); + emit sceneChanged(m_controller->scene()); + QObject::connect(m_controller, &Abstract3DController::activeInputHandlerChanged, this, + &AbstractDeclarative::handleInputHandlerUpdate); + emit inputHandlerChanged(m_controller->activeInputHandler()); +} + +QAbstract3DInputHandler* AbstractDeclarative::inputHandler() const +{ + return m_controller->activeInputHandler(); +} + +void AbstractDeclarative::setInputHandler(QAbstract3DInputHandler *inputHandler) +{ + m_controller->setActiveInputHandler(inputHandler); +} + +void AbstractDeclarative::mouseDoubleClickEvent(QMouseEvent *event) +{ + m_controller->mouseDoubleClickEvent(event); +} + +void AbstractDeclarative::touchEvent(QTouchEvent *event) +{ + m_controller->touchEvent(event); + update(); +} + +void AbstractDeclarative::mousePressEvent(QMouseEvent *event) +{ + QPoint mousePos = event->pos(); + //mousePos.setY(height() - mousePos.y()); + m_controller->mousePressEvent(event, mousePos); +} + +void AbstractDeclarative::mouseReleaseEvent(QMouseEvent *event) +{ + QPoint mousePos = event->pos(); + //mousePos.setY(height() - mousePos.y()); + m_controller->mouseReleaseEvent(event, mousePos); +} + +void AbstractDeclarative::mouseMoveEvent(QMouseEvent *event) +{ + QPoint mousePos = event->pos(); + //mousePos.setY(height() - mousePos.y()); + m_controller->mouseMoveEvent(event, mousePos); +} + +void AbstractDeclarative::wheelEvent(QWheelEvent *event) +{ + m_controller->wheelEvent(event); +} + +void AbstractDeclarative::handleShadowQualityUpdate(QDataVis::ShadowQuality quality) +{ + emit shadowQualityChanged(quality); +} + +void AbstractDeclarative::handleInputHandlerUpdate(QAbstract3DInputHandler *inputHandler) +{ + emit inputHandlerChanged(inputHandler); +} + +QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavisualizationqml2/abstractdeclarative_p.h b/src/datavisualizationqml2/abstractdeclarative_p.h new file mode 100644 index 00000000..41d4a4da --- /dev/null +++ b/src/datavisualizationqml2/abstractdeclarative_p.h @@ -0,0 +1,119 @@ +/**************************************************************************** +** +** 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 ABSTRACTDECLARATIVE_P_H +#define ABSTRACTDECLARATIVE_P_H + +#include "datavisualizationglobal_p.h" +#include "abstract3dcontroller_p.h" +#include "qabstract3dinputhandler.h" + +#include <QAbstractItemModel> +#include <QQuickItem> +#include <QObject> + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +class AbstractDeclarative : public QQuickItem +{ + Q_OBJECT + Q_PROPERTY(QtDataVisualization::QDataVis::SelectionMode selectionMode READ selectionMode WRITE setSelectionMode) + Q_PROPERTY(QtDataVisualization::QDataVis::LabelStyle labelStyle READ labelStyle WRITE setLabelStyle) + Q_PROPERTY(QtDataVisualization::QDataVis::ShadowQuality shadowQuality READ shadowQuality WRITE setShadowQuality) + Q_PROPERTY(Q3DScene* scene READ scene NOTIFY sceneChanged) + Q_PROPERTY(QAbstract3DInputHandler* inputHandler READ inputHandler WRITE setInputHandler NOTIFY inputHandlerChanged) + Q_PROPERTY(QtDataVisualization::QDataVis::Theme theme READ theme WRITE setTheme) + Q_PROPERTY(QFont font READ font WRITE setFont) + Q_PROPERTY(bool gridVisible READ isGridVisible WRITE setGridVisible) + Q_PROPERTY(bool backgroundVisible READ isBackgroundVisible WRITE setBackgroundVisible) + Q_PROPERTY(QString itemLabelFormat READ itemLabelFormat WRITE setItemLabelFormat) + Q_ENUMS(QtDataVisualization::QDataVis::SelectionMode) + Q_ENUMS(QtDataVisualization::QDataVis::ShadowQuality) + Q_ENUMS(QtDataVisualization::QDataVis::LabelStyle) + Q_ENUMS(QtDataVisualization::QDataVis::CameraPreset) + Q_ENUMS(QtDataVisualization::QDataVis::Theme) + +public: + explicit AbstractDeclarative(QQuickItem *parent = 0); + virtual ~AbstractDeclarative(); + + virtual Q3DScene *scene() const; + + virtual QAbstract3DInputHandler *inputHandler() const; + virtual void setInputHandler(QAbstract3DInputHandler *inputHandler); + + virtual void setTheme(QDataVis::Theme theme); + virtual QDataVis::Theme theme() const; + + virtual void setSelectionMode(QDataVis::SelectionMode mode); + virtual QDataVis::SelectionMode selectionMode() const; + + virtual void setFont(const QFont &font); + virtual QFont font() const; + + virtual void setLabelStyle(QDataVis::LabelStyle style); + virtual QDataVis::LabelStyle labelStyle() const; + + virtual void setGridVisible(bool visible); + virtual bool isGridVisible() const; + + virtual void setBackgroundVisible(bool visible); + virtual bool isBackgroundVisible() const; + + virtual void setShadowQuality(QDataVis::ShadowQuality quality); + virtual QDataVis::ShadowQuality shadowQuality() const; + + virtual void setItemLabelFormat(const QString &format); + virtual QString itemLabelFormat() const; + + void setSharedController(Abstract3DController *controller); + +protected: + virtual void mouseDoubleClickEvent(QMouseEvent *event); + virtual void touchEvent(QTouchEvent *event); + virtual void mousePressEvent(QMouseEvent *event); + virtual void mouseReleaseEvent(QMouseEvent *event); + virtual void mouseMoveEvent(QMouseEvent *event); + virtual void wheelEvent(QWheelEvent *event); + + // Used to detect when shadow quality changes autonomously due to e.g. resizing. + virtual void handleShadowQualityUpdate(QDataVis::ShadowQuality quality); + virtual void handleInputHandlerUpdate(QAbstract3DInputHandler *inputHandler); +signals: + // Signals shadow quality changes. + void shadowQualityChanged(QDataVis::ShadowQuality quality); + void sceneChanged(Q3DScene *scene); + void inputHandlerChanged(QAbstract3DInputHandler *inputHandler); + +private: + Abstract3DController *m_controller; +}; + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif // ABSTRACTDECLARATIVE_P_H diff --git a/src/datavisualizationqml2/colorgradient.cpp b/src/datavisualizationqml2/colorgradient.cpp new file mode 100644 index 00000000..43efbd1c --- /dev/null +++ b/src/datavisualizationqml2/colorgradient.cpp @@ -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 +** +****************************************************************************/ + +#include "colorgradient_p.h" + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +ColorGradientStop::ColorGradientStop(QObject *parent) + : QObject(parent) +{ +} + +qreal ColorGradientStop::position() const +{ + return m_position; +} + +void ColorGradientStop::setPosition(qreal position) +{ + m_position = position; + updateGradient(); +} + +QColor ColorGradientStop::color() const +{ + return m_color; +} + +void ColorGradientStop::setColor(const QColor &color) +{ + m_color = color; + updateGradient(); +} + +void ColorGradientStop::updateGradient() +{ + if (ColorGradient *grad = qobject_cast<ColorGradient*>(parent())) + grad->doUpdate(); +} + +ColorGradient::ColorGradient(QObject *parent) +: QObject(parent) +{ +} + +ColorGradient::~ColorGradient() +{ +} + +QQmlListProperty<ColorGradientStop> ColorGradient::stops() +{ + return QQmlListProperty<ColorGradientStop>(this, m_stops); +} + +void ColorGradient::doUpdate() +{ + emit updated(); +} + +QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavisualizationqml2/colorgradient_p.h b/src/datavisualizationqml2/colorgradient_p.h new file mode 100644 index 00000000..37d3e407 --- /dev/null +++ b/src/datavisualizationqml2/colorgradient_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 COLORGRADIENT_P_H +#define COLORGRADIENT_P_H + +#include "datavisualizationglobal_p.h" +#include <QColor> +#include <QQmlListProperty> + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +class ColorGradientStop : public QObject +{ + Q_OBJECT + + Q_PROPERTY(qreal position READ position WRITE setPosition) + Q_PROPERTY(QColor color READ color WRITE setColor) + +public: + ColorGradientStop(QObject *parent = 0); + + qreal position() const; + void setPosition(qreal position); + + QColor color() const; + void setColor(const QColor &color); + +private: + void updateGradient(); + +private: + qreal m_position; + QColor m_color; +}; + +class ColorGradient : public QObject +{ + Q_OBJECT + + Q_PROPERTY(QQmlListProperty<ColorGradientStop> stops READ stops) + Q_CLASSINFO("DefaultProperty", "stops") + +public: + ColorGradient(QObject *parent = 0); + ~ColorGradient(); + + QQmlListProperty<ColorGradientStop> stops(); + +Q_SIGNALS: + void updated(); + +private: + void doUpdate(); + +private: + QList<ColorGradientStop *> m_stops; + + friend class ColorGradientStop; + friend class DeclarativeSurface; +}; + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif diff --git a/src/datavis3dqml2/datavis3dqml2.pro b/src/datavisualizationqml2/datavisualizationqml2.pro index c994c5be..d5191c62 100644 --- a/src/datavis3dqml2/datavis3dqml2.pro +++ b/src/datavisualizationqml2/datavisualizationqml2.pro @@ -1,38 +1,42 @@ TEMPLATE = lib -TARGET = datavis3dqml2 -QT += qml quick datavis3d +TARGET = datavisualizationqml2 +QT += qml quick datavisualization CONFIG += qt plugin TARGET = $$qtLibraryTarget($$TARGET) -uri = com.digia.QtDataVis3D +uri = com.digia.QtDataVisualization static { - DEFINES += QT_DATAVIS3D_STATICLIB + DEFINES += QT_DATAVISUALIZATION_STATICLIB CONFIG -= static staticlib } # Input -INCLUDEPATH += ../datavis3d/engine \ - ../datavis3d/global \ - ../datavis3d/data +INCLUDEPATH += ../datavisualization/engine \ + ../datavisualization/global \ + ../datavisualization/data SOURCES += \ - datavis3dqml2_plugin.cpp \ + datavisualizationqml2_plugin.cpp \ declarativebars.cpp \ declarativebarsrenderer.cpp \ declarativescatter.cpp \ declarativescatterrenderer.cpp \ - declarativemaps.cpp \ - declarativemapsrenderer.cpp + declarativesurface.cpp \ + declarativesurfacerenderer.cpp \ + abstractdeclarative.cpp \ + colorgradient.cpp HEADERS += \ - datavis3dqml2_plugin.h \ + datavisualizationqml2_plugin.h \ declarativebars_p.h \ declarativebarsrenderer_p.h \ declarativescatter_p.h \ declarativescatterrenderer_p.h \ - declarativemaps_p.h \ - declarativemapsrenderer_p.h + declarativesurface_p.h \ + declarativesurfacerenderer_p.h \ + abstractdeclarative_p.h \ + colorgradient_p.h OTHER_FILES = qmldir diff --git a/src/datavisualizationqml2/datavisualizationqml2_plugin.cpp b/src/datavisualizationqml2/datavisualizationqml2_plugin.cpp new file mode 100644 index 00000000..b98f72ac --- /dev/null +++ b/src/datavisualizationqml2/datavisualizationqml2_plugin.cpp @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** 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 "datavisualizationqml2_plugin.h" + +#include <qqml.h> + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +void Datavis3Dqml2Plugin::registerTypes(const char *uri) +{ + // @uri com.digia.QtDataVisualization + qmlRegisterUncreatableType<const QAbstractItemModel>(uri, 1, 0, "AbstractItemModel", + QLatin1String("Trying to create uncreatable: AbstractItemModel.")); + qmlRegisterUncreatableType<QDataVis>(uri, 1, 0, "DataVis", + QLatin1String("Trying to create uncreatable: DataVis.")); + qmlRegisterUncreatableType<Q3DAbstractAxis>(uri, 1, 0, "AbstractAxis3D", + QLatin1String("Trying to create uncreatable: AbstractAxis.")); + qmlRegisterUncreatableType<QAbstractDataProxy>(uri, 1, 0, "AbstractDataProxy", + QLatin1String("Trying to create uncreatable: AbstractDataProxy.")); + qmlRegisterUncreatableType<QBarDataProxy>(uri, 1, 0, "BarDataProxy", + QLatin1String("Trying to create uncreatable: BarDataProxy.")); + qmlRegisterUncreatableType<QScatterDataProxy>(uri, 1, 0, "ScatterDataProxy", + QLatin1String("Trying to create uncreatable: ScatterDataProxy.")); + qmlRegisterUncreatableType<QSurfaceDataProxy>(uri, 1, 0, "SurfaceDataProxy", + QLatin1String("Trying to create uncreatable: SurfaceDataProxy.")); + qmlRegisterUncreatableType<AbstractDeclarative>(uri, 1, 0, "AbstractGraph3D", + QLatin1String("Trying to create uncreatable: AbstractGraph3D.")); + qmlRegisterUncreatableType<Q3DScene>(uri, 1, 0, "Scene3D", + QLatin1String("Trying to create uncreatable: Scene3D.")); + + qmlRegisterType<QItemModelBarDataMapping>(uri, 1, 0, "BarDataMapping"); + qmlRegisterType<QItemModelScatterDataMapping>(uri, 1, 0, "ScatterDataMapping"); + qmlRegisterType<QItemModelSurfaceDataMapping>(uri, 1, 0, "SurfaceDataMapping"); + + qmlRegisterType<DeclarativeBars>(uri, 1, 0, "Bars3D"); + qmlRegisterType<DeclarativeScatter>(uri, 1, 0, "Scatter3D"); + qmlRegisterType<DeclarativeSurface>(uri, 1, 0, "Surface3D"); + + qmlRegisterType<Q3DValueAxis>(uri, 1, 0, "ValueAxis3D"); + qmlRegisterType<Q3DCategoryAxis>(uri, 1, 0, "CategoryAxis3D"); + + qmlRegisterType<Q3DCamera>(uri, 1, 0, "Camera3D"); + + qmlRegisterType<QItemModelBarDataProxy>(uri, 1, 0, "ItemModelBarDataProxy"); + qmlRegisterType<QItemModelScatterDataProxy>(uri, 1, 0, "ItemModelScatterDataProxy"); + qmlRegisterType<QItemModelSurfaceDataProxy>(uri, 1, 0, "ItemModelSurfaceDataProxy"); + qmlRegisterType<QHeightMapSurfaceDataProxy>(uri, 1, 0, "HeightMapSurfaceDataProxy"); + + qmlRegisterType<ColorGradientStop>(uri, 1, 0, "ColorGradientStop"); + qmlRegisterType<ColorGradient>(uri, 1, 0, "ColorGradient"); +} + +QT_DATAVISUALIZATION_END_NAMESPACE + diff --git a/src/datavisualizationqml2/datavisualizationqml2_plugin.h b/src/datavisualizationqml2/datavisualizationqml2_plugin.h new file mode 100644 index 00000000..c0d7c4b8 --- /dev/null +++ b/src/datavisualizationqml2/datavisualizationqml2_plugin.h @@ -0,0 +1,88 @@ +/**************************************************************************** +** +** 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 DATAVISUALIZATIONQML2_PLUGIN_H +#define DATAVISUALIZATIONQML2_PLUGIN_H + +#include "datavisualizationglobal_p.h" +#include "declarativebars_p.h" +#include "declarativescatter_p.h" +#include "declarativesurface_p.h" +#include "qitemmodelbardatamapping.h" +#include "qitemmodelscatterdatamapping.h" +#include "qitemmodelsurfacedatamapping.h" +#include "qitemmodelbardataproxy.h" +#include "qitemmodelscatterdataproxy.h" +#include "qitemmodelsurfacedataproxy.h" +#include "qheightmapsurfacedataproxy.h" +#include "q3dvalueaxis.h" +#include "q3dcategoryaxis.h" +#include "q3dobject.h" +#include "q3dcamera.h" +#include "q3dscene.h" + +#include <QQmlExtensionPlugin> + +QT_DATAVISUALIZATION_USE_NAMESPACE + +QML_DECLARE_TYPE(AbstractDeclarative) +QML_DECLARE_TYPE(DeclarativeBars) +QML_DECLARE_TYPE(DeclarativeScatter) +QML_DECLARE_TYPE(DeclarativeSurface) + +QML_DECLARE_TYPE(QItemModelBarDataMapping) +QML_DECLARE_TYPE(QItemModelScatterDataMapping) +QML_DECLARE_TYPE(QItemModelSurfaceDataMapping) + +QML_DECLARE_TYPE(const QAbstractItemModel) +QML_DECLARE_TYPE(QDataVis) + +QML_DECLARE_TYPE(Q3DAbstractAxis) +QML_DECLARE_TYPE(Q3DCategoryAxis) +QML_DECLARE_TYPE(Q3DValueAxis) + +QML_DECLARE_TYPE(Q3DScene) +QML_DECLARE_TYPE(Q3DCamera) + +QML_DECLARE_TYPE(QAbstractDataProxy) +QML_DECLARE_TYPE(QBarDataProxy) +QML_DECLARE_TYPE(QItemModelBarDataProxy) +QML_DECLARE_TYPE(QScatterDataProxy) +QML_DECLARE_TYPE(QItemModelScatterDataProxy) +QML_DECLARE_TYPE(QSurfaceDataProxy) +QML_DECLARE_TYPE(QItemModelSurfaceDataProxy) +QML_DECLARE_TYPE(QHeightMapSurfaceDataProxy) + +QML_DECLARE_TYPE(ColorGradientStop) +QML_DECLARE_TYPE(ColorGradient) + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +class Datavis3Dqml2Plugin : public QQmlExtensionPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") + +public: + void registerTypes(const char *uri); +}; + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif // DATAVISUALIZATIONQML2_PLUGIN_H + diff --git a/src/datavisualizationqml2/declarativebars.cpp b/src/datavisualizationqml2/declarativebars.cpp new file mode 100644 index 00000000..9ed80106 --- /dev/null +++ b/src/datavisualizationqml2/declarativebars.cpp @@ -0,0 +1,214 @@ +/**************************************************************************** +** +** 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 "declarativebars_p.h" +#include "declarativebarsrenderer_p.h" +#include "q3dvalueaxis.h" +#include "qitemmodelbardataproxy.h" +#include "theme_p.h" + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +const QString smoothString(QStringLiteral("Smooth")); + +DeclarativeBars::DeclarativeBars(QQuickItem *parent) + : AbstractDeclarative(parent), + m_shared(0), + m_initialisedSize(0, 0) +{ + setFlags(QQuickItem::ItemHasContents); + setAcceptedMouseButtons(Qt::AllButtons); + + // TODO: These seem to have no effect; find a way to activate anti-aliasing + setAntialiasing(true); + setSmooth(true); + + // Create the shared component on the main GUI thread. + m_shared = new Bars3DController(boundingRect().toRect()); + AbstractDeclarative::setSharedController(m_shared); + QObject::connect(m_shared, &Bars3DController::selectedBarPosChanged, this, + &DeclarativeBars::selectedBarPosChanged); + + QItemModelBarDataProxy *proxy = new QItemModelBarDataProxy; + m_shared->setActiveDataProxy(proxy); +} + +DeclarativeBars::~DeclarativeBars() +{ + delete m_shared; +} + + +QSGNode *DeclarativeBars::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) +{ + // If old node exists and has right size, reuse it. + if (oldNode && m_initialisedSize == boundingRect().size().toSize()) { + // Update bounding rectangle (that has same size as before). + static_cast<DeclarativeBarsRenderer *>( oldNode )->setRect(boundingRect()); + return oldNode; + } + + // Create a new render node when size changes or if there is no node yet + m_initialisedSize = boundingRect().size().toSize(); + + // Delete old node + if (oldNode) + delete oldNode; + + // Create a new one and set it's bounding rectangle + DeclarativeBarsRenderer *node = new DeclarativeBarsRenderer(window(), m_shared); + node->setRect(boundingRect()); + m_shared->setBoundingRect(boundingRect().toRect()); + return node; +} + +void DeclarativeBars::setBarColor(const QColor &baseColor, bool uniform) +{ + m_shared->setObjectColor(baseColor, uniform); +} + +void DeclarativeBars::setDataProxy(QBarDataProxy *dataProxy) +{ + m_shared->setActiveDataProxy(dataProxy); +} + +QBarDataProxy *DeclarativeBars::dataProxy() const +{ + return static_cast<QBarDataProxy *>(m_shared->activeDataProxy()); +} + +Q3DCategoryAxis *DeclarativeBars::rowAxis() const +{ + return static_cast<Q3DCategoryAxis *>(m_shared->axisX()); +} + +void DeclarativeBars::setRowAxis(Q3DCategoryAxis *axis) +{ + m_shared->setAxisX(axis); +} + +Q3DValueAxis *DeclarativeBars::valueAxis() const +{ + return static_cast<Q3DValueAxis *>(m_shared->axisY()); +} + +void DeclarativeBars::setValueAxis(Q3DValueAxis *axis) +{ + m_shared->setAxisY(axis); +} + +Q3DCategoryAxis *DeclarativeBars::columnAxis() const +{ + return static_cast<Q3DCategoryAxis *>(m_shared->axisZ()); +} + +void DeclarativeBars::setColumnAxis(Q3DCategoryAxis *axis) +{ + m_shared->setAxisZ(axis); +} + +void DeclarativeBars::setBarThickness(qreal thicknessRatio) +{ + m_shared->setBarSpecs(GLfloat(thicknessRatio), barSpacing(), isBarSpacingRelative()); +} + +qreal DeclarativeBars::barThickness() const +{ + return m_shared->barThickness(); +} + +void DeclarativeBars::setBarSpacing(QSizeF spacing) +{ + m_shared->setBarSpecs(GLfloat(barThickness()), spacing, isBarSpacingRelative()); +} + +QSizeF DeclarativeBars::barSpacing() const +{ + return m_shared->barSpacing(); +} + +void DeclarativeBars::setBarSpacingRelative(bool relative) +{ + m_shared->setBarSpecs(GLfloat(barThickness()), barSpacing(), relative); +} + +bool DeclarativeBars::isBarSpacingRelative() const +{ + return m_shared->isBarSpecRelative(); +} + +void DeclarativeBars::setBarType(QDataVis::MeshStyle style) +{ + QString objFile = m_shared->meshFileName(); + bool smooth = objFile.endsWith(smoothString); + m_shared->setBarType(style, smooth); +} + +QDataVis::MeshStyle DeclarativeBars::barType() const +{ + QString objFile = m_shared->meshFileName(); + if (objFile.contains("/sphere")) + return QDataVis::MeshStyleSpheres; + else + return QDataVis::MeshStyleDots; +} + +void DeclarativeBars::setBarSmoothingEnabled(bool enabled) +{ + QString objFile = m_shared->meshFileName(); + if (objFile.endsWith(smoothString)) { + if (enabled) + return; // Already smooth; do nothing + else // Rip Smooth off the end + objFile.resize(objFile.indexOf(smoothString)); + } else { + if (!enabled) // Already flat; do nothing + return; + else // Append Smooth to the end + objFile.append(smoothString); + } + m_shared->setMeshFileName(objFile); +} + +bool DeclarativeBars::isBarSmoothingEnabled() const +{ + QString objFile = m_shared->meshFileName(); + return objFile.endsWith(smoothString); +} + +void DeclarativeBars::setMeshFileName(const QString &objFileName) +{ + m_shared->setMeshFileName(objFileName); +} + +QString DeclarativeBars::meshFileName() const +{ + return m_shared->meshFileName(); +} + +void DeclarativeBars::setSelectedBarPos(const QPointF &position) +{ + m_shared->setSelectedBarPos(position.toPoint()); +} + +QPointF DeclarativeBars::selectedBarPos() const +{ + return QPointF(m_shared->selectedBarPos()); +} + +QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavisualizationqml2/declarativebars_p.h b/src/datavisualizationqml2/declarativebars_p.h new file mode 100644 index 00000000..dfbf9934 --- /dev/null +++ b/src/datavisualizationqml2/declarativebars_p.h @@ -0,0 +1,113 @@ +/**************************************************************************** +** +** 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 DECLARATIVEBARS_P_H +#define DECLARATIVEBARS_P_H + +#include "datavisualizationglobal_p.h" +#include "abstractdeclarative_p.h" +#include "bars3dcontroller_p.h" +#include "declarativebars_p.h" +#include "q3dvalueaxis.h" +#include "q3dcategoryaxis.h" +#include "qbardataproxy.h" + +#include <QAbstractItemModel> +#include <QQuickItem> +#include <QObject> +#include <QQuickWindow> + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +class DeclarativeBars : public AbstractDeclarative +{ + Q_OBJECT + Q_PROPERTY(QBarDataProxy *dataProxy READ dataProxy WRITE setDataProxy) + Q_PROPERTY(Q3DCategoryAxis *rowAxis READ rowAxis WRITE setRowAxis) + Q_PROPERTY(Q3DValueAxis *valueAxis READ valueAxis WRITE setValueAxis) + Q_PROPERTY(Q3DCategoryAxis *columnAxis READ columnAxis WRITE setColumnAxis) + Q_PROPERTY(QtDataVisualization::QDataVis::MeshStyle barType READ barType WRITE setBarType) + Q_PROPERTY(qreal barThickness READ barThickness WRITE setBarThickness) + Q_PROPERTY(QSizeF barSpacing READ barSpacing WRITE setBarSpacing) + Q_PROPERTY(bool barSpacingRelative READ isBarSpacingRelative WRITE setBarSpacingRelative) + Q_PROPERTY(bool barSmoothingEnabled READ isBarSmoothingEnabled WRITE setBarSmoothingEnabled) + Q_PROPERTY(QString meshFileName READ meshFileName WRITE setMeshFileName) + Q_PROPERTY(QPointF selectedBarPos READ selectedBarPos WRITE setSelectedBarPos NOTIFY selectedBarPosChanged) + Q_ENUMS(QtDataVisualization::QDataVis::MeshStyle) + +public: + explicit DeclarativeBars(QQuickItem *parent = 0); + ~DeclarativeBars(); + + Q_INVOKABLE void setBarColor(const QColor &baseColor, bool uniform = true); + + QBarDataProxy *dataProxy() const; + void setDataProxy(QBarDataProxy *dataProxy); + + Q3DCategoryAxis *rowAxis() const; + void setRowAxis(Q3DCategoryAxis *axis); + Q3DValueAxis *valueAxis() const; + void setValueAxis(Q3DValueAxis *axis); + Q3DCategoryAxis *columnAxis() const; + void setColumnAxis(Q3DCategoryAxis *axis); + + void setBarThickness(qreal thicknessRatio); + qreal barThickness() const; + + void setBarSpacing(QSizeF spacing); + QSizeF barSpacing() const; + + void setBarSpacingRelative(bool relative); + bool isBarSpacingRelative() const; + + void setBarType(QDataVis::MeshStyle style); + QDataVis::MeshStyle barType() const; + + void setBarSmoothingEnabled(bool enabled); + bool isBarSmoothingEnabled() const; + + void setMeshFileName(const QString &objFileName); + QString meshFileName() const; + + void setSelectedBarPos(const QPointF &position); + QPointF selectedBarPos() const; + +signals: + void selectedBarPosChanged(const QPointF &position); + +protected: + QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *); + +private: + Bars3DController *m_shared; + QSize m_initialisedSize; +}; + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif diff --git a/src/datavis3dqml2/declarativebarsrenderer.cpp b/src/datavisualizationqml2/declarativebarsrenderer.cpp index 1ecd4003..3925e062 100644 --- a/src/datavis3dqml2/declarativebarsrenderer.cpp +++ b/src/datavisualizationqml2/declarativebarsrenderer.cpp @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -21,16 +21,20 @@ #include <QtQuick/QQuickWindow> #include <QtGui/QOpenGLFramebufferObject> -QT_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVISUALIZATION_BEGIN_NAMESPACE -DeclarativeBarsRenderer::DeclarativeBarsRenderer(QQuickWindow *window, Bars3dController *renderer) +DeclarativeBarsRenderer::DeclarativeBarsRenderer(QQuickWindow *window, Bars3DController *renderer) : m_fbo(0), m_texture(0), m_window(window), m_barsRenderer(renderer) { - connect(m_window, SIGNAL(beforeSynchronizing()), this, SLOT(synchDataToRenderer()), Qt::DirectConnection); - connect(m_window, SIGNAL(beforeRendering()), this, SLOT(renderFBO()), Qt::DirectConnection); + connect(m_window, &QQuickWindow::beforeSynchronizing, this, + &DeclarativeBarsRenderer::synchDataToRenderer, Qt::DirectConnection); + connect(m_window, &QQuickWindow::beforeRendering, this, + &DeclarativeBarsRenderer::renderFBO, Qt::DirectConnection); + connect(m_barsRenderer, &Abstract3DController::needRender, m_window, + &QQuickWindow::update); } DeclarativeBarsRenderer::~DeclarativeBarsRenderer() @@ -78,9 +82,6 @@ void DeclarativeBarsRenderer::renderFBO() m_barsRenderer->render(m_fbo->handle()); m_fbo->release(); - - // New view is in the FBO, request repaint of scene graph - m_window->update(); } -QT_DATAVIS3D_END_NAMESPACE +QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavis3dqml2/declarativebarsrenderer_p.h b/src/datavisualizationqml2/declarativebarsrenderer_p.h index 1b40d3df..3be9b911 100644 --- a/src/datavis3dqml2/declarativebarsrenderer_p.h +++ b/src/datavisualizationqml2/declarativebarsrenderer_p.h @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -20,7 +20,7 @@ // W A R N I N G // ------------- // -// This file is not part of the QtDataVis3D API. It exists purely as an +// 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. // @@ -29,7 +29,7 @@ #ifndef DECLARATIVEBARSRENDERER_H #define DECLARATIVEBARSRENDERER_H -#include "datavis3dglobal_p.h" +#include "datavisualizationglobal_p.h" #include "bars3dcontroller_p.h" #include <qsgsimpletexturenode.h> @@ -37,14 +37,14 @@ class QOpenGLFramebufferObject; class QSGTexture; class QQuickWindow; -QT_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVISUALIZATION_BEGIN_NAMESPACE class DeclarativeBarsRenderer : public QObject, public QSGSimpleTextureNode { Q_OBJECT public: - DeclarativeBarsRenderer(QQuickWindow *window, Bars3dController *shared); + DeclarativeBarsRenderer(QQuickWindow *window, Bars3DController *shared); ~DeclarativeBarsRenderer(); public slots: @@ -57,9 +57,9 @@ private: QOpenGLFramebufferObject *m_fbo; QSGTexture *m_texture; QQuickWindow *m_window; - Bars3dController *m_barsRenderer; + Bars3DController *m_barsRenderer; }; -QT_DATAVIS3D_END_NAMESPACE +QT_DATAVISUALIZATION_END_NAMESPACE #endif diff --git a/src/datavisualizationqml2/declarativescatter.cpp b/src/datavisualizationqml2/declarativescatter.cpp new file mode 100644 index 00000000..346abec2 --- /dev/null +++ b/src/datavisualizationqml2/declarativescatter.cpp @@ -0,0 +1,168 @@ +/**************************************************************************** +** +** 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 "declarativescatter_p.h" +#include "declarativescatterrenderer_p.h" +#include "qitemmodelscatterdataproxy.h" +#include "theme_p.h" + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +const QString smoothString(QStringLiteral("Smooth")); + +DeclarativeScatter::DeclarativeScatter(QQuickItem *parent) + : AbstractDeclarative(parent), + m_shared(0), + m_initialisedSize(0, 0) +{ + setFlags(QQuickItem::ItemHasContents); + setAcceptedMouseButtons(Qt::AllButtons); + + // TODO: These seem to have no effect; find a way to activate anti-aliasing + setAntialiasing(true); + setSmooth(true); + + // Create the shared component on the main GUI thread. + m_shared = new Scatter3DController(boundingRect().toRect()); + setSharedController(m_shared); + m_shared->setActiveDataProxy(new QItemModelScatterDataProxy); +} + +DeclarativeScatter::~DeclarativeScatter() +{ + delete m_shared; +} + +QSGNode *DeclarativeScatter::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) +{ + // If old node exists and has right size, reuse it. + if (oldNode && m_initialisedSize == boundingRect().size().toSize()) { + // Update bounding rectangle (that has same size as before). + static_cast<DeclarativeScatterRenderer *>( oldNode )->setRect(boundingRect()); + return oldNode; + } + + // Create a new render node when size changes or if there is no node yet + m_initialisedSize = boundingRect().size().toSize(); + + // Delete old node + if (oldNode) + delete oldNode; + + // Create a new one and set it's bounding rectangle + DeclarativeScatterRenderer *node = new DeclarativeScatterRenderer(window(), m_shared); + node->setRect(boundingRect()); + m_shared->setBoundingRect(boundingRect().toRect()); + return node; +} + +void DeclarativeScatter::setObjectColor(const QColor &baseColor, bool uniform) +{ + m_shared->setObjectColor(baseColor, uniform); +} + +QScatterDataProxy *DeclarativeScatter::dataProxy() const +{ + return static_cast<QScatterDataProxy *>(m_shared->activeDataProxy()); +} + +void DeclarativeScatter::setDataProxy(QScatterDataProxy *dataProxy) +{ + m_shared->setActiveDataProxy(dataProxy); +} + +Q3DValueAxis *DeclarativeScatter::axisX() const +{ + return static_cast<Q3DValueAxis *>(m_shared->axisX()); +} + +void DeclarativeScatter::setAxisX(Q3DValueAxis *axis) +{ + m_shared->setAxisX(axis); +} + +Q3DValueAxis *DeclarativeScatter::axisY() const +{ + return static_cast<Q3DValueAxis *>(m_shared->axisY()); +} + +void DeclarativeScatter::setAxisY(Q3DValueAxis *axis) +{ + m_shared->setAxisY(axis); +} + +Q3DValueAxis *DeclarativeScatter::axisZ() const +{ + return static_cast<Q3DValueAxis *>(m_shared->axisZ()); +} + +void DeclarativeScatter::setAxisZ(Q3DValueAxis *axis) +{ + m_shared->setAxisZ(axis); +} + +void DeclarativeScatter::setObjectType(QDataVis::MeshStyle style) +{ + QString objFile = m_shared->meshFileName(); + bool smooth = objFile.endsWith(smoothString); + m_shared->setObjectType(style, smooth); +} + +QDataVis::MeshStyle DeclarativeScatter::objectType() const +{ + QString objFile = m_shared->meshFileName(); + if (objFile.contains("/sphere")) + return QDataVis::MeshStyleSpheres; + else + return QDataVis::MeshStyleDots; +} + +void DeclarativeScatter::setObjectSmoothingEnabled(bool enabled) +{ + QString objFile = m_shared->meshFileName(); + if (objFile.endsWith(smoothString)) { + if (enabled) + return; // Already smooth; do nothing + else // Rip Smooth off the end + objFile.resize(objFile.indexOf(smoothString)); + } else { + if (!enabled) // Already flat; do nothing + return; + else // Append Smooth to the end + objFile.append(smoothString); + } + m_shared->setMeshFileName(objFile); +} + +bool DeclarativeScatter::isObjectSmoothingEnabled() const +{ + QString objFile = m_shared->meshFileName(); + return objFile.endsWith(smoothString); +} + +void DeclarativeScatter::setMeshFileName(const QString &objFileName) +{ + m_shared->setMeshFileName(objFileName); +} + +QString DeclarativeScatter::meshFileName() const +{ + return m_shared->meshFileName(); +} + +QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavisualizationqml2/declarativescatter_p.h b/src/datavisualizationqml2/declarativescatter_p.h new file mode 100644 index 00000000..cc16e770 --- /dev/null +++ b/src/datavisualizationqml2/declarativescatter_p.h @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** 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 DECLARATIVESCATTER_P_H +#define DECLARATIVESCATTER_P_H + +#include "datavisualizationglobal_p.h" +#include "abstractdeclarative_p.h" +#include "scatter3dcontroller_p.h" +#include "declarativescatter_p.h" +#include "q3dvalueaxis.h" +#include "qscatterdataproxy.h" + +#include <QAbstractItemModel> +#include <QQuickItem> +#include <QObject> + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +class DeclarativeScatter : public AbstractDeclarative +{ + Q_OBJECT + Q_PROPERTY(QScatterDataProxy *dataProxy READ dataProxy WRITE setDataProxy) + Q_PROPERTY(Q3DValueAxis *axisX READ axisX WRITE setAxisX) + Q_PROPERTY(Q3DValueAxis *axisY READ axisY WRITE setAxisY) + Q_PROPERTY(Q3DValueAxis *axisZ READ axisZ WRITE setAxisZ) + Q_PROPERTY(QtDataVisualization::QDataVis::MeshStyle objectType READ objectType WRITE setObjectType) + Q_PROPERTY(bool objectSmoothingEnabled READ isObjectSmoothingEnabled WRITE setObjectSmoothingEnabled) + Q_PROPERTY(QString meshFileName READ meshFileName WRITE setMeshFileName) + Q_PROPERTY(QString itemLabelFormat READ itemLabelFormat WRITE setItemLabelFormat) + Q_ENUMS(QtDataVisualization::QDataVis::MeshStyle) + +public: + explicit DeclarativeScatter(QQuickItem *parent = 0); + ~DeclarativeScatter(); + + Q_INVOKABLE void setObjectColor(const QColor &baseColor, bool uniform = true); + + QScatterDataProxy *dataProxy() const; + void setDataProxy(QScatterDataProxy *dataProxy); + + Q3DValueAxis *axisX() const; + void setAxisX(Q3DValueAxis *axis); + Q3DValueAxis *axisY() const; + void setAxisY(Q3DValueAxis *axis); + Q3DValueAxis *axisZ() const; + void setAxisZ(Q3DValueAxis *axis); + + void setObjectType(QDataVis::MeshStyle style); + QDataVis::MeshStyle objectType() const; + + void setObjectSmoothingEnabled(bool enabled); + bool isObjectSmoothingEnabled() const; + + void setMeshFileName(const QString &objFileName); + QString meshFileName() const; + +protected: + Scatter3DController *m_shared; + QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *); + +private: + QSize m_initialisedSize; +}; + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif diff --git a/src/datavis3dqml2/declarativescatterrenderer.cpp b/src/datavisualizationqml2/declarativescatterrenderer.cpp index 23c59c26..39aaa22e 100644 --- a/src/datavis3dqml2/declarativescatterrenderer.cpp +++ b/src/datavisualizationqml2/declarativescatterrenderer.cpp @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -21,7 +21,7 @@ #include <QtQuick/QQuickWindow> #include <QtGui/QOpenGLFramebufferObject> -QT_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVISUALIZATION_BEGIN_NAMESPACE DeclarativeScatterRenderer::DeclarativeScatterRenderer(QQuickWindow *window, Scatter3DController *renderer) @@ -30,8 +30,12 @@ DeclarativeScatterRenderer::DeclarativeScatterRenderer(QQuickWindow *window, m_window(window), m_scatterRenderer(renderer) { - connect(m_window, SIGNAL(beforeSynchronizing()), this, SLOT(synchDataToRenderer()), Qt::DirectConnection); - connect(m_window, SIGNAL(beforeRendering()), this, SLOT(renderFBO()), Qt::DirectConnection); + connect(m_window, &QQuickWindow::beforeSynchronizing, this, + &DeclarativeScatterRenderer::synchDataToRenderer, Qt::DirectConnection); + connect(m_window, &QQuickWindow::beforeRendering, this, + &DeclarativeScatterRenderer::renderFBO, Qt::DirectConnection); + connect(m_scatterRenderer, &Abstract3DController::needRender, m_window, + &QQuickWindow::update); } DeclarativeScatterRenderer::~DeclarativeScatterRenderer() @@ -79,9 +83,6 @@ void DeclarativeScatterRenderer::renderFBO() m_scatterRenderer->render(m_fbo->handle()); m_fbo->release(); - - // New view is in the FBO, request repaint of scene graph - m_window->update(); } -QT_DATAVIS3D_END_NAMESPACE +QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavis3dqml2/declarativescatterrenderer_p.h b/src/datavisualizationqml2/declarativescatterrenderer_p.h index 498b1d83..0bbd01ec 100644 --- a/src/datavis3dqml2/declarativescatterrenderer_p.h +++ b/src/datavisualizationqml2/declarativescatterrenderer_p.h @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -20,7 +20,7 @@ // W A R N I N G // ------------- // -// This file is not part of the QtDataVis3D API. It exists purely as an +// 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. // @@ -29,7 +29,7 @@ #ifndef DECLARATIVESCATTERRENDERER_P_H #define DECLARATIVESCATTERRENDERER_P_H -#include "datavis3dglobal_p.h" +#include "datavisualizationglobal_p.h" #include "scatter3dcontroller_p.h" #include <qsgsimpletexturenode.h> @@ -37,7 +37,7 @@ class QOpenGLFramebufferObject; class QSGTexture; class QQuickWindow; -QT_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVISUALIZATION_BEGIN_NAMESPACE class DeclarativeScatterRenderer : public QObject, public QSGSimpleTextureNode { @@ -60,6 +60,6 @@ private: Scatter3DController *m_scatterRenderer; }; -QT_DATAVIS3D_END_NAMESPACE +QT_DATAVISUALIZATION_END_NAMESPACE #endif diff --git a/src/datavisualizationqml2/declarativesurface.cpp b/src/datavisualizationqml2/declarativesurface.cpp new file mode 100644 index 00000000..8375fa53 --- /dev/null +++ b/src/datavisualizationqml2/declarativesurface.cpp @@ -0,0 +1,185 @@ +/**************************************************************************** +** +** 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 "declarativesurface_p.h" +#include "declarativesurfacerenderer_p.h" +#include "q3dvalueaxis.h" +#include "qitemmodelsurfacedataproxy.h" +#include "theme_p.h" + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +DeclarativeSurface::DeclarativeSurface(QQuickItem *parent) + : AbstractDeclarative(parent), + m_shared(0), + m_initialisedSize(0, 0), + m_gradient(0) +{ + setFlags(QQuickItem::ItemHasContents); + setAcceptedMouseButtons(Qt::AllButtons); + + // TODO: These seem to have no effect; find a way to activate anti-aliasing + setAntialiasing(true); + setSmooth(true); + + // Create the shared component on the main GUI thread. + m_shared = new Surface3DController(boundingRect().toRect()); + setSharedController(m_shared); + + QItemModelSurfaceDataProxy *proxy = new QItemModelSurfaceDataProxy; + m_shared->setActiveDataProxy(proxy); +} + +DeclarativeSurface::~DeclarativeSurface() +{ + delete m_shared; +} + +void DeclarativeSurface::handleGradientUpdate() +{ + if (m_gradient) + setControllerGradient(*m_gradient); +} + +QSGNode *DeclarativeSurface::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) +{ + // If old node exists and has right size, reuse it. + if (oldNode && m_initialisedSize == boundingRect().size().toSize()) { + // Update bounding rectangle (that has same size as before). + static_cast<DeclarativeSurfaceRenderer *>( oldNode )->setRect(boundingRect()); + return oldNode; + } + + // Create a new render node when size changes or if there is no node yet + m_initialisedSize = boundingRect().size().toSize(); + + // Delete old node + if (oldNode) + delete oldNode; + + // Create a new one and set it's bounding rectangle + DeclarativeSurfaceRenderer *node = new DeclarativeSurfaceRenderer(window(), m_shared); + node->setRect(boundingRect()); + m_shared->setBoundingRect(boundingRect().toRect()); + return node; +} + +void DeclarativeSurface::setDataProxy(QSurfaceDataProxy *dataProxy) +{ + m_shared->setActiveDataProxy(dataProxy); +} + +QSurfaceDataProxy *DeclarativeSurface::dataProxy() const +{ + return static_cast<QSurfaceDataProxy *>(m_shared->activeDataProxy()); +} + +Q3DValueAxis *DeclarativeSurface::axisX() const +{ + return static_cast<Q3DValueAxis *>(m_shared->axisX()); +} + +void DeclarativeSurface::setAxisX(Q3DValueAxis *axis) +{ + m_shared->setAxisX(axis); +} + +Q3DValueAxis *DeclarativeSurface::axisY() const +{ + return static_cast<Q3DValueAxis *>(m_shared->axisY()); +} + +void DeclarativeSurface::setAxisY(Q3DValueAxis *axis) +{ + m_shared->setAxisY(axis); +} + +Q3DValueAxis *DeclarativeSurface::axisZ() const +{ + return static_cast<Q3DValueAxis *>(m_shared->axisZ()); +} + +void DeclarativeSurface::setAxisZ(Q3DValueAxis *axis) +{ + m_shared->setAxisZ(axis); +} + +void DeclarativeSurface::setSmoothSurfaceEnabled(bool enabled) +{ + m_shared->setSmoothSurface(enabled); +} + +bool DeclarativeSurface::isSmoothSurfaceEnabled() const +{ + return m_shared->smoothSurface(); +} + +void DeclarativeSurface::setSurfaceGridEnabled(bool enabled) +{ + m_shared->setSurfaceGrid(enabled); +} + +bool DeclarativeSurface::isSurfaceGridEnabled() const +{ + return m_shared->surfaceGrid(); +} + +void DeclarativeSurface::setGradient(ColorGradient *gradient) +{ + // connect new / disconnect old + if (gradient != m_gradient) { + if (m_gradient) + QObject::disconnect(m_gradient, 0, this, 0); + + m_gradient = gradient; + + if (m_gradient) { + QObject::connect(m_gradient, &ColorGradient::updated, this, + &DeclarativeSurface::handleGradientUpdate); + } + } + + if (m_gradient) + setControllerGradient(*m_gradient); +} + +ColorGradient *DeclarativeSurface::gradient() const +{ + + return m_gradient; +} + +void DeclarativeSurface::setControllerGradient(const ColorGradient &gradient) +{ + QLinearGradient newGradient; + QGradientStops stops; + QList<ColorGradientStop *> qmlstops = gradient.m_stops; + + // Get sorted gradient stops + for (int i = 0; i < qmlstops.size(); i++) { + int j = 0; + while (j < stops.size() && stops.at(j).first < qmlstops[i]->position()) + j++; + stops.insert(j, QGradientStop(qmlstops.at(i)->position(), qmlstops.at(i)->color())); + } + + newGradient.setStops(stops); + m_shared->setGradient(newGradient); +} + +QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavisualizationqml2/declarativesurface_p.h b/src/datavisualizationqml2/declarativesurface_p.h new file mode 100644 index 00000000..6ba52146 --- /dev/null +++ b/src/datavisualizationqml2/declarativesurface_p.h @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** 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 DECLARATIVESURFACE_P_H +#define DECLARATIVESURFACE_P_H + +#include "datavisualizationglobal_p.h" +#include "abstractdeclarative_p.h" +#include "surface3dcontroller_p.h" +#include "declarativesurface_p.h" +#include "q3dvalueaxis.h" +#include "qsurfacedataproxy.h" +#include "colorgradient_p.h" + +#include <QAbstractItemModel> +#include <QQuickItem> +#include <QObject> +#include <QQuickWindow> + +QT_DATAVISUALIZATION_BEGIN_NAMESPACE + +class DeclarativeSurface : public AbstractDeclarative +{ + Q_OBJECT + Q_PROPERTY(QSurfaceDataProxy *dataProxy READ dataProxy WRITE setDataProxy) + Q_PROPERTY(Q3DValueAxis *axisX READ axisX WRITE setAxisX) + Q_PROPERTY(Q3DValueAxis *axisY READ axisY WRITE setAxisY) + Q_PROPERTY(Q3DValueAxis *axisZ READ axisZ WRITE setAxisZ) + Q_PROPERTY(bool smoothSurfaceEnabled READ isSmoothSurfaceEnabled WRITE setSmoothSurfaceEnabled) + Q_PROPERTY(bool surfaceGridEnabled READ isSurfaceGridEnabled WRITE setSurfaceGridEnabled) + Q_PROPERTY(ColorGradient *gradient READ gradient WRITE setGradient) + +public: + explicit DeclarativeSurface(QQuickItem *parent = 0); + ~DeclarativeSurface(); + + QSurfaceDataProxy *dataProxy() const; + void setDataProxy(QSurfaceDataProxy *dataProxy); + + Q3DValueAxis *axisX() const; + void setAxisX(Q3DValueAxis *axis); + Q3DValueAxis *axisY() const; + void setAxisY(Q3DValueAxis *axis); + Q3DValueAxis *axisZ() const; + void setAxisZ(Q3DValueAxis *axis); + + void setSmoothSurfaceEnabled(bool enabled); + bool isSmoothSurfaceEnabled() const; + + void setSurfaceGridEnabled(bool enabled); + bool isSurfaceGridEnabled() const; + + void setGradient(ColorGradient *gradient); + ColorGradient *gradient() const; + +protected: + void handleGradientUpdate(); + + QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *); + +private: + Surface3DController *m_shared; + + void setControllerGradient(const ColorGradient &gradient); + + QSize m_initialisedSize; + ColorGradient *m_gradient; // Not owned +}; + +QT_DATAVISUALIZATION_END_NAMESPACE + +#endif diff --git a/src/datavis3dqml2/declarativemapsrenderer.cpp b/src/datavisualizationqml2/declarativesurfacerenderer.cpp index 6e8dc2db..87a290ce 100644 --- a/src/datavis3dqml2/declarativemapsrenderer.cpp +++ b/src/datavisualizationqml2/declarativesurfacerenderer.cpp @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -16,29 +16,41 @@ ** ****************************************************************************/ -#include "declarativemapsrenderer_p.h" +#include "declarativesurfacerenderer_p.h" #include <QtQuick/QQuickWindow> #include <QtGui/QOpenGLFramebufferObject> -QT_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVISUALIZATION_BEGIN_NAMESPACE -DeclarativeMapsRenderer::DeclarativeMapsRenderer(QQuickWindow *window, Maps3DController *renderer) +DeclarativeSurfaceRenderer::DeclarativeSurfaceRenderer(QQuickWindow *window, + Surface3DController *renderer) : m_fbo(0), m_texture(0), m_window(window), - m_mapsRenderer(renderer) + m_surfaceRenderer(renderer) { - connect(m_window, SIGNAL(beforeRendering()), this, SLOT(render()), Qt::DirectConnection); + connect(m_window, &QQuickWindow::beforeSynchronizing, this, + &DeclarativeSurfaceRenderer::synchDataToRenderer, Qt::DirectConnection); + connect(m_window, &QQuickWindow::beforeRendering, this, + &DeclarativeSurfaceRenderer::renderFBO, Qt::DirectConnection); + connect(m_surfaceRenderer, &Abstract3DController::needRender, m_window, + &QQuickWindow::update); } -DeclarativeMapsRenderer::~DeclarativeMapsRenderer() +DeclarativeSurfaceRenderer::~DeclarativeSurfaceRenderer() { delete m_texture; delete m_fbo; } -void DeclarativeMapsRenderer::render() +void DeclarativeSurfaceRenderer::synchDataToRenderer() +{ + m_surfaceRenderer->initializeOpenGL(); + m_surfaceRenderer->synchDataToRenderer(); +} + +void DeclarativeSurfaceRenderer::renderFBO() { QSize size = rect().size().toSize(); @@ -62,18 +74,14 @@ void DeclarativeMapsRenderer::render() QSGGeometry::updateTexturedRectGeometry(geometry, rect(), m_texture->convertToNormalizedSourceRect(sourceRect)); markDirty(DirtyMaterial); - //qDebug() << "create node" << m_fbo->handle() << m_texture->textureId() << m_fbo->size(); } // Call the shared rendering function m_fbo->bind(); - m_mapsRenderer->render(m_fbo->handle()); + m_surfaceRenderer->render(m_fbo->handle()); m_fbo->release(); - - // New view is in the FBO, request repaint of scene graph - m_window->update(); } -QT_DATAVIS3D_END_NAMESPACE +QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavis3dqml2/declarativemapsrenderer_p.h b/src/datavisualizationqml2/declarativesurfacerenderer_p.h index 755764c9..09128f59 100644 --- a/src/datavis3dqml2/declarativemapsrenderer_p.h +++ b/src/datavisualizationqml2/declarativesurfacerenderer_p.h @@ -4,7 +4,7 @@ ** All rights reserved. ** For any questions to Digia, please use contact form at http://qt.digia.com ** -** This file is part of the QtDataVis3D module. +** 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 @@ -20,43 +20,46 @@ // W A R N I N G // ------------- // -// This file is not part of the QtDataVis3D API. It exists purely as an +// 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 DECLARATIVEMAPSRENDERER_P_H -#define DECLARATIVEMAPSRENDERER_P_H +#ifndef DECLARATIVESURFACERENDERER_H +#define DECLARATIVESURFACERENDERER_H -#include "datavis3dglobal_p.h" -#include "maps3dcontroller_p.h" +#include "datavisualizationglobal_p.h" +#include "surface3dcontroller_p.h" #include <qsgsimpletexturenode.h> class QOpenGLFramebufferObject; class QSGTexture; class QQuickWindow; -QT_DATAVIS3D_BEGIN_NAMESPACE +QT_DATAVISUALIZATION_BEGIN_NAMESPACE -class DeclarativeMapsRenderer : public QObject, public QSGSimpleTextureNode +class DeclarativeSurfaceRenderer : public QObject, public QSGSimpleTextureNode { Q_OBJECT public: - DeclarativeMapsRenderer(QQuickWindow *window, Maps3DController *shared); - ~DeclarativeMapsRenderer(); + DeclarativeSurfaceRenderer(QQuickWindow *window, Surface3DController *shared); + ~DeclarativeSurfaceRenderer(); public slots: - void render(); + // Used to synch up data model from controller to renderer while main thread is locked + void synchDataToRenderer(); + // Renders view to FBO before render cycle starts. + void renderFBO(); private: QOpenGLFramebufferObject *m_fbo; QSGTexture *m_texture; QQuickWindow *m_window; - Maps3DController *m_mapsRenderer; + Surface3DController *m_surfaceRenderer; }; -QT_DATAVIS3D_END_NAMESPACE +QT_DATAVISUALIZATION_END_NAMESPACE #endif diff --git a/src/datavisualizationqml2/qmldir b/src/datavisualizationqml2/qmldir new file mode 100644 index 00000000..1def2238 --- /dev/null +++ b/src/datavisualizationqml2/qmldir @@ -0,0 +1,3 @@ +module com.digia.QtDataVisualization +plugin datavisualizationqml2 + diff --git a/src/src.pro b/src/src.pro index 171f9fde..33e3c009 100644 --- a/src/src.pro +++ b/src/src.pro @@ -1,3 +1,4 @@ TEMPLATE = subdirs -SUBDIRS += datavis3d \ - datavis3dqml2 +CONFIG += ordered +SUBDIRS += datavisualization \ + datavisualizationqml2 |