From ec1756baf2334364097278366447d3223f618088 2013-05-27 11:07:53 From: Miikka Heikkinen Date: 2013-05-27 11:07:53 Subject: [PATCH] Fix multiline axis label positioning. Refactored axis label/title handling to not use QFontMetrics but a dummy graphics text item instead. Task-number: QTRD-2056 Change-Id: Ib24f26d214046f97f4fd2d3b2dd720e866561dbd Reviewed-by: Tomi Korpipää --- diff --git a/src/axis/barcategoryaxis/chartbarcategoryaxisx.cpp b/src/axis/barcategoryaxis/chartbarcategoryaxisx.cpp index 9d09aeb..f4f8bc6 100644 --- a/src/axis/barcategoryaxis/chartbarcategoryaxisx.cpp +++ b/src/axis/barcategoryaxis/chartbarcategoryaxisx.cpp @@ -22,7 +22,6 @@ #include "chartpresenter_p.h" #include "qbarcategoryaxis_p.h" #include "abstractchartlayout_p.h" -#include #include #include @@ -104,7 +103,6 @@ QSizeF ChartBarCategoryAxisX::sizeHint(Qt::SizeHint which, const QSizeF &constra { Q_UNUSED(constraint) - QFontMetrics fn(axis()->labelsFont()); QSizeF sh; QSizeF base = HorizontalAxis::sizeHint(which, constraint); QStringList ticksList = m_categoriesAxis->categories(); @@ -114,20 +112,18 @@ QSizeF ChartBarCategoryAxisX::sizeHint(Qt::SizeHint which, const QSizeF &constra switch (which) { case Qt::MinimumSize: { - QRectF boundingRect = labelBoundingRect(fn, "..."); - height = boundingRect.height() + labelPadding(); - height += base.height(); + QRectF boundingRect = textBoundingRect(axis()->labelsFont(), "...", axis()->labelsAngle()); + height = boundingRect.height() + labelPadding() + base.height() + 1.0; sh = QSizeF(width, height); break; } case Qt::PreferredSize:{ - int labelHeight = 0; + qreal labelHeight = 0.0; foreach (const QString& s, ticksList) { - QRect rect = labelBoundingRect(fn, s); + QRectF rect = textBoundingRect(axis()->labelsFont(), s, axis()->labelsAngle()); labelHeight = qMax(rect.height(), labelHeight); } - height = labelHeight + labelPadding(); - height += base.height(); + height = labelHeight + labelPadding() + base.height() + 1.0; sh = QSizeF(width, height); break; } diff --git a/src/axis/barcategoryaxis/chartbarcategoryaxisy.cpp b/src/axis/barcategoryaxis/chartbarcategoryaxisy.cpp index 20194bb..6d44546 100644 --- a/src/axis/barcategoryaxis/chartbarcategoryaxisy.cpp +++ b/src/axis/barcategoryaxis/chartbarcategoryaxisy.cpp @@ -23,7 +23,6 @@ #include "qbarcategoryaxis_p.h" #include "abstractchartlayout_p.h" #include -#include #include QTCOMMERCIALCHART_BEGIN_NAMESPACE @@ -103,7 +102,6 @@ QSizeF ChartBarCategoryAxisY::sizeHint(Qt::SizeHint which, const QSizeF &constra { Q_UNUSED(constraint) - QFontMetrics fn(axis()->labelsFont()); QSizeF sh; QSizeF base = VerticalAxis::sizeHint(which, constraint); QStringList ticksList = m_categoriesAxis->categories(); @@ -112,23 +110,21 @@ QSizeF ChartBarCategoryAxisY::sizeHint(Qt::SizeHint which, const QSizeF &constra switch (which) { case Qt::MinimumSize: { - QRectF boundingRect = labelBoundingRect(fn, "..."); - width = boundingRect.width() + labelPadding(); - width += base.width(); - if (base.width() > 0) + QRectF boundingRect = textBoundingRect(axis()->labelsFont(), "...", axis()->labelsAngle()); + width = boundingRect.width() + labelPadding() + base.width() + 1.0; + if (base.width() > 0.0) width += labelPadding(); sh = QSizeF(width, height); break; } case Qt::PreferredSize:{ - int labelWidth = 0; + qreal labelWidth = 0.0; foreach (const QString& s, ticksList) { - QRect rect = labelBoundingRect(fn, s); + QRectF rect = textBoundingRect(axis()->labelsFont(), s, axis()->labelsAngle()); labelWidth = qMax(rect.width(), labelWidth); } - width = labelWidth + labelPadding() + 1; - width += base.width(); - if (base.width() > 0) + width = labelWidth + labelPadding() + base.width() + 1.0; + if (base.width() > 0.0) width += labelPadding(); sh = QSizeF(width, height); break; diff --git a/src/axis/categoryaxis/chartcategoryaxisx.cpp b/src/axis/categoryaxis/chartcategoryaxisx.cpp index cb1ede6..8c83812 100644 --- a/src/axis/categoryaxis/chartcategoryaxisx.cpp +++ b/src/axis/categoryaxis/chartcategoryaxisx.cpp @@ -24,7 +24,6 @@ #include "chartpresenter_p.h" #include "abstractchartlayout_p.h" #include -#include #include QTCOMMERCIALCHART_BEGIN_NAMESPACE @@ -78,7 +77,6 @@ QSizeF ChartCategoryAxisX::sizeHint(Qt::SizeHint which, const QSizeF &constraint { Q_UNUSED(constraint) - QFontMetrics fn(axis()->labelsFont()); QSizeF sh; QSizeF base = HorizontalAxis::sizeHint(which, constraint); QStringList ticksList = m_axis->categoriesLabels(); @@ -87,20 +85,18 @@ QSizeF ChartCategoryAxisX::sizeHint(Qt::SizeHint which, const QSizeF &constraint switch (which) { case Qt::MinimumSize: { - QRectF boundingRect = labelBoundingRect(fn, "..."); - height = boundingRect.height() + labelPadding(); - height += base.height(); + QRectF boundingRect = textBoundingRect(axis()->labelsFont(), "...", axis()->labelsAngle()); + height = boundingRect.height() + labelPadding() + base.height() + 1.0; sh = QSizeF(width, height); break; } case Qt::PreferredSize: { - int labelHeight = 0; + qreal labelHeight = 0.0; foreach (const QString& s, ticksList) { - QRect rect = labelBoundingRect(fn, s); + QRectF rect = textBoundingRect(axis()->labelsFont(), s, axis()->labelsAngle()); labelHeight = qMax(rect.height(), labelHeight); } - height = labelHeight + labelPadding(); - height += base.height(); + height = labelHeight + labelPadding() + base.height() + 1.0; sh = QSizeF(width, height); break; } diff --git a/src/axis/categoryaxis/chartcategoryaxisy.cpp b/src/axis/categoryaxis/chartcategoryaxisy.cpp index 96f5a2d..f38400b 100644 --- a/src/axis/categoryaxis/chartcategoryaxisy.cpp +++ b/src/axis/categoryaxis/chartcategoryaxisy.cpp @@ -24,7 +24,6 @@ #include "chartpresenter_p.h" #include "abstractchartlayout_p.h" #include -#include #include #include @@ -78,7 +77,6 @@ QSizeF ChartCategoryAxisY::sizeHint(Qt::SizeHint which, const QSizeF &constraint { Q_UNUSED(constraint) - QFontMetrics fn(axis()->labelsFont()); QSizeF sh; QSizeF base = VerticalAxis::sizeHint(which, constraint); QStringList ticksList = m_axis->categoriesLabels(); @@ -87,20 +85,18 @@ QSizeF ChartCategoryAxisY::sizeHint(Qt::SizeHint which, const QSizeF &constraint switch (which) { case Qt::MinimumSize: { - QRectF boundingRect = labelBoundingRect(fn, "..."); - width = boundingRect.width() + labelPadding(); - width += base.width(); + QRectF boundingRect = textBoundingRect(axis()->labelsFont(), "...", axis()->labelsAngle()); + width = boundingRect.width() + labelPadding() + base.width() + 1.0; sh = QSizeF(width, height); break; } case Qt::PreferredSize: { - int labelWidth = 0; + qreal labelWidth = 0.0; foreach (const QString& s, ticksList) { - QRect rect = labelBoundingRect(fn, s); + QRectF rect = textBoundingRect(axis()->labelsFont(), s, axis()->labelsAngle()); labelWidth = qMax(rect.width(), labelWidth); } - width = labelWidth + labelPadding() + 1; - width += base.width(); + width = labelWidth + labelPadding() + base.width() + 1.0; sh = QSizeF(width, height); break; } diff --git a/src/axis/chartaxiselement.cpp b/src/axis/chartaxiselement.cpp index 19fa8e1..f5e019d 100644 --- a/src/axis/chartaxiselement.cpp +++ b/src/axis/chartaxiselement.cpp @@ -24,10 +24,18 @@ #include "abstractchartlayout_p.h" #include #include -#include QTCOMMERCIALCHART_BEGIN_NAMESPACE +QGraphicsSimpleTextItem *dummyTextItem = 0; +class StaticDeleter +{ +public: + StaticDeleter() {} + ~StaticDeleter() { delete dummyTextItem; } +}; +StaticDeleter staticDeleter; + ChartAxisElement::ChartAxisElement(QAbstractAxis *axis, QGraphicsItem *item, bool intervalAxis) : ChartElement(item), m_axis(axis), @@ -41,6 +49,8 @@ ChartAxisElement::ChartAxisElement(QAbstractAxis *axis, QGraphicsItem *item, boo { //initial initialization + if (!dummyTextItem) + dummyTextItem = new QGraphicsSimpleTextItem; m_arrow->setHandlesChildEvents(false); m_arrow->setZValue(ChartPresenter::AxisZValue); m_labels->setZValue(ChartPresenter::AxisZValue); @@ -184,19 +194,44 @@ void ChartAxisElement::handleVisibleChanged(bool visible) if (presenter()) presenter()->layout()->invalidate(); } -QRect ChartAxisElement::labelBoundingRect(const QFontMetrics &fn, const QString &label) const +QRectF ChartAxisElement::textBoundingRect(const QFont &font, const QString &text, qreal angle) const { - QRect boundingRect = fn.boundingRect(label); - // Take label rotation into account - if (axis()->labelsAngle()) { + dummyTextItem->setFont(font); + dummyTextItem->setText(text); + QRectF boundingRect = dummyTextItem->boundingRect(); + + // Take rotation into account + if (angle) { QTransform transform; - transform.rotate(axis()->labelsAngle()); + transform.rotate(angle); boundingRect = transform.mapRect(boundingRect); } return boundingRect; } +// boundingRect parameter returns the rotated bounding rect of the text +QString ChartAxisElement::truncatedText(const QFont &font, const QString &text, qreal angle, + qreal maxSize, Qt::Orientation constraintOrientation, + QRectF &boundingRect) const +{ + QString truncatedString(text); + boundingRect = textBoundingRect(font, truncatedString, angle); + qreal checkDimension = ((constraintOrientation == Qt::Horizontal) + ? boundingRect.width() : boundingRect.height()); + if (checkDimension > maxSize) { + truncatedString.append("..."); + while (checkDimension > maxSize && truncatedString.length() > 3) { + truncatedString.remove(truncatedString.length() - 4, 1); + boundingRect = textBoundingRect(font, truncatedString, angle); + checkDimension = ((constraintOrientation == Qt::Horizontal) + ? boundingRect.width() : boundingRect.height()); + } + } + + return truncatedString; +} + void ChartAxisElement::handleRangeChanged(qreal min, qreal max) { Q_UNUSED(min); diff --git a/src/axis/chartaxiselement_p.h b/src/axis/chartaxiselement_p.h index 0fdd207..83e3e4e 100644 --- a/src/axis/chartaxiselement_p.h +++ b/src/axis/chartaxiselement_p.h @@ -70,7 +70,9 @@ public: QRectF axisGeometry() const { return m_axisRect; } void setAxisGeometry(const QRectF &axisGeometry) { m_axisRect = axisGeometry; } - QRect labelBoundingRect(const QFontMetrics &fn, const QString &label) const; + QRectF textBoundingRect(const QFont &font, const QString &text, qreal angle = 0.0) const; + QString truncatedText(const QFont &font, const QString &text, qreal angle, qreal maxSize, + Qt::Orientation constraintOrientation, QRectF &boundingRect) const; void axisSelected(); diff --git a/src/axis/datetimeaxis/chartdatetimeaxisx.cpp b/src/axis/datetimeaxis/chartdatetimeaxisx.cpp index 6ff32c5..a746ec9 100644 --- a/src/axis/datetimeaxis/chartdatetimeaxisx.cpp +++ b/src/axis/datetimeaxis/chartdatetimeaxisx.cpp @@ -24,7 +24,6 @@ #include "abstractchartlayout_p.h" #include #include -#include #include QTCOMMERCIALCHART_BEGIN_NAMESPACE @@ -85,7 +84,6 @@ QSizeF ChartDateTimeAxisX::sizeHint(Qt::SizeHint which, const QSizeF &constraint { Q_UNUSED(constraint) - QFontMetrics fn(axis()->labelsFont()); QSizeF sh; QSizeF base = HorizontalAxis::sizeHint(which, constraint); @@ -100,26 +98,24 @@ QSizeF ChartDateTimeAxisX::sizeHint(Qt::SizeHint which, const QSizeF &constraint switch (which) { case Qt::MinimumSize: { - QRectF boundingRect = labelBoundingRect(fn, "..."); + QRectF boundingRect = textBoundingRect(axis()->labelsFont(), "...", axis()->labelsAngle()); width = boundingRect.width() / 2.0; - height = boundingRect.height() + labelPadding(); - height += base.height(); + height = boundingRect.height() + labelPadding() + base.height() + 1.0; sh = QSizeF(width, height); break; } case Qt::PreferredSize: { - int labelHeight = 0; - int firstWidth = -1; + qreal labelHeight = 0.0; + qreal firstWidth = -1.0; foreach (const QString& s, ticksList) { - QRect rect = labelBoundingRect(fn, s); + QRectF rect = textBoundingRect(axis()->labelsFont(), s, axis()->labelsAngle()); labelHeight = qMax(rect.height(), labelHeight); width = rect.width(); - if (firstWidth < 0) + if (firstWidth < 0.0) firstWidth = width; } - height = labelHeight + labelPadding(); - height += base.height(); - width = qMax(width, qreal(firstWidth)) / 2.0; + height = labelHeight + labelPadding() + base.height() + 1.0; + width = qMax(width, firstWidth) / 2.0; sh = QSizeF(width, height); break; } diff --git a/src/axis/datetimeaxis/chartdatetimeaxisy.cpp b/src/axis/datetimeaxis/chartdatetimeaxisy.cpp index a8fe58a..49a57f2 100644 --- a/src/axis/datetimeaxis/chartdatetimeaxisy.cpp +++ b/src/axis/datetimeaxis/chartdatetimeaxisy.cpp @@ -23,7 +23,6 @@ #include "qdatetimeaxis.h" #include "abstractchartlayout_p.h" #include -#include #include #include @@ -86,7 +85,6 @@ QSizeF ChartDateTimeAxisY::sizeHint(Qt::SizeHint which, const QSizeF &constraint { Q_UNUSED(constraint) - QFontMetrics fn(axis()->labelsFont()); QSizeF sh; QSizeF base = VerticalAxis::sizeHint(which, constraint); @@ -101,26 +99,24 @@ QSizeF ChartDateTimeAxisY::sizeHint(Qt::SizeHint which, const QSizeF &constraint switch (which) { case Qt::MinimumSize: { - QRectF boundingRect = labelBoundingRect(fn, "..."); - width = boundingRect.width() + labelPadding(); - width += base.width(); + QRectF boundingRect = textBoundingRect(axis()->labelsFont(), "...", axis()->labelsAngle()); + width = boundingRect.width() + labelPadding() + base.width() + 1.0; height = boundingRect.height() / 2.0; sh = QSizeF(width, height); break; } case Qt::PreferredSize: { - int labelWidth = 0; - int firstHeight = -1; + qreal labelWidth = 0.0; + qreal firstHeight = -1.0; foreach (const QString& s, ticksList) { - QRect rect = labelBoundingRect(fn, s); + QRectF rect = textBoundingRect(axis()->labelsFont(), s, axis()->labelsAngle()); labelWidth = qMax(rect.width(), labelWidth); height = rect.height(); - if (firstHeight < 0) + if (firstHeight < 0.0) firstHeight = height; } - width = labelWidth + labelPadding() + 2; //two pixels of tolerance - width += base.width(); - height = qMax(height, qreal(firstHeight)) / 2.0; + width = labelWidth + labelPadding() + base.width() + 2.0; //two pixels of tolerance + height = qMax(height, firstHeight) / 2.0; sh = QSizeF(width, height); break; } diff --git a/src/axis/horizontalaxis.cpp b/src/axis/horizontalaxis.cpp index 323aefe..2a4a4eb 100644 --- a/src/axis/horizontalaxis.cpp +++ b/src/axis/horizontalaxis.cpp @@ -20,7 +20,6 @@ #include "horizontalaxis_p.h" #include "qabstractaxis_p.h" -#include #include #include @@ -65,32 +64,13 @@ void HorizontalAxis::updateGeometry() arrowItem->setLine(gridRect.left(), axisRect.top(), gridRect.right(), axisRect.top()); qreal width = 0; - QFontMetrics fn(axis()->labelsFont()); //title int titlePad = 0; QRectF titleBoundingRect; QString titleText = axis()->titleText(); if (!titleText.isEmpty() && titleItem()->isVisible()) { - int size(0); - size = gridRect.width(); - - QGraphicsSimpleTextItem dummyTitle; - dummyTitle.setFont(axis()->titleFont()); - dummyTitle.setText(axis()->titleText()); - QRectF dummyRect = dummyTitle.boundingRect(); - - if (dummyRect.width() > size) { - QString string = titleText + "..."; - while (dummyRect.width() > size && string.length() > 3) { - string.remove(string.length() - 4, 1); - dummyTitle.setText(string); - dummyRect = dummyTitle.boundingRect(); - } - title->setText(string); - } else { - title->setText(titleText); - } + title->setText(truncatedText(axis()->titleFont(), titleText, 0.0, gridRect.width(), Qt::Horizontal, QRectF())); titlePad = titlePadding(); titleBoundingRect = title->boundingRect(); @@ -104,7 +84,6 @@ void HorizontalAxis::updateGeometry() } for (int i = 0; i < layout.size(); ++i) { - //items QGraphicsLineItem *gridItem = static_cast(lines.at(i)); QGraphicsLineItem *tickItem = static_cast(arrow.at(i + 1)); @@ -115,18 +94,10 @@ void HorizontalAxis::updateGeometry() //label text wrapping QString text = labelList.at(i); - QRectF boundingRect = labelBoundingRect(fn, text); + QRectF boundingRect; qreal size = axisRect.bottom() - axisRect.top() - labelPadding() - titleBoundingRect.height() - (titlePad * 2); - if (boundingRect.height() > size) { - QString label = text + "..."; - while (boundingRect.height() >= size && label.length() > 3) { - label.remove(label.length() - 4, 1); - boundingRect = labelBoundingRect(fn, label); - } - labelItem->setText(label); - } else { - labelItem->setText(text); - } + labelItem->setText(truncatedText(axis()->labelsFont(), text, axis()->labelsAngle(), + size, Qt::Vertical, boundingRect)); //label transformation origin point const QRectF& rect = labelItem->boundingRect(); @@ -214,16 +185,13 @@ QSizeF HorizontalAxis::sizeHint(Qt::SizeHint which, const QSizeF &constraint) co switch (which) { case Qt::MinimumSize: { - QFontMetrics fn(axis()->titleFont()); - sh = QSizeF(fn.boundingRect("...").width(), fn.height() + (titlePadding() * 2)); + QRectF titleRect = textBoundingRect(axis()->titleFont(), "..."); + sh = QSizeF(titleRect.width(), titleRect.height() + (titlePadding() * 2)); break; } case Qt::MaximumSize: case Qt::PreferredSize: { - QGraphicsSimpleTextItem dummyTitle; - dummyTitle.setFont(axis()->titleFont()); - dummyTitle.setText(axis()->titleText()); - QRectF titleRect = dummyTitle.boundingRect(); + QRectF titleRect = textBoundingRect(axis()->titleFont(), axis()->titleText()); sh = QSizeF(titleRect.width(), titleRect.height() + (titlePadding() * 2)); break; } diff --git a/src/axis/logvalueaxis/chartlogvalueaxisx.cpp b/src/axis/logvalueaxis/chartlogvalueaxisx.cpp index ac8f1f0..d7c6b69 100644 --- a/src/axis/logvalueaxis/chartlogvalueaxisx.cpp +++ b/src/axis/logvalueaxis/chartlogvalueaxisx.cpp @@ -23,7 +23,6 @@ #include "qlogvalueaxis.h" #include "abstractchartlayout_p.h" #include -#include #include #include @@ -87,7 +86,6 @@ QSizeF ChartLogValueAxisX::sizeHint(Qt::SizeHint which, const QSizeF &constraint { Q_UNUSED(constraint) - QFontMetrics fn(axis()->labelsFont()); QSizeF sh; QSizeF base = HorizontalAxis::sizeHint(which, constraint); @@ -106,26 +104,24 @@ QSizeF ChartLogValueAxisX::sizeHint(Qt::SizeHint which, const QSizeF &constraint switch (which) { case Qt::MinimumSize:{ - QRectF boundingRect = labelBoundingRect(fn, "..."); + QRectF boundingRect = textBoundingRect(axis()->labelsFont(), "...", axis()->labelsAngle()); width = boundingRect.width() / 2.0; - height = boundingRect.height() + labelPadding(); - height += base.height(); + height = boundingRect.height() + labelPadding() + base.height() + 1.0; sh = QSizeF(width, height); break; } case Qt::PreferredSize: { - int labelHeight = 0; - int firstWidth = -1; + qreal labelHeight = 0.0; + qreal firstWidth = -1.0; foreach (const QString& s, ticksList) { - QRect rect = labelBoundingRect(fn, s); + QRectF rect = textBoundingRect(axis()->labelsFont(), s, axis()->labelsAngle()); labelHeight = qMax(rect.height(), labelHeight); width = rect.width(); - if (firstWidth < 0) + if (firstWidth < 0.0) firstWidth = width; } - height = labelHeight + labelPadding(); - height += base.height(); - width = qMax(width, qreal(firstWidth)) / 2.0; + height = labelHeight + labelPadding() + base.height() + 1.0; + width = qMax(width, firstWidth) / 2.0; sh = QSizeF(width, height); break; } diff --git a/src/axis/logvalueaxis/chartlogvalueaxisy.cpp b/src/axis/logvalueaxis/chartlogvalueaxisy.cpp index 42ae875..38a68ff 100644 --- a/src/axis/logvalueaxis/chartlogvalueaxisy.cpp +++ b/src/axis/logvalueaxis/chartlogvalueaxisy.cpp @@ -23,7 +23,6 @@ #include "qlogvalueaxis.h" #include "abstractchartlayout_p.h" #include -#include #include #include @@ -87,7 +86,6 @@ QSizeF ChartLogValueAxisY::sizeHint(Qt::SizeHint which, const QSizeF &constraint { Q_UNUSED(constraint) - QFontMetrics fn(axis()->labelsFont()); QSizeF sh; QSizeF base = VerticalAxis::sizeHint(which, constraint); @@ -106,26 +104,24 @@ QSizeF ChartLogValueAxisY::sizeHint(Qt::SizeHint which, const QSizeF &constraint switch (which) { case Qt::MinimumSize: { - QRectF boundingRect = labelBoundingRect(fn, "..."); - width = boundingRect.width() + labelPadding(); - width += base.width(); + QRectF boundingRect = textBoundingRect(axis()->labelsFont(), "...", axis()->labelsAngle()); + width = boundingRect.width() + labelPadding() + base.width() + 1.0; height = boundingRect.height() / 2.0; sh = QSizeF(width, height); break; } case Qt::PreferredSize: { - int labelWidth = 0; - int firstHeight = -1; + qreal labelWidth = 0.0; + qreal firstHeight = -1.0; foreach (const QString& s, ticksList) { - QRect rect = labelBoundingRect(fn, s); + QRectF rect = textBoundingRect(axis()->labelsFont(), s, axis()->labelsAngle()); labelWidth = qMax(rect.width(), labelWidth); height = rect.height(); - if (firstHeight < 0) + if (firstHeight < 0.0) firstHeight = height; } - width = labelWidth + labelPadding() + 2; //two pixels of tolerance - width += base.width(); - height = qMax(height, qreal(firstHeight)) / 2.0; + width = labelWidth + labelPadding() + base.width() + 2.0; //two pixels of tolerance + height = qMax(height, firstHeight) / 2.0; sh = QSizeF(width, height); break; } diff --git a/src/axis/polarchartaxisangular.cpp b/src/axis/polarchartaxisangular.cpp index 07339e4..a7f6994 100644 --- a/src/axis/polarchartaxisangular.cpp +++ b/src/axis/polarchartaxisangular.cpp @@ -23,7 +23,6 @@ #include "abstractchartlayout_p.h" #include "qabstractaxis.h" #include "qabstractaxis_p.h" -#include #include QTCOMMERCIALCHART_BEGIN_NAMESPACE @@ -59,7 +58,6 @@ void PolarChartAxisAngular::updateGeometry() qreal radius = axisGeometry().height() / 2.0; - QFontMetrics fn(axis()->labelsFont()); QRectF previousLabelRect; QRectF firstLabelRect; @@ -124,7 +122,7 @@ void PolarChartAxisAngular::updateGeometry() const QRectF &rect = labelItem->boundingRect(); QPointF labelCenter = rect.center(); labelItem->setTransformOriginPoint(labelCenter.x(), labelCenter.y()); - QRectF boundingRect = labelBoundingRect(fn, labelList.at(i)); + QRectF boundingRect = textBoundingRect(axis()->labelsFont(), labelList.at(i), axis()->labelsAngle()); boundingRect.moveCenter(labelCenter); QPointF positionDiff(rect.topLeft() - boundingRect.topLeft()); @@ -221,28 +219,9 @@ void PolarChartAxisAngular::updateGeometry() // Title, centered above the chart QString titleText = axis()->titleText(); if (!titleText.isEmpty() && axis()->isTitleVisible()) { - int size(0); - size = axisGeometry().width(); - - QGraphicsSimpleTextItem dummyTitle; - dummyTitle.setFont(axis()->titleFont()); - dummyTitle.setText(titleText); - QRectF dummyRect = dummyTitle.boundingRect(); - - if (dummyRect.width() > size) { - QString string = titleText + "..."; - while (dummyRect.width() > size && string.length() > 3) { - string.remove(string.length() - 4, 1); - dummyTitle.setText(string); - dummyRect = dummyTitle.boundingRect(); - } - title->setText(string); - } else { - title->setText(titleText); - } + title->setText(truncatedText(axis()->titleFont(), titleText, 0.0, axisGeometry().width(), Qt::Horizontal, QRectF())); - QRectF titleBoundingRect; - titleBoundingRect = title->boundingRect(); + QRectF titleBoundingRect = title->boundingRect(); QPointF titleCenter = center - titleBoundingRect.center(); title->setPos(titleCenter.x(), axisGeometry().top() - qreal(titlePadding()) * 2.0 - titleBoundingRect.height() - labelHeight); } @@ -339,7 +318,6 @@ qreal PolarChartAxisAngular::preferredAxisRadius(const QSizeF &maxSize) // This is a horrible way to find out the maximum radius for angular axis and its labels. // It just increments the radius down until everyhing fits the constraint size. // Proper way would be to actually calculate it but this seems to work reasonably fast as it is. - QFontMetrics fm(font); bool nextTickVisible = false; for (int i = 0; i < layout.size(); ) { if ((i == layout.size() - 1) @@ -377,7 +355,7 @@ qreal PolarChartAxisAngular::preferredAxisRadius(const QSizeF &maxSize) continue; } - QRectF boundingRect = labelBoundingRect(fm, labelList.at(i)); + QRectF boundingRect = textBoundingRect(axis()->labelsFont(), labelList.at(i), axis()->labelsAngle()); QPointF labelPoint = QLineF::fromPolar(radius + tickWidth(), 90.0 - labelCoordinate).p2(); boundingRect = moveLabelToPosition(labelCoordinate, labelPoint, boundingRect); @@ -392,12 +370,9 @@ qreal PolarChartAxisAngular::preferredAxisRadius(const QSizeF &maxSize) } if (!axis()->titleText().isEmpty() && axis()->isTitleVisible()) { - QGraphicsSimpleTextItem dummyTitle; - dummyTitle.setFont(axis()->titleFont()); - dummyTitle.setText(axis()->titleText()); - QRectF dummyRect = dummyTitle.boundingRect(); + QRectF titleRect = textBoundingRect(axis()->titleFont(), axis()->titleText()); - radius -= titlePadding() + (dummyRect.height() / 2.0); + radius -= titlePadding() + (titleRect.height() / 2.0); if (radius < 1.0) // safeguard return 1.0; } diff --git a/src/axis/polarchartaxisradial.cpp b/src/axis/polarchartaxisradial.cpp index c82c588..8b818af 100644 --- a/src/axis/polarchartaxisradial.cpp +++ b/src/axis/polarchartaxisradial.cpp @@ -23,7 +23,6 @@ #include "abstractchartlayout_p.h" #include "qabstractaxis_p.h" #include "linearrowitem_p.h" -#include QTCOMMERCIALCHART_BEGIN_NAMESPACE @@ -56,7 +55,6 @@ void PolarChartAxisRadial::updateGeometry() QGraphicsLineItem *axisLine = static_cast(arrowItemList.at(0)); axisLine->setLine(line); - QFontMetrics fn(axis()->labelsFont()); QRectF previousLabelRect; bool firstShade = true; bool nextTickVisible = false; @@ -112,7 +110,7 @@ void PolarChartAxisRadial::updateGeometry() QRectF labelRect = labelItem->boundingRect(); QPointF labelCenter = labelRect.center(); labelItem->setTransformOriginPoint(labelCenter.x(), labelCenter.y()); - QRectF boundingRect = labelBoundingRect(fn, labelList.at(i)); + QRectF boundingRect = textBoundingRect(axis()->labelsFont(), labelList.at(i), axis()->labelsAngle()); boundingRect.moveCenter(labelCenter); QPointF positionDiff(labelRect.topLeft() - boundingRect.topLeft()); QPointF labelPoint = center; @@ -205,25 +203,9 @@ void PolarChartAxisRadial::updateGeometry() // Title, along the 0 axis QString titleText = axis()->titleText(); if (!titleText.isEmpty() && axis()->isTitleVisible()) { - QGraphicsSimpleTextItem dummyTitle; - dummyTitle.setFont(axis()->titleFont()); - dummyTitle.setText(titleText); - QRectF dummyRect = dummyTitle.boundingRect(); - - if (dummyRect.width() > radius) { - QString string = titleText + "..."; - while (dummyRect.width() > radius && string.length() > 3) { - string.remove(string.length() - 4, 1); - dummyTitle.setText(string); - dummyRect = dummyTitle.boundingRect(); - } - title->setText(string); - } else { - title->setText(titleText); - } + title->setText(truncatedText(axis()->titleFont(), titleText, 0.0, radius, Qt::Horizontal, QRectF())); - QRectF titleBoundingRect; - titleBoundingRect = title->boundingRect(); + QRectF titleBoundingRect = title->boundingRect(); QPointF titleCenter = titleBoundingRect.center(); QPointF arrowCenter = axisLine->boundingRect().center(); QPointF titleCenterDiff = arrowCenter - titleCenter; diff --git a/src/axis/valueaxis/chartvalueaxisx.cpp b/src/axis/valueaxis/chartvalueaxisx.cpp index da6055f..167adf7 100644 --- a/src/axis/valueaxis/chartvalueaxisx.cpp +++ b/src/axis/valueaxis/chartvalueaxisx.cpp @@ -24,7 +24,6 @@ #include "qvalueaxis.h" #include "abstractchartlayout_p.h" #include -#include #include #include @@ -86,7 +85,6 @@ QSizeF ChartValueAxisX::sizeHint(Qt::SizeHint which, const QSizeF &constraint) c { Q_UNUSED(constraint) - QFontMetrics fn(axis()->labelsFont()); QSizeF sh; QSizeF base = HorizontalAxis::sizeHint(which, constraint); @@ -98,26 +96,24 @@ QSizeF ChartValueAxisX::sizeHint(Qt::SizeHint which, const QSizeF &constraint) c switch (which) { case Qt::MinimumSize: { - QRectF boundingRect = labelBoundingRect(fn, "..."); + QRectF boundingRect = textBoundingRect(axis()->labelsFont(), "...", axis()->labelsAngle()); width = boundingRect.width() / 2.0; - height = boundingRect.height() + labelPadding(); - height += base.height(); + height = boundingRect.height() + labelPadding() + base.height() + 1.0; sh = QSizeF(width, height); break; } case Qt::PreferredSize: { - int labelHeight = 0; - int firstWidth = -1; + qreal labelHeight = 0.0; + qreal firstWidth = -1.0; foreach (const QString& s, ticksList) { - QRect rect = labelBoundingRect(fn, s); + QRectF rect = textBoundingRect(axis()->labelsFont(), s, axis()->labelsAngle()); labelHeight = qMax(rect.height(), labelHeight); width = rect.width(); - if (firstWidth < 0) + if (firstWidth < 0.0) firstWidth = width; } - height = labelHeight + labelPadding(); - height += base.height(); - width = qMax(width, qreal(firstWidth)) / 2.0; + height = labelHeight + labelPadding() + base.height() + 1.0; + width = qMax(width, firstWidth) / 2.0; sh = QSizeF(width, height); break; } diff --git a/src/axis/valueaxis/chartvalueaxisy.cpp b/src/axis/valueaxis/chartvalueaxisy.cpp index 54b5824..8d82b78 100644 --- a/src/axis/valueaxis/chartvalueaxisy.cpp +++ b/src/axis/valueaxis/chartvalueaxisy.cpp @@ -24,7 +24,6 @@ #include "qvalueaxis.h" #include "abstractchartlayout_p.h" #include -#include #include #include @@ -87,7 +86,6 @@ QSizeF ChartValueAxisY::sizeHint(Qt::SizeHint which, const QSizeF &constraint) c { Q_UNUSED(constraint) - QFontMetrics fn(axis()->labelsFont()); QSizeF sh; QSizeF base = VerticalAxis::sizeHint(which, constraint); QStringList ticksList = createValueLabels(min(),max(),m_axis->tickCount(),m_axis->labelFormat()); @@ -98,26 +96,24 @@ QSizeF ChartValueAxisY::sizeHint(Qt::SizeHint which, const QSizeF &constraint) c switch (which) { case Qt::MinimumSize: { - QRectF boundingRect = labelBoundingRect(fn, "..."); - width = boundingRect.width() + labelPadding(); - width += base.width(); + QRectF boundingRect = textBoundingRect(axis()->labelsFont(), "...", axis()->labelsAngle()); + width = boundingRect.width() + labelPadding() + base.width() + 1.0; height = boundingRect.height() / 2.0; sh = QSizeF(width, height); break; } case Qt::PreferredSize: { - int labelWidth = 0; - int firstHeight = -1; + qreal labelWidth = 0.0; + qreal firstHeight = -1.0; foreach (const QString& s, ticksList) { - QRect rect = labelBoundingRect(fn, s); + QRectF rect = textBoundingRect(axis()->labelsFont(), s, axis()->labelsAngle()); labelWidth = qMax(rect.width(), labelWidth); height = rect.height(); - if (firstHeight < 0) + if (firstHeight < 0.0) firstHeight = height; } - width = labelWidth + labelPadding() + 2; //two pixels of tolerance - width += base.width(); - height = qMax(height, qreal(firstHeight)) / 2.0; + width = labelWidth + labelPadding() + base.width() + 2.0; //two pixels of tolerance + height = qMax(height, firstHeight) / 2.0; sh = QSizeF(width, height); break; } diff --git a/src/axis/verticalaxis.cpp b/src/axis/verticalaxis.cpp index 532fb93..dcff8a0 100644 --- a/src/axis/verticalaxis.cpp +++ b/src/axis/verticalaxis.cpp @@ -20,7 +20,6 @@ #include "verticalaxis_p.h" #include "qabstractaxis.h" -#include #include QTCOMMERCIALCHART_BEGIN_NAMESPACE @@ -67,32 +66,12 @@ void VerticalAxis::updateGeometry() else if (axis()->alignment() == Qt::AlignRight) arrowItem->setLine(axisRect.left(), gridRect.top(), axisRect.left(), gridRect.bottom()); - QFontMetrics fn(axis()->labelsFont()); - //title int titlePad = 0; QRectF titleBoundingRect; QString titleText = axis()->titleText(); if (!titleText.isEmpty() && titleItem()->isVisible()) { - int size(0); - size = gridRect.height(); - - QGraphicsSimpleTextItem dummyTitle; - dummyTitle.setFont(axis()->titleFont()); - dummyTitle.setText(axis()->titleText()); - QRectF dummyRect = dummyTitle.boundingRect(); - - if (dummyRect.width() > size) { - QString string = titleText + "..."; - while (dummyRect.width() > size && string.length() > 3) { - string.remove(string.length() - 4, 1); - dummyTitle.setText(string); - dummyRect = dummyTitle.boundingRect(); - } - title->setText(string); - } else { - title->setText(titleText); - } + title->setText(truncatedText(axis()->titleFont(), titleText, 0.0, gridRect.height(), Qt::Horizontal, QRectF())); titlePad = titlePadding(); titleBoundingRect = title->boundingRect(); @@ -119,23 +98,13 @@ void VerticalAxis::updateGeometry() //label text wrapping QString text = labelList.at(i); - QRectF boundingRect = labelBoundingRect(fn, text); - + QRectF boundingRect; qreal size = axisRect.right() - axisRect.left() - labelPadding() - titleBoundingRect.height() - (titlePad * 2); - if (boundingRect.width() > size) { - QString label = text + "..."; - while (boundingRect.width() > size && label.length() > 3) { - label.remove(label.length() - 4, 1); - boundingRect = labelBoundingRect(fn, label); - } - labelItem->setText(label); - } else { - labelItem->setText(text); - } + labelItem->setText(truncatedText(axis()->labelsFont(), text, axis()->labelsAngle(), + size, Qt::Horizontal, boundingRect)); //label transformation origin point const QRectF &rect = labelItem->boundingRect(); - QPointF center = rect.center(); labelItem->setTransformOriginPoint(center.x(), center.y()); int widthDiff = rect.width() - boundingRect.width(); @@ -221,16 +190,13 @@ QSizeF VerticalAxis::sizeHint(Qt::SizeHint which, const QSizeF &constraint) cons switch (which) { case Qt::MinimumSize: { - QFontMetrics fn(axis()->titleFont()); - sh = QSizeF(fn.height() + (titlePadding() * 2), fn.boundingRect("...").width()); + QRectF titleRect = textBoundingRect(axis()->titleFont(), "..."); + sh = QSizeF(titleRect.height() + (titlePadding() * 2), titleRect.width()); break; } case Qt::MaximumSize: case Qt::PreferredSize: { - QGraphicsSimpleTextItem dummyTitle; - dummyTitle.setFont(axis()->titleFont()); - dummyTitle.setText(axis()->titleText()); - QRectF titleRect = dummyTitle.boundingRect(); + QRectF titleRect = textBoundingRect(axis()->titleFont(), axis()->titleText()); sh = QSizeF(titleRect.height() + (titlePadding() * 2), titleRect.width()); break; } diff --git a/src/layout/polarchartlayout.cpp b/src/layout/polarchartlayout.cpp index 905f43c..127560a 100644 --- a/src/layout/polarchartlayout.cpp +++ b/src/layout/polarchartlayout.cpp @@ -22,7 +22,6 @@ #include "chartpresenter_p.h" #include "polarchartaxis_p.h" #include -#include QTCOMMERCIALCHART_BEGIN_NAMESPACE @@ -58,10 +57,7 @@ QRectF PolarChartLayout::calculateAxisGeometry(const QRectF &geometry, const QLi && chartAxis->axis()->isTitleVisible() && !chartAxis->axis()->titleText().isEmpty()) { // If axis has angular title, adjust geometry down by the space title takes - QGraphicsSimpleTextItem dummyTitle; - dummyTitle.setFont(chartAxis->axis()->titleFont()); - dummyTitle.setText(chartAxis->axis()->titleText()); - QRectF dummyRect = dummyTitle.boundingRect(); + QRectF dummyRect = chartAxis->textBoundingRect(chartAxis->axis()->titleFont(), chartAxis->axis()->titleText()); titleHeight = (dummyRect.height() / 2.0) + chartAxis->titlePadding(); } }