diff --git a/src/charts/barchart/abstractbarchartitem.cpp b/src/charts/barchart/abstractbarchartitem.cpp index 9031a8f..ea0e9a0 100644 --- a/src/charts/barchart/abstractbarchartitem.cpp +++ b/src/charts/barchart/abstractbarchartitem.cpp @@ -51,6 +51,7 @@ AbstractBarChartItem::AbstractBarChartItem(QAbstractBarSeries *series, QGraphics connect(series, SIGNAL(labelsFormatChanged(QString)), this, SLOT(positionLabels())); connect(series, SIGNAL(labelsPositionChanged(QAbstractBarSeries::LabelsPosition)), this, SLOT(handleLabelsPositionChanged())); + connect(series, SIGNAL(labelsAngleChanged(qreal)), this, SLOT(positionLabels())); setZValue(ChartPresenter::BarSeriesZValue); handleDataStructureChanged(); handleVisibleChanged(); @@ -249,20 +250,101 @@ void AbstractBarChartItem::handleLabelsPositionChanged() void AbstractBarChartItem::positionLabels() { + // By default position labels on horizontal bar series + // Vertical bar series overload positionLabels() to call positionLabelsVertical() + + QTransform transform; + const qreal angle = m_series->d_func()->labelsAngle(); + if (angle != 0.0) + transform.rotate(angle); + for (int i = 0; i < m_layout.count(); i++) { QGraphicsTextItem *label = m_labels.at(i); + + QRectF labelRect = label->boundingRect(); + QPointF center = labelRect.center(); + qreal xPos = 0; - qreal yPos = m_layout.at(i).center().y() - label->boundingRect().center().y(); + qreal yPos = m_layout.at(i).center().y() - center.y(); + + int xDiff = 0; + if (angle != 0.0) { + label->setTransformOriginPoint(center.x(), center.y()); + label->setRotation(m_series->d_func()->labelsAngle()); + qreal oldWidth = labelRect.width(); + labelRect = transform.mapRect(labelRect); + xDiff = (labelRect.width() - oldWidth) / 2; + } int offset = m_bars.at(i)->pen().width() / 2 + 2; - if (m_series->labelsPosition() == QAbstractBarSeries::LabelsCenter) - xPos = m_layout.at(i).center().x() - label->boundingRect().center().x(); - else if (m_series->labelsPosition() == QAbstractBarSeries::LabelsInsideEnd) - xPos = m_layout.at(i).right() - label->boundingRect().width() - offset; - else if (m_series->labelsPosition() == QAbstractBarSeries::LabelsInsideBase) - xPos = m_layout.at(i).left() + offset; - else if (m_series->labelsPosition() == QAbstractBarSeries::LabelsOutsideEnd) - xPos = m_layout.at(i).right() + offset; + + switch (m_series->labelsPosition()) { + case QAbstractBarSeries::LabelsCenter: + xPos = m_layout.at(i).center().x() - center.x(); + break; + case QAbstractBarSeries::LabelsInsideEnd: + xPos = m_layout.at(i).right() - labelRect.width() - offset + xDiff; + break; + case QAbstractBarSeries::LabelsInsideBase: + xPos = m_layout.at(i).left() + offset + xDiff; + break; + case QAbstractBarSeries::LabelsOutsideEnd: + xPos = m_layout.at(i).right() + offset + xDiff; + break; + default: + // Invalid position, never comes here + break; + } + + label->setPos(xPos, yPos); + label->setZValue(zValue() + 1); + } +} + +void AbstractBarChartItem::positionLabelsVertical() +{ + QTransform transform; + const qreal angle = m_series->d_func()->labelsAngle(); + if (angle != 0.0) + transform.rotate(angle); + + for (int i = 0; i < m_layout.count(); i++) { + QGraphicsTextItem *label = m_labels.at(i); + + QRectF labelRect = label->boundingRect(); + QPointF center = labelRect.center(); + + qreal xPos = m_layout.at(i).center().x() - center.x(); + qreal yPos = 0; + + int yDiff = 0; + if (angle != 0.0) { + label->setTransformOriginPoint(center.x(), center.y()); + label->setRotation(m_series->d_func()->labelsAngle()); + qreal oldHeight = labelRect.height(); + labelRect = transform.mapRect(labelRect); + yDiff = (labelRect.height() - oldHeight) / 2; + } + + int offset = m_bars.at(i)->pen().width() / 2 + 2; + + switch (m_series->labelsPosition()) { + case QAbstractBarSeries::LabelsCenter: + yPos = m_layout.at(i).center().y() - center.y(); + break; + case QAbstractBarSeries::LabelsInsideEnd: + yPos = m_layout.at(i).top() + offset + yDiff; + break; + case QAbstractBarSeries::LabelsInsideBase: + yPos = m_layout.at(i).bottom() - labelRect.height() - offset + yDiff; + break; + case QAbstractBarSeries::LabelsOutsideEnd: + yPos = m_layout.at(i).top() - labelRect.height() - offset + yDiff; + break; + default: + // Invalid position, never comes here + break; + } label->setPos(xPos, yPos); label->setZValue(zValue() + 1); diff --git a/src/charts/barchart/abstractbarchartitem_p.h b/src/charts/barchart/abstractbarchartitem_p.h index 552ba02..3a2c186 100644 --- a/src/charts/barchart/abstractbarchartitem_p.h +++ b/src/charts/barchart/abstractbarchartitem_p.h @@ -72,6 +72,7 @@ public Q_SLOTS: virtual void positionLabels(); protected: + void positionLabelsVertical(); qreal m_domainMinX; qreal m_domainMaxX; diff --git a/src/charts/barchart/qabstractbarseries.cpp b/src/charts/barchart/qabstractbarseries.cpp index 5b013ca..26674e1 100644 --- a/src/charts/barchart/qabstractbarseries.cpp +++ b/src/charts/barchart/qabstractbarseries.cpp @@ -197,6 +197,23 @@ QT_CHARTS_BEGIN_NAMESPACE */ /*! + \property QAbstractBarSeries::labelsAngle + The angle of the value labels in degrees. +*/ +/*! + \qmlproperty qreal QAbstractBarSeries::labelsAngle + The angle of the value labels in degrees. +*/ +/*! + \fn void QAbstractBarSeries::labelsAngleChanged(qreal angle) + Signal is emitted when the \a angle of the value labels is changed. +*/ +/*! + \qmlsignal AbstractBarSeries::onLabelsAngleChanged(qreal angle) + Signal is emitted when the \a angle of the value labels is changed. +*/ + +/*! \fn void QAbstractBarSeries::clicked(int index, QBarSet *barset) The signal is emitted if the user clicks with a mouse on top of QBarSet \a barset. Clicked bar inside set is indexed by \a index @@ -531,6 +548,21 @@ QString QAbstractBarSeries::labelsFormat() const return d->m_labelsFormat; } +void QAbstractBarSeries::setLabelsAngle(qreal angle) +{ + Q_D(QAbstractBarSeries); + if (d->m_labelsAngle != angle) { + d->m_labelsAngle = angle; + emit labelsAngleChanged(angle); + } +} + +qreal QAbstractBarSeries::labelsAngle() const +{ + Q_D(const QAbstractBarSeries); + return d->m_labelsAngle; +} + void QAbstractBarSeries::setLabelsPosition(QAbstractBarSeries::LabelsPosition position) { Q_D(QAbstractBarSeries); @@ -555,7 +587,8 @@ QAbstractBarSeriesPrivate::QAbstractBarSeriesPrivate(QAbstractBarSeries *q) : m_visible(true), m_blockBarUpdate(false), m_labelsFormat(), - m_labelsPosition(QAbstractBarSeries::LabelsCenter) + m_labelsPosition(QAbstractBarSeries::LabelsCenter), + m_labelsAngle(0) { } @@ -799,6 +832,11 @@ bool QAbstractBarSeriesPrivate::blockBarUpdate() return m_blockBarUpdate; } +qreal QAbstractBarSeriesPrivate::labelsAngle() const +{ + return m_labelsAngle; +} + void QAbstractBarSeriesPrivate::initializeDomain() { qreal minX(domain()->minX()); diff --git a/src/charts/barchart/qabstractbarseries.h b/src/charts/barchart/qabstractbarseries.h index 6819eb6..c869277 100644 --- a/src/charts/barchart/qabstractbarseries.h +++ b/src/charts/barchart/qabstractbarseries.h @@ -36,6 +36,7 @@ class QT_CHARTS_EXPORT QAbstractBarSeries : public QAbstractSeries Q_PROPERTY(bool labelsVisible READ isLabelsVisible WRITE setLabelsVisible NOTIFY labelsVisibleChanged) Q_PROPERTY(QString labelsFormat READ labelsFormat WRITE setLabelsFormat NOTIFY labelsFormatChanged) Q_PROPERTY(LabelsPosition labelsPosition READ labelsPosition WRITE setLabelsPosition NOTIFY labelsPositionChanged) + Q_PROPERTY(qreal labelsAngle READ labelsAngle WRITE setLabelsAngle NOTIFY labelsAngleChanged) Q_ENUMS(LabelsPosition) public: @@ -67,6 +68,9 @@ public: void setLabelsFormat(const QString &format); QString labelsFormat() const; + void setLabelsAngle(qreal angle); + qreal labelsAngle() const; + void setLabelsPosition(QAbstractBarSeries::LabelsPosition position); QAbstractBarSeries::LabelsPosition labelsPosition() const; @@ -83,6 +87,7 @@ Q_SIGNALS: void labelsVisibleChanged(); void labelsFormatChanged(const QString &format); void labelsPositionChanged(QAbstractBarSeries::LabelsPosition position); + void labelsAngleChanged(qreal angle); void barsetsAdded(QList sets); void barsetsRemoved(QList sets); diff --git a/src/charts/barchart/qabstractbarseries_p.h b/src/charts/barchart/qabstractbarseries_p.h index 5b1a6e1..7e1e94e 100644 --- a/src/charts/barchart/qabstractbarseries_p.h +++ b/src/charts/barchart/qabstractbarseries_p.h @@ -85,6 +85,8 @@ public: bool blockBarUpdate(); + qreal labelsAngle() const; + Q_SIGNALS: void clicked(int index, QBarSet *barset); void pressed(int index, QBarSet *barset); @@ -107,6 +109,7 @@ protected: bool m_blockBarUpdate; QString m_labelsFormat; QAbstractBarSeries::LabelsPosition m_labelsPosition; + qreal m_labelsAngle; private: Q_DECLARE_PUBLIC(QAbstractBarSeries) diff --git a/src/charts/barchart/vertical/bar/barchartitem.cpp b/src/charts/barchart/vertical/bar/barchartitem.cpp index f9e9f51..cc9218f 100644 --- a/src/charts/barchart/vertical/bar/barchartitem.cpp +++ b/src/charts/barchart/vertical/bar/barchartitem.cpp @@ -98,24 +98,7 @@ void BarChartItem::handleLabelsPositionChanged() void BarChartItem::positionLabels() { - for (int i = 0; i < m_layout.count(); i++) { - QGraphicsTextItem *label = m_labels.at(i); - qreal xPos = m_layout.at(i).center().x() - label->boundingRect().center().x(); - qreal yPos = 0; - - int offset = m_bars.at(i)->pen().width() / 2 + 2; - if (m_series->labelsPosition() == QAbstractBarSeries::LabelsCenter) - yPos = m_layout.at(i).center().y() - label->boundingRect().center().y(); - else if (m_series->labelsPosition() == QAbstractBarSeries::LabelsInsideEnd) - yPos = m_layout.at(i).top() - offset; - else if (m_series->labelsPosition() == QAbstractBarSeries::LabelsInsideBase) - yPos = m_layout.at(i).bottom() - label->boundingRect().height() + offset; - else if (m_series->labelsPosition() == QAbstractBarSeries::LabelsOutsideEnd) - yPos = m_layout.at(i).top() - label->boundingRect().height() + offset; - - label->setPos(xPos, yPos); - label->setZValue(zValue() + 1); - } + positionLabelsVertical(); } #include "moc_barchartitem_p.cpp" diff --git a/src/charts/barchart/vertical/percent/percentbarchartitem.cpp b/src/charts/barchart/vertical/percent/percentbarchartitem.cpp index 2620b0c..fbde59a 100644 --- a/src/charts/barchart/vertical/percent/percentbarchartitem.cpp +++ b/src/charts/barchart/vertical/percent/percentbarchartitem.cpp @@ -144,24 +144,7 @@ void PercentBarChartItem::handleLabelsPositionChanged() void PercentBarChartItem::positionLabels() { - for (int i = 0; i < m_layout.count(); i++) { - QGraphicsTextItem *label = m_labels.at(i); - qreal xPos = m_layout.at(i).center().x() - label->boundingRect().center().x(); - qreal yPos = 0; - - int offset = m_bars.at(i)->pen().width() / 2 + 2; - if (m_series->labelsPosition() == QAbstractBarSeries::LabelsCenter) - yPos = m_layout.at(i).center().y() - label->boundingRect().center().y(); - else if (m_series->labelsPosition() == QAbstractBarSeries::LabelsInsideEnd) - yPos = m_layout.at(i).top() - offset; - else if (m_series->labelsPosition() == QAbstractBarSeries::LabelsInsideBase) - yPos = m_layout.at(i).bottom() - label->boundingRect().height() + offset; - else if (m_series->labelsPosition() == QAbstractBarSeries::LabelsOutsideEnd) - yPos = m_layout.at(i).top() - label->boundingRect().height() + offset; - - label->setPos(xPos, yPos); - label->setZValue(zValue() + 1); - } + positionLabelsVertical(); } #include "moc_percentbarchartitem_p.cpp" diff --git a/src/charts/barchart/vertical/stacked/stackedbarchartitem.cpp b/src/charts/barchart/vertical/stacked/stackedbarchartitem.cpp index d3f0a83..aa8624d 100644 --- a/src/charts/barchart/vertical/stacked/stackedbarchartitem.cpp +++ b/src/charts/barchart/vertical/stacked/stackedbarchartitem.cpp @@ -110,24 +110,7 @@ void StackedBarChartItem::handleLabelsPositionChanged() void StackedBarChartItem::positionLabels() { - for (int i = 0; i < m_layout.count(); i++) { - QGraphicsTextItem *label = m_labels.at(i); - qreal xPos = m_layout.at(i).center().x() - label->boundingRect().center().x(); - qreal yPos = 0; - - int offset = m_bars.at(i)->pen().width() / 2 + 2; - if (m_series->labelsPosition() == QAbstractBarSeries::LabelsCenter) - yPos = m_layout.at(i).center().y() - label->boundingRect().center().y(); - else if (m_series->labelsPosition() == QAbstractBarSeries::LabelsInsideEnd) - yPos = m_layout.at(i).top() - offset; - else if (m_series->labelsPosition() == QAbstractBarSeries::LabelsInsideBase) - yPos = m_layout.at(i).bottom() - label->boundingRect().height() + offset; - else if (m_series->labelsPosition() == QAbstractBarSeries::LabelsOutsideEnd) - yPos = m_layout.at(i).top() - label->boundingRect().height() + offset; - - label->setPos(xPos, yPos); - label->setZValue(zValue() + 1); - } + positionLabelsVertical(); } #include "moc_stackedbarchartitem_p.cpp" diff --git a/tests/auto/qbarseries/tst_qbarseries.cpp b/tests/auto/qbarseries/tst_qbarseries.cpp index 580d35c..d03f237 100644 --- a/tests/auto/qbarseries/tst_qbarseries.cpp +++ b/tests/auto/qbarseries/tst_qbarseries.cpp @@ -60,6 +60,7 @@ private slots: void setLabelsVisible(); void setLabelsFormat(); void setLabelsPosition(); + void setLabelsAngle(); void opacity(); void mouseclicked_data(); void mouseclicked(); @@ -405,6 +406,19 @@ void tst_QBarSeries::setLabelsPosition() QCOMPARE(m_barseries->labelsPosition(), QBarSeries::LabelsCenter); } +void tst_QBarSeries::setLabelsAngle() +{ + QSignalSpy labelsAngleSpy(m_barseries, + SIGNAL(labelsAngleChanged(qreal))); + QCOMPARE(m_barseries->labelsAngle(), 0.0); + + m_barseries->setLabelsAngle(55.0); + TRY_COMPARE(labelsAngleSpy.count(), 1); + QList arguments = labelsAngleSpy.takeFirst(); + QVERIFY(arguments.at(0).value() == 55.0); + QCOMPARE(m_barseries->labelsAngle(), 55.0); +} + void tst_QBarSeries::opacity() { QSignalSpy opacitySpy(m_barseries, SIGNAL(opacityChanged())); diff --git a/tests/auto/qhorizontalbarseries/tst_qhorizontalbarseries.cpp b/tests/auto/qhorizontalbarseries/tst_qhorizontalbarseries.cpp index 643d221..f32b8f7 100644 --- a/tests/auto/qhorizontalbarseries/tst_qhorizontalbarseries.cpp +++ b/tests/auto/qhorizontalbarseries/tst_qhorizontalbarseries.cpp @@ -57,6 +57,7 @@ private slots: void setLabelsVisible(); void setLabelsFormat(); void setLabelsPosition(); + void setLabelsAngle(); void mouseclicked_data(); void mouseclicked(); void mousehovered_data(); @@ -370,6 +371,19 @@ void tst_QHorizontalBarSeries::setLabelsPosition() QCOMPARE(m_barseries->labelsPosition(), QHorizontalBarSeries::LabelsCenter); } +void tst_QHorizontalBarSeries::setLabelsAngle() +{ + QSignalSpy labelsAngleSpy(m_barseries, + SIGNAL(labelsAngleChanged(qreal))); + QCOMPARE(m_barseries->labelsAngle(), 0.0); + + m_barseries->setLabelsAngle(55.0); + TRY_COMPARE(labelsAngleSpy.count(), 1); + QList arguments = labelsAngleSpy.takeFirst(); + QVERIFY(arguments.at(0).value() == 55.0); + QCOMPARE(m_barseries->labelsAngle(), 55.0); +} + void tst_QHorizontalBarSeries::mouseclicked_data() { diff --git a/tests/auto/qhorizontalpercentbarseries/tst_qhorizontalpercentbarseries.cpp b/tests/auto/qhorizontalpercentbarseries/tst_qhorizontalpercentbarseries.cpp index cdba077..b0408b8 100644 --- a/tests/auto/qhorizontalpercentbarseries/tst_qhorizontalpercentbarseries.cpp +++ b/tests/auto/qhorizontalpercentbarseries/tst_qhorizontalpercentbarseries.cpp @@ -45,6 +45,7 @@ private slots: void type(); void setLabelsFormat(); void setLabelsPosition(); + void setLabelsAngle(); void mouseclicked_data(); void mouseclicked(); void mousehovered_data(); @@ -155,6 +156,19 @@ void tst_QHorizontalPercentBarSeries::setLabelsPosition() QCOMPARE(m_barseries->labelsPosition(), QHorizontalPercentBarSeries::LabelsCenter); } +void tst_QHorizontalPercentBarSeries::setLabelsAngle() +{ + QSignalSpy labelsAngleSpy(m_barseries, + SIGNAL(labelsAngleChanged(qreal))); + QCOMPARE(m_barseries->labelsAngle(), 0.0); + + m_barseries->setLabelsAngle(55.0); + TRY_COMPARE(labelsAngleSpy.count(), 1); + QList arguments = labelsAngleSpy.takeFirst(); + QVERIFY(arguments.at(0).value() == 55.0); + QCOMPARE(m_barseries->labelsAngle(), 55.0); +} + void tst_QHorizontalPercentBarSeries::mouseclicked_data() { diff --git a/tests/auto/qhorizontalstackedbarseries/tst_qhorizontalstackedbarseries.cpp b/tests/auto/qhorizontalstackedbarseries/tst_qhorizontalstackedbarseries.cpp index 0eb00fe..73e75a2 100644 --- a/tests/auto/qhorizontalstackedbarseries/tst_qhorizontalstackedbarseries.cpp +++ b/tests/auto/qhorizontalstackedbarseries/tst_qhorizontalstackedbarseries.cpp @@ -45,6 +45,7 @@ private slots: void type(); void setLabelsFormat(); void setLabelsPosition(); + void setLabelsAngle(); void mouseclicked_data(); void mouseclicked(); void mousehovered_data(); @@ -154,6 +155,19 @@ void tst_QHorizontalStackedBarSeries::setLabelsPosition() QCOMPARE(m_barseries->labelsPosition(), QHorizontalStackedBarSeries::LabelsCenter); } +void tst_QHorizontalStackedBarSeries::setLabelsAngle() +{ + QSignalSpy labelsAngleSpy(m_barseries, + SIGNAL(labelsAngleChanged(qreal))); + QCOMPARE(m_barseries->labelsAngle(), 0.0); + + m_barseries->setLabelsAngle(55.0); + TRY_COMPARE(labelsAngleSpy.count(), 1); + QList arguments = labelsAngleSpy.takeFirst(); + QVERIFY(arguments.at(0).value() == 55.0); + QCOMPARE(m_barseries->labelsAngle(), 55.0); +} + void tst_QHorizontalStackedBarSeries::mouseclicked_data() { diff --git a/tests/auto/qpercentbarseries/tst_qpercentbarseries.cpp b/tests/auto/qpercentbarseries/tst_qpercentbarseries.cpp index 8f243cd..de49a6a 100644 --- a/tests/auto/qpercentbarseries/tst_qpercentbarseries.cpp +++ b/tests/auto/qpercentbarseries/tst_qpercentbarseries.cpp @@ -45,6 +45,7 @@ private slots: void type(); void setLabelsFormat(); void setLabelsPosition(); + void setLabelsAngle(); void mouseclicked_data(); void mouseclicked(); void mousehovered_data(); @@ -160,6 +161,19 @@ void tst_QPercentBarSeries::setLabelsPosition() QCOMPARE(m_barseries->labelsPosition(), QPercentBarSeries::LabelsCenter); } +void tst_QPercentBarSeries::setLabelsAngle() +{ + QSignalSpy labelsAngleSpy(m_barseries, + SIGNAL(labelsAngleChanged(qreal))); + QCOMPARE(m_barseries->labelsAngle(), 0.0); + + m_barseries->setLabelsAngle(55.0); + TRY_COMPARE(labelsAngleSpy.count(), 1); + QList arguments = labelsAngleSpy.takeFirst(); + QVERIFY(arguments.at(0).value() == 55.0); + QCOMPARE(m_barseries->labelsAngle(), 55.0); +} + void tst_QPercentBarSeries::mouseclicked() { SKIP_IF_CANNOT_TEST_MOUSE_EVENTS(); diff --git a/tests/auto/qstackedbarseries/tst_qstackedbarseries.cpp b/tests/auto/qstackedbarseries/tst_qstackedbarseries.cpp index 0193939..9dc51ae 100644 --- a/tests/auto/qstackedbarseries/tst_qstackedbarseries.cpp +++ b/tests/auto/qstackedbarseries/tst_qstackedbarseries.cpp @@ -45,6 +45,7 @@ private slots: void type(); void setLabelsFormat(); void setLabelsPosition(); + void setLabelsAngle(); void mouseclicked_data(); void mouseclicked(); void mousehovered_data(); @@ -154,6 +155,19 @@ void tst_QStackedBarSeries::setLabelsPosition() QCOMPARE(m_barseries->labelsPosition(), QStackedBarSeries::LabelsCenter); } +void tst_QStackedBarSeries::setLabelsAngle() +{ + QSignalSpy labelsAngleSpy(m_barseries, + SIGNAL(labelsAngleChanged(qreal))); + QCOMPARE(m_barseries->labelsAngle(), 0.0); + + m_barseries->setLabelsAngle(55.0); + TRY_COMPARE(labelsAngleSpy.count(), 1); + QList arguments = labelsAngleSpy.takeFirst(); + QVERIFY(arguments.at(0).value() == 55.0); + QCOMPARE(m_barseries->labelsAngle(), 55.0); +} + void tst_QStackedBarSeries::mouseclicked_data() { diff --git a/tests/manual/qmlchartproperties/qml/qmlchartproperties/BarEditor.qml b/tests/manual/qmlchartproperties/qml/qmlchartproperties/BarEditor.qml index 0a2ec3e..98b7ab8 100644 --- a/tests/manual/qmlchartproperties/qml/qmlchartproperties/BarEditor.qml +++ b/tests/manual/qmlchartproperties/qml/qmlchartproperties/BarEditor.qml @@ -186,6 +186,14 @@ Row { text: "set 1 label color" onClicked: series.at(0).labelColor = main.nextColor(); } + Button { + text: "labels angle +" + onClicked: series.labelsAngle = series.labelsAngle + 5; + } + Button { + text: "labels angle -" + onClicked: series.labelsAngle = series.labelsAngle - 5; + } FontEditor { id: fontEditor fontDescription: "label"