diff options
author | Miikka Heikkinen <miikka.heikkinen@digia.com> | 2013-08-28 14:55:50 +0300 |
---|---|---|
committer | Miikka Heikkinen <miikka.heikkinen@digia.com> | 2013-08-29 08:24:43 +0300 |
commit | 89007c36f04fb965167501a0d473451976548da3 (patch) | |
tree | 7289354f1ed9b63ec14d78cd6664dd0d0bbba8af /src | |
parent | 5bbd3b72540fd24ecb4538627e01bffe3d03acc6 (diff) |
Make axes ownership more useful
Chart can now own multiple axes while showing only one.
Default axes are no longer modifiable by users.
Task-number: QTRD-2212
Change-Id: I028f0d7539dbbf6e3474680290c7ec6bba5a4223
Reviewed-by: Tomi Korpipää <tomi.korpipaa@digia.com>
Diffstat (limited to 'src')
26 files changed, 497 insertions, 141 deletions
diff --git a/src/datavis3d/axis/qabstractaxis.cpp b/src/datavis3d/axis/qabstractaxis.cpp index 5129dfab..0b233903 100644 --- a/src/datavis3d/axis/qabstractaxis.cpp +++ b/src/datavis3d/axis/qabstractaxis.cpp @@ -124,7 +124,8 @@ QAbstractAxisPrivate::QAbstractAxisPrivate(QAbstractAxis *q, QAbstractAxis::Axis : QObject(0), q_ptr(q), m_orientation(QAbstractAxis::AxisOrientationNone), - m_type(type) + m_type(type), + m_isDefaultAxis(false) { } diff --git a/src/datavis3d/axis/qabstractaxis.h b/src/datavis3d/axis/qabstractaxis.h index aac2ee30..e2c127ad 100644 --- a/src/datavis3d/axis/qabstractaxis.h +++ b/src/datavis3d/axis/qabstractaxis.h @@ -80,6 +80,7 @@ private: Q_DISABLE_COPY(QAbstractAxis) friend class Abstract3DController; + friend class Bars3dController; }; QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/axis/qabstractaxis_p.h b/src/datavis3d/axis/qabstractaxis_p.h index 5b73ce17..6422868f 100644 --- a/src/datavis3d/axis/qabstractaxis_p.h +++ b/src/datavis3d/axis/qabstractaxis_p.h @@ -28,6 +28,7 @@ #include "datavis3dglobal_p.h" #include "qabstractaxis.h" +#include "abstract3dcontroller_p.h" #ifndef QABSTRACTAXIS_P_H #define QABSTRACTAXIS_P_H @@ -43,6 +44,9 @@ public: void setOrientation(QAbstractAxis::AxisOrientation orientation); + inline bool isDefaultAxis() { return m_isDefaultAxis; } + inline void setDefaultAxis(bool isDefault) { m_isDefaultAxis = isDefault; } + protected: virtual void updateLabels(); @@ -52,6 +56,7 @@ protected: QStringList m_labels; QAbstractAxis::AxisOrientation m_orientation; QAbstractAxis::AxisType m_type; + bool m_isDefaultAxis; friend class QAbstractAxis; friend class QValueAxis; diff --git a/src/datavis3d/axis/qcategoryaxis.h b/src/datavis3d/axis/qcategoryaxis.h index d162d34b..ab82e8d6 100644 --- a/src/datavis3d/axis/qcategoryaxis.h +++ b/src/datavis3d/axis/qcategoryaxis.h @@ -35,7 +35,7 @@ class QT_DATAVIS3D_EXPORT QCategoryAxis : public QAbstractAxis public: explicit QCategoryAxis(QObject *parent = 0); - ~QCategoryAxis(); + virtual ~QCategoryAxis(); QStringList categoryLabels() const; diff --git a/src/datavis3d/axis/qvalueaxis.cpp b/src/datavis3d/axis/qvalueaxis.cpp index 67bb9a38..9520cacd 100644 --- a/src/datavis3d/axis/qvalueaxis.cpp +++ b/src/datavis3d/axis/qvalueaxis.cpp @@ -219,7 +219,9 @@ QValueAxisPrivate::QValueAxisPrivate(QValueAxis *q) m_max(10.0), m_segmentCount(5), m_subSegmentCount(1), - m_autoAdjust(true) + m_autoAdjust(true), + m_labelFormat(Utils::defaultLabelFormat()), + m_labelsDirty(true) { } @@ -307,9 +309,6 @@ void QValueAxisPrivate::updateLabels() qreal segmentStep = (m_max - m_min) / m_segmentCount; QString formatString(m_labelFormat); - if (formatString.isEmpty()) - formatString = Utils::defaultLabelFormat(); - Utils::ParamType paramType = Utils::findFormatParamType(formatString); QByteArray formatArray = formatString.toUtf8(); diff --git a/src/datavis3d/axis/qvalueaxis.h b/src/datavis3d/axis/qvalueaxis.h index 6bc84c15..1bffcb15 100644 --- a/src/datavis3d/axis/qvalueaxis.h +++ b/src/datavis3d/axis/qvalueaxis.h @@ -37,7 +37,7 @@ class QT_DATAVIS3D_EXPORT QValueAxis : public QAbstractAxis public: explicit QValueAxis(QObject *parent = 0); - ~QValueAxis(); + virtual ~QValueAxis(); qreal min() const; qreal max() const; diff --git a/src/datavis3d/data/barrenderitem_p.h b/src/datavis3d/data/barrenderitem_p.h index 0b7dc639..67e1e256 100644 --- a/src/datavis3d/data/barrenderitem_p.h +++ b/src/datavis3d/data/barrenderitem_p.h @@ -77,14 +77,12 @@ protected: void BarRenderItem::setValue(qreal value) { - if (m_value != value) { - m_value = value; - // Force reformatting on next access by setting label string to null string - if (!m_sliceLabel.isNull()) - setSliceLabel(QString()); - if (!m_selectionLabel.isNull()) - setSelectionLabel(QString()); - } + 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; diff --git a/src/datavis3d/engine/abstract3dcontroller.cpp b/src/datavis3d/engine/abstract3dcontroller.cpp index de80bd41..06d81021 100644 --- a/src/datavis3d/engine/abstract3dcontroller.cpp +++ b/src/datavis3d/engine/abstract3dcontroller.cpp @@ -20,6 +20,7 @@ #include "camerahelper_p.h" #include "qabstractaxis_p.h" #include "qvalueaxis.h" +#include "qcategoryaxis.h" #include "abstract3drenderer_p.h" #if defined(Q_OS_ANDROID) @@ -63,9 +64,8 @@ Abstract3DController::Abstract3DController(QRect boundRect, QObject *parent) : Abstract3DController::~Abstract3DController() { delete m_cameraHelper; - delete m_axisX; - delete m_axisY; - delete m_axisZ; + + // Attached axes are children, so no need to explicitly delete them } void Abstract3DController::setRenderer(Abstract3DRenderer *renderer) @@ -383,6 +383,8 @@ void Abstract3DController::setAxisX(QAbstractAxis *axis) QAbstractAxis *Abstract3DController::axisX() { + if (m_axisX->d_ptr->isDefaultAxis()) + return 0; return m_axisX; } @@ -393,6 +395,8 @@ void Abstract3DController::setAxisY(QAbstractAxis *axis) QAbstractAxis *Abstract3DController::axisY() { + if (m_axisY->d_ptr->isDefaultAxis()) + return 0; return m_axisY; } @@ -403,9 +407,57 @@ void Abstract3DController::setAxisZ(QAbstractAxis *axis) QAbstractAxis *Abstract3DController::axisZ() { + if (m_axisZ->d_ptr->isDefaultAxis()) + return 0; return m_axisZ; } +void Abstract3DController::addAxis(QAbstractAxis *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(QAbstractAxis *axis) +{ + if (axis && m_axes.contains(axis)) { + // If the axis is in use, replace it with a temporary one + switch (axis->orientation()) { + case QAbstractAxis::AxisOrientationX: + setAxisX(0); + break; + case QAbstractAxis::AxisOrientationY: + setAxisY(0); + break; + case QAbstractAxis::AxisOrientationZ: + setAxisZ(0); + break; + default: + break; + } + + m_axes.removeAll(axis); + axis->setParent(0); + } +} + +QList<QAbstractAxis *> Abstract3DController::axes() const +{ + QList<QAbstractAxis *> retList; + foreach (QAbstractAxis *axis, m_axes) { + if (!axis->d_ptr->isDefaultAxis()) + retList.append(axis); + } + + return retList; +} + int Abstract3DController::zoomLevel() { return m_zoomLevel; @@ -658,25 +710,48 @@ void Abstract3DController::handleAxisLabelFormatChanged(const QString &format) void Abstract3DController::handleAxisLabelFormatChangedBySender(QObject *sender) { - if (sender == m_axisX) + // 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) + } else if (sender == m_axisY) { + m_isDataDirty = true; m_changeTracker.axisYLabelFormatChanged = true; - else if (sender == m_axisZ) + } else if (sender == m_axisZ) { + m_isDataDirty = true; m_changeTracker.axisZLabelFormatChanged = true; - else + } else { qWarning() << __FUNCTION__ << "invoked for invalid axis"; + } } void Abstract3DController::setAxisHelper(QAbstractAxis::AxisOrientation orientation, QAbstractAxis *axis, QAbstractAxis **axisPtr) { - Q_ASSERT(axis); + // Setting null axis indicates using default axis + if (axis == 0) + axis = createDefaultAxis(orientation); + + // If old axis is default axis, delete it + QAbstractAxis *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(QAbstractAxis::AxisOrientationNone); + } + } - delete *axisPtr; + // Assume ownership + addAxis(axis); + + // Connect the new axis *axisPtr = axis; - axis->setParent(0); // Assume ownership axis->d_ptr->setOrientation(orientation); QObject::connect(axis, &QAbstractAxis::titleChanged, @@ -716,4 +791,37 @@ void Abstract3DController::setAxisHelper(QAbstractAxis::AxisOrientation orientat } } +QAbstractAxis *Abstract3DController::createDefaultAxis(QAbstractAxis::AxisOrientation orientation) +{ + Q_UNUSED(orientation) + + // The default default axis is a value axis. If the chart type has a different default axis + // for some orientation, this function needs to be overridden. + QAbstractAxis *defaultAxis = createDefaultValueAxis(); + return defaultAxis; +} + +QValueAxis *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 + QValueAxis *defaultAxis = new QValueAxis; + defaultAxis->setSegmentCount(1); + defaultAxis->setSubSegmentCount(1); + defaultAxis->setAutoAdjustRange(true); + defaultAxis->setLabelFormat(QString()); + defaultAxis->d_ptr->setDefaultAxis(true); + + return defaultAxis; +} + +QCategoryAxis *Abstract3DController::createDefaultCategoryAxis() +{ + // Default category axis has no labels + // TODO: Grid should be also hidden, but that is not currently controlled by axis. + QCategoryAxis *defaultAxis = new QCategoryAxis; + defaultAxis->d_ptr->setDefaultAxis(true); + return defaultAxis; +} + QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/engine/abstract3dcontroller_p.h b/src/datavis3d/engine/abstract3dcontroller_p.h index 4868e3eb..3123a5d7 100644 --- a/src/datavis3d/engine/abstract3dcontroller_p.h +++ b/src/datavis3d/engine/abstract3dcontroller_p.h @@ -156,9 +156,12 @@ protected: QAbstract3DInputHandler *m_inputHandler; CameraHelper *m_cameraHelper; int m_zoomLevel; + // Active axes QAbstractAxis *m_axisX; QAbstractAxis *m_axisY; QAbstractAxis *m_axisZ; + + QList<QAbstractAxis *> m_axes; // List of all added axes Abstract3DRenderer *m_renderer; bool m_isDataDirty; @@ -201,6 +204,9 @@ public: virtual QAbstractAxis *axisY(); virtual void setAxisZ(QAbstractAxis *axis); virtual QAbstractAxis *axisZ(); + virtual void addAxis(QAbstractAxis *axis); + virtual void releaseAxis(QAbstractAxis *axis); + virtual QList<QAbstractAxis *> axes() const; // Omits default axes virtual int zoomLevel(); virtual void setZoomLevel(int zoomLevel); @@ -283,6 +289,11 @@ signals: void gridEnabledChanged(bool enable); // TODO: Should be handled via axes? void meshFileNameChanged(QString fileName); +protected: + virtual QAbstractAxis *createDefaultAxis(QAbstractAxis::AxisOrientation orientation); + QValueAxis *createDefaultValueAxis(); + QCategoryAxis *createDefaultCategoryAxis(); + private: void setAxisHelper(QAbstractAxis::AxisOrientation orientation, QAbstractAxis *axis, QAbstractAxis **axisPtr); diff --git a/src/datavis3d/engine/abstract3drenderer.cpp b/src/datavis3d/engine/abstract3drenderer.cpp index 2b40955c..a1800ba8 100644 --- a/src/datavis3d/engine/abstract3drenderer.cpp +++ b/src/datavis3d/engine/abstract3drenderer.cpp @@ -111,8 +111,6 @@ void Abstract3DRenderer::render(CameraHelper *camera, const GLuint defaultFboHan QString Abstract3DRenderer::generateValueLabel(const QString &format, qreal value) { QString valueLabelFormat = format; - if (valueLabelFormat.isEmpty()) - valueLabelFormat = Utils::defaultLabelFormat(); Utils::ParamType valueParamType = Utils::findFormatParamType(valueLabelFormat); QByteArray valueFormatArray = valueLabelFormat.toUtf8(); return Utils::formatLabel(valueFormatArray, valueParamType, value); diff --git a/src/datavis3d/engine/axisrendercache.cpp b/src/datavis3d/engine/axisrendercache.cpp index 4374d545..0ca92247 100644 --- a/src/datavis3d/engine/axisrendercache.cpp +++ b/src/datavis3d/engine/axisrendercache.cpp @@ -52,11 +52,21 @@ void AxisRenderCache::setType(QAbstractAxis::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,10 +90,10 @@ 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); + 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)) diff --git a/src/datavis3d/engine/bars3dcontroller.cpp b/src/datavis3d/engine/bars3dcontroller.cpp index 13dce382..36a00319 100644 --- a/src/datavis3d/engine/bars3dcontroller.cpp +++ b/src/datavis3d/engine/bars3dcontroller.cpp @@ -44,15 +44,17 @@ Bars3dController::Bars3dController(QRect boundRect) 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); + + // Setting a null axis creates a new default axis according to orientation and chart 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() @@ -502,4 +504,16 @@ void Bars3dController::adjustValueAxisRange() } } +QAbstractAxis *Bars3dController::createDefaultAxis(QAbstractAxis::AxisOrientation orientation) +{ + QAbstractAxis *defaultAxis = 0; + + if (orientation == QAbstractAxis::AxisOrientationY) + defaultAxis = createDefaultValueAxis(); + else + defaultAxis = createDefaultCategoryAxis(); + + return defaultAxis; +} + QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/engine/bars3dcontroller_p.h b/src/datavis3d/engine/bars3dcontroller_p.h index f7016860..bdff63b3 100644 --- a/src/datavis3d/engine/bars3dcontroller_p.h +++ b/src/datavis3d/engine/bars3dcontroller_p.h @@ -152,6 +152,9 @@ signals: void barSpecsChanged(GLfloat thicknessRatio, QSizeF spacing, bool relative); void selectedBarPosChanged(QPoint position); +protected: + virtual QAbstractAxis *createDefaultAxis(QAbstractAxis::AxisOrientation orientation); + private: void adjustValueAxisRange(); diff --git a/src/datavis3d/engine/bars3drenderer.cpp b/src/datavis3d/engine/bars3drenderer.cpp index ce05b0b9..ce7dd0e4 100644 --- a/src/datavis3d/engine/bars3drenderer.cpp +++ b/src/datavis3d/engine/bars3drenderer.cpp @@ -1360,7 +1360,10 @@ void Bars3dRenderer::drawScene(CameraHelper *camera, labelText.replace(valueTitleTag, m_axisCacheY.title()); if (labelText.contains(valueLabelTag)) { - QString valueLabelText = generateValueLabel(m_axisCacheY.labelFormat(), selectedBar->value()); + QString labelFormat = m_axisCacheY.labelFormat(); + if (labelFormat.isEmpty()) + labelFormat = Utils::defaultLabelFormat(); + QString valueLabelText = generateValueLabel(labelFormat, selectedBar->value()); labelText.replace(valueLabelTag, valueLabelText); } diff --git a/src/datavis3d/engine/drawer.cpp b/src/datavis3d/engine/drawer.cpp index d2e3ddaf..9ea958ba 100644 --- a/src/datavis3d/engine/drawer.cpp +++ b/src/datavis3d/engine/drawer.cpp @@ -321,18 +321,20 @@ void Drawer::generateLabelItem(LabelItem &item, const QString &text) 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_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)); + } } QT_DATAVIS3D_END_NAMESPACE diff --git a/src/datavis3d/engine/q3dbars.cpp b/src/datavis3d/engine/q3dbars.cpp index cf196ac8..5c2cf0c8 100644 --- a/src/datavis3d/engine/q3dbars.cpp +++ b/src/datavis3d/engine/q3dbars.cpp @@ -20,6 +20,7 @@ #include "q3dbars_p.h" #include "bars3dcontroller_p.h" #include "qvalueaxis.h" +#include "qcategoryaxis.h" #include <QMouseEvent> @@ -394,7 +395,7 @@ QPoint Q3DBars::selectedBarPos() const */ void Q3DBars::setShadowQuality(QDataVis::ShadowQuality quality) { - return d_ptr->m_shared->setShadowQuality(quality); + d_ptr->m_shared->setShadowQuality(quality); } QDataVis::ShadowQuality Q3DBars::shadowQuality() const @@ -403,33 +404,65 @@ QDataVis::ShadowQuality Q3DBars::shadowQuality() const } /*! - * \return category axis for rows. + * 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, or if user doesn't explicitly set row axis at all, a temporary + * default axis with no labels is used. + * + * \sa addAxis(), releaseAxis() + */ +void Q3DBars::setRowAxis(QCategoryAxis *axis) +{ + d_ptr->m_shared->setAxisX(axis); +} + +/*! + * \return category axis for rows. Returns null pointer if default axis is in use. */ QCategoryAxis *Q3DBars::rowAxis() const { - return reinterpret_cast<QCategoryAxis *>(d_ptr->m_shared->axisX()); + return static_cast<QCategoryAxis *>(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, or if user doesn't explicitly set column axis at all, a temporary + * default axis with no labels is used. + * + * \sa addAxis(), releaseAxis() + */ +void Q3DBars::setColumnAxis(QCategoryAxis *axis) +{ + d_ptr->m_shared->setAxisZ(axis); } /*! - * \return category axis for columns. + * \return category axis for columns. Returns null pointer if default axis is in use. */ QCategoryAxis *Q3DBars::columnAxis() const { - return reinterpret_cast<QCategoryAxis *>(d_ptr->m_shared->axisZ()); + return static_cast<QCategoryAxis *>(d_ptr->m_shared->axisZ()); } /*! - * Sets a user-defined value \a axis (Y-axis). Ownership of the axis is transferred to Q3DBars. + * 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, or if user doesn't explicitly set value axis at all, a temporary + * default axis with no labels and automatic range adjusting is used. + * + * \sa addAxis(), releaseAxis() */ void Q3DBars::setValueAxis(QValueAxis *axis) { - Q_ASSERT(axis); - - return d_ptr->m_shared->setAxisY(axis); + d_ptr->m_shared->setAxisY(axis); } /*! - * \return used value axis (Y-axis). + * \return used value axis (Y-axis). Returns null pointer if default axis is in use. */ QValueAxis *Q3DBars::valueAxis() const { @@ -437,6 +470,39 @@ QValueAxis *Q3DBars::valueAxis() const } /*! + * 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(QAbstractAxis *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 temporary default axis will be set active. + * + * \sa addAxis(), setValueAxis(), setRowAxis(), setColumnAxis() + */ +void Q3DBars::releaseAxis(QAbstractAxis *axis) +{ + d_ptr->m_shared->releaseAxis(axis); +} + +/*! + * \return list of all added axes. + * + * \sa addAxis() + */ +QList<QAbstractAxis *> Q3DBars::axes() const +{ + return d_ptr->m_shared->axes(); +} + +/*! * Sets a user-defined data \a proxy. Ownership of the proxy is transferred to Q3DBars. */ void Q3DBars::setDataProxy(QBarDataProxy *proxy) diff --git a/src/datavis3d/engine/q3dbars.h b/src/datavis3d/engine/q3dbars.h index ff6a6fad..b3e695d3 100644 --- a/src/datavis3d/engine/q3dbars.h +++ b/src/datavis3d/engine/q3dbars.h @@ -26,6 +26,7 @@ QT_DATAVIS3D_BEGIN_NAMESPACE class Q3DBarsPrivate; +class QAbstractAxis; class QCategoryAxis; class QValueAxis; class QBarDataProxy; @@ -93,10 +94,15 @@ public: void setShadowQuality(QDataVis::ShadowQuality quality); QDataVis::ShadowQuality shadowQuality() const; + void setRowAxis(QCategoryAxis *axis); QCategoryAxis *rowAxis() const; + void setColumnAxis(QCategoryAxis *axis); QCategoryAxis *columnAxis() const; void setValueAxis(QValueAxis *axis); QValueAxis *valueAxis() const; + void addAxis(QAbstractAxis *axis); + void releaseAxis(QAbstractAxis *axis); + QList<QAbstractAxis *> axes() const; void setDataProxy(QBarDataProxy *proxy); QBarDataProxy *dataProxy(); diff --git a/src/datavis3d/engine/q3dscatter.cpp b/src/datavis3d/engine/q3dscatter.cpp index 7fc6f628..bd9a884f 100644 --- a/src/datavis3d/engine/q3dscatter.cpp +++ b/src/datavis3d/engine/q3dscatter.cpp @@ -365,60 +365,109 @@ QDataVis::ShadowQuality Q3DScatter::shadowQuality() const } /*! - * Sets a user-defined value \a axis (X-axis). Ownership of the axis is transferred to Q3DScatter. + * 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, or if user doesn't explicitly set value axis at all, a temporary + * default axis with no labels and automatic range adjusting is used. + * + * \sa addAxis(), releaseAxis() */ -void Q3DScatter::setValueAxisX(QValueAxis *axis) +void Q3DScatter::setAxisX(QValueAxis *axis) { - Q_ASSERT(axis); - - return d_ptr->m_shared->setAxisX(axis); + d_ptr->m_shared->setAxisX(axis); } /*! - * \return used value axis (X-axis). + * \return used X-axis. Returns null pointer if default axis is in use. */ -QValueAxis *Q3DScatter::valueAxisX() const +QValueAxis *Q3DScatter::axisX() const { return static_cast<QValueAxis *>(d_ptr->m_shared->axisX()); } /*! - * Sets a user-defined value \a axis (Y-axis). Ownership of the axis is transferred to Q3DScatter. + * 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, or if user doesn't explicitly set value axis at all, a temporary + * default axis with no labels and automatic range adjusting is used. + * + * \sa addAxis(), releaseAxis() */ -void Q3DScatter::setValueAxisY(QValueAxis *axis) +void Q3DScatter::setAxisY(QValueAxis *axis) { - Q_ASSERT(axis); - - return d_ptr->m_shared->setAxisY(axis); + d_ptr->m_shared->setAxisY(axis); } /*! - * \return used value axis (Y-axis). + * \return used Y-axis. Returns null pointer if default axis is in use. */ -QValueAxis *Q3DScatter::valueAxisY() const +QValueAxis *Q3DScatter::axisY() const { return static_cast<QValueAxis *>(d_ptr->m_shared->axisY()); } /*! - * Sets a user-defined value \a axis (Z-axis). Ownership of the axis is transferred to Q3DScatter. + * 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, or if user doesn't explicitly set value axis at all, a temporary + * default axis with no labels and automatic range adjusting is used. + * + * \sa addAxis(), releaseAxis() */ -void Q3DScatter::setValueAxisZ(QValueAxis *axis) +void Q3DScatter::setAxisZ(QValueAxis *axis) { - Q_ASSERT(axis); - - return d_ptr->m_shared->setAxisZ(axis); + d_ptr->m_shared->setAxisZ(axis); } /*! - * \return used value axis (Z-axis). + * \return used Z-axis. Returns null pointer if default axis is in use. */ -QValueAxis *Q3DScatter::valueAxisZ() const +QValueAxis *Q3DScatter::axisZ() const { return static_cast<QValueAxis *>(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(QValueAxis *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. + * + * \sa addAxis(), setAxisX(), setAxisY(), setAxisZ() + */ +void Q3DScatter::releaseAxis(QValueAxis *axis) +{ + d_ptr->m_shared->releaseAxis(axis); +} + +/*! + * \return list of all added axes. + * + * \sa addAxis() + */ +QList<QValueAxis *> Q3DScatter::axes() const +{ + QList<QAbstractAxis *> abstractAxes = d_ptr->m_shared->axes(); + QList<QValueAxis *> retList; + foreach (QAbstractAxis *axis, abstractAxes) + retList.append(static_cast<QValueAxis *>(axis)); + + return retList; +} + +/*! * Sets a user-defined data \a proxy. Ownership of the proxy is transferred to Q3DScatter. */ void Q3DScatter::setDataProxy(QScatterDataProxy *proxy) diff --git a/src/datavis3d/engine/q3dscatter.h b/src/datavis3d/engine/q3dscatter.h index 26e3da08..a432b101 100644 --- a/src/datavis3d/engine/q3dscatter.h +++ b/src/datavis3d/engine/q3dscatter.h @@ -86,14 +86,15 @@ public: void setShadowQuality(QDataVis::ShadowQuality quality); QDataVis::ShadowQuality shadowQuality() const; - void setValueAxisX(QValueAxis *axis); - QValueAxis *valueAxisX() const; - - void setValueAxisY(QValueAxis *axis); - QValueAxis *valueAxisY() const; - - void setValueAxisZ(QValueAxis *axis); - QValueAxis *valueAxisZ() const; + void setAxisX(QValueAxis *axis); + QValueAxis *axisX() const; + void setAxisY(QValueAxis *axis); + QValueAxis *axisY() const; + void setAxisZ(QValueAxis *axis); + QValueAxis *axisZ() const; + void addAxis(QValueAxis *axis); + void releaseAxis(QValueAxis *axis); + QList<QValueAxis *> axes() const; void setDataProxy(QScatterDataProxy *proxy); QScatterDataProxy *dataProxy(); diff --git a/src/datavis3d/engine/q3dsurface.cpp b/src/datavis3d/engine/q3dsurface.cpp index d4b5f2f1..2201053d 100644 --- a/src/datavis3d/engine/q3dsurface.cpp +++ b/src/datavis3d/engine/q3dsurface.cpp @@ -154,42 +154,109 @@ void Q3DSurface::setSegmentCount(int segmentCount, qreal step, qreal minimum) d_ptr->m_shared->setSegmentCount(GLint(segmentCount), GLfloat(step), GLfloat(minimum)); } -void Q3DSurface::setValueAxisX(QValueAxis *axis) +/*! + * 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, or if user doesn't explicitly set value axis at all, a temporary + * default axis with no labels and automatic range adjusting is used. + * + * \sa addAxis(), releaseAxis() + */ +void Q3DSurface::setAxisX(QValueAxis *axis) { - Q_ASSERT(axis); - - return d_ptr->m_shared->setAxisX(axis); + d_ptr->m_shared->setAxisX(axis); } -QValueAxis *Q3DSurface::valueAxisX() +/*! + * \return used X-axis. Returns null pointer if default axis is in use. + */ +QValueAxis *Q3DSurface::axisX() const { return static_cast<QValueAxis *>(d_ptr->m_shared->axisX()); } -void Q3DSurface::setValueAxisY(QValueAxis *axis) +/*! + * 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, or if user doesn't explicitly set value axis at all, a temporary + * default axis with no labels and automatic range adjusting is used. + * + * \sa addAxis(), releaseAxis() + */ +void Q3DSurface::setAxisY(QValueAxis *axis) { - Q_ASSERT(axis); - - return d_ptr->m_shared->setAxisY(axis); + d_ptr->m_shared->setAxisY(axis); } -QValueAxis *Q3DSurface::valueAxisY() +/*! + * \return used Y-axis. Returns null pointer if default axis is in use. + */ +QValueAxis *Q3DSurface::axisY() const { return static_cast<QValueAxis *>(d_ptr->m_shared->axisY()); } -void Q3DSurface::setValueAxisZ(QValueAxis *axis) +/*! + * 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, or if user doesn't explicitly set value axis at all, a temporary + * default axis with no labels and automatic range adjusting is used. + * + * \sa addAxis(), releaseAxis() + */ +void Q3DSurface::setAxisZ(QValueAxis *axis) { - Q_ASSERT(axis); - - return d_ptr->m_shared->setAxisZ(axis); + d_ptr->m_shared->setAxisZ(axis); } -QValueAxis *Q3DSurface::valueAxisZ() +/*! + * \return used Z-axis. Returns null pointer if default axis is in use. + */ +QValueAxis *Q3DSurface::axisZ() const { return static_cast<QValueAxis *>(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(QValueAxis *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. + * + * \sa addAxis(), setAxisX(), setAxisY(), setAxisZ() + */ +void Q3DSurface::releaseAxis(QValueAxis *axis) +{ + d_ptr->m_shared->releaseAxis(axis); +} + +/*! + * \return list of all added axes. + * + * \sa addAxis() + */ +QList<QValueAxis *> Q3DSurface::axes() const +{ + QList<QAbstractAxis *> abstractAxes = d_ptr->m_shared->axes(); + QList<QValueAxis *> retList; + foreach (QAbstractAxis *axis, abstractAxes) + retList.append(static_cast<QValueAxis *>(axis)); + + return retList; +} + void Q3DSurface::setGradientColorAt(qreal pos, const QColor &color) { d_ptr->m_shared->setGradientColorAt(pos, color); diff --git a/src/datavis3d/engine/q3dsurface.h b/src/datavis3d/engine/q3dsurface.h index 357d65bd..c46a3710 100644 --- a/src/datavis3d/engine/q3dsurface.h +++ b/src/datavis3d/engine/q3dsurface.h @@ -58,14 +58,15 @@ public: void setGradientColorAt(qreal pos, const QColor &color); // Axes - void setValueAxisX(QValueAxis *axis); - QValueAxis *valueAxisX(); - - void setValueAxisY(QValueAxis *axis); - QValueAxis *valueAxisY(); - - void setValueAxisZ(QValueAxis *axis); - QValueAxis *valueAxisZ(); + void setAxisX(QValueAxis *axis); + QValueAxis *axisX() const; + void setAxisY(QValueAxis *axis); + QValueAxis *axisY() const; + void setAxisZ(QValueAxis *axis); + QValueAxis *axisZ() const; + void addAxis(QValueAxis *axis); + void releaseAxis(QValueAxis *axis); + QList<QValueAxis *> axes() const; // TODO: Remove when axes handling in use void setSegmentCount(int segmentCount, qreal step, qreal minimum = 0.0f); diff --git a/src/datavis3d/engine/scatter3dcontroller.cpp b/src/datavis3d/engine/scatter3dcontroller.cpp index 3b0a2c1f..c5ed1fed 100644 --- a/src/datavis3d/engine/scatter3dcontroller.cpp +++ b/src/datavis3d/engine/scatter3dcontroller.cpp @@ -38,15 +38,17 @@ Scatter3DController::Scatter3DController(QRect boundRect) m_data(0), m_selectedItemIndex(noSelectionIndex()) { - // Default axes - setAxisX(new QValueAxis()); - setAxisY(new QValueAxis()); - setAxisZ(new QValueAxis()); - // Default object type; specific to scatter setObjectType(QDataVis::Spheres, false); setDataProxy(new QScatterDataProxy); + + // Setting a null axis creates a new default axis according to orientation and chart 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() diff --git a/src/datavis3d/engine/scatter3drenderer.cpp b/src/datavis3d/engine/scatter3drenderer.cpp index 600726f1..bee1ee5c 100644 --- a/src/datavis3d/engine/scatter3drenderer.cpp +++ b/src/datavis3d/engine/scatter3drenderer.cpp @@ -1324,17 +1324,26 @@ void Scatter3DRenderer::drawScene(CameraHelper *camera, labelText.replace(zTitleTag, m_axisCacheZ.title()); if (labelText.contains(xLabelTag)) { - QString valueLabelText = generateValueLabel(m_axisCacheX.labelFormat(), + 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 valueLabelText = generateValueLabel(m_axisCacheY.labelFormat(), + 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 valueLabelText = generateValueLabel(m_axisCacheZ.labelFormat(), + QString labelFormat = m_axisCacheZ.labelFormat(); + if (labelFormat.isEmpty()) + labelFormat = Utils::defaultLabelFormat(); + QString valueLabelText = generateValueLabel(labelFormat, selectedItem->position().z()); labelText.replace(zLabelTag, valueLabelText); } diff --git a/src/datavis3d/engine/surface3dcontroller.cpp b/src/datavis3d/engine/surface3dcontroller.cpp index 89ec4fe6..dd21f388 100644 --- a/src/datavis3d/engine/surface3dcontroller.cpp +++ b/src/datavis3d/engine/surface3dcontroller.cpp @@ -38,10 +38,12 @@ Surface3dController::Surface3dController(QRect rect) m_mouseState(MouseNone), m_mousePos(QPoint(0, 0)) { - // Default axes - setAxisX(new QValueAxis()); // Or QCategoryAxis - setAxisY(new QValueAxis()); - setAxisZ(new QValueAxis()); // Or QCategoryAxis + // Setting a null axis creates a new default axis according to orientation and chart type. + // Note: These cannot be set in Abstract3DController constructor, as they will call virtual + // functions implemented by subclasses. + setAxisX(0); + setAxisY(0); + setAxisZ(0); } Surface3dController::~Surface3dController() diff --git a/src/datavis3dqml2/declarativebars.cpp b/src/datavis3dqml2/declarativebars.cpp index 6c63bda4..32ed5c57 100644 --- a/src/datavis3dqml2/declarativebars.cpp +++ b/src/datavis3dqml2/declarativebars.cpp @@ -125,32 +125,32 @@ void DeclarativeBars::setMapping(QItemModelBarDataMapping *mapping) static_cast<QItemModelBarDataProxy *>(m_shared->dataProxy())->setMapping(mapping); } -QCategoryAxis *DeclarativeBars::axisX() const +QCategoryAxis *DeclarativeBars::rowAxis() const { return static_cast<QCategoryAxis *>(m_shared->axisX()); } -void DeclarativeBars::setAxisX(QCategoryAxis *axis) +void DeclarativeBars::setRowAxis(QCategoryAxis *axis) { m_shared->setAxisX(axis); } -QValueAxis *DeclarativeBars::axisY() const +QValueAxis *DeclarativeBars::valueAxis() const { return static_cast<QValueAxis *>(m_shared->axisY()); } -void DeclarativeBars::setAxisY(QValueAxis *axis) +void DeclarativeBars::setValueAxis(QValueAxis *axis) { m_shared->setAxisY(axis); } -QCategoryAxis *DeclarativeBars::axisZ() const +QCategoryAxis *DeclarativeBars::columnAxis() const { return static_cast<QCategoryAxis *>(m_shared->axisZ()); } -void DeclarativeBars::setAxisZ(QCategoryAxis *axis) +void DeclarativeBars::setColumnAxis(QCategoryAxis *axis) { m_shared->setAxisZ(axis); } diff --git a/src/datavis3dqml2/declarativebars_p.h b/src/datavis3dqml2/declarativebars_p.h index 5a8fb165..6ada9a35 100644 --- a/src/datavis3dqml2/declarativebars_p.h +++ b/src/datavis3dqml2/declarativebars_p.h @@ -48,9 +48,9 @@ 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(QCategoryAxis *rowAxis READ rowAxis WRITE setRowAxis) + Q_PROPERTY(QValueAxis *valueAxis READ valueAxis WRITE setValueAxis) + Q_PROPERTY(QCategoryAxis *columnAxis READ columnAxis WRITE setColumnAxis) 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) @@ -103,18 +103,18 @@ public: 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); + QCategoryAxis *rowAxis() const; + void setRowAxis(QCategoryAxis *axis); + QValueAxis *valueAxis() const; + void setValueAxis(QValueAxis *axis); + QCategoryAxis *columnAxis() const; + void setColumnAxis(QCategoryAxis *axis); - // Set bar thickness. Y -component sets the thickness of z -direction. + // Set bar thickness. void setBarThickness(qreal thicknessRatio); qreal barThickness(); - // Set spacing between bars. Y -component sets the spacing of z -direction. + // 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(); |