Graphs 2D: Add api for horizontal text elide

Axis labels on 2D graphs now support horizontal text elide.

Task-number: QTBUG-120502
Task-number: QTBUG-135930
Change-Id: Id89e59bfb9791e8512124432f0d6235880c6b2fe
Reviewed-by: Sami Varanka <sami.varanka@qt.io>
Reviewed-by: Alexei Cazacov <alexei.cazacov@qt.io>
This commit is contained in:
Sami Varanka 2025-05-09 14:52:55 +03:00
parent 0f4f9f4a66
commit 3ab339061b
7 changed files with 117 additions and 17 deletions

View File

@ -162,6 +162,7 @@ QT_BEGIN_NAMESPACE
The font of the title of the axis.
*/
/*!
\property QAbstractAxis::alignment
\since 6.9
@ -177,6 +178,22 @@ QT_BEGIN_NAMESPACE
\l{Qt::AlignTop}{Qt.AlignTop}.
*/
/*!
\property QAbstractAxis::textElide
\since 6.10
\brief The textElide of the axis labels.
Can be Qt::ElideLeft, Qt::ElideRight, Qt::ElideMiddle, or Qt::ElideNone.
By default, the value is \c Qt::ElideNone.
*/
/*!
\qmlproperty enumeration AbstractAxis::textElide
\since 6.10
The textElide of the axis labels. Can be \l{Qt::ElideLeft}{Qt.ElideLeft},
\l{Qt::ElideRight}{Qt.ElideRight}, \l{Qt::ElideMiddle}{Qt.ElideMiddle}, or
\l{Qt::ElideNone}{Qt.ElideNone}. By default, the value is \c Qt.ElideNone.
*/
/*!
\fn void QAbstractAxis::update()
This signal is emitted when the axis needs to be updated.
@ -239,6 +256,12 @@ QT_BEGIN_NAMESPACE
the min and max of the new range.
*/
/*!
\qmlsignal AbstractAxis::textElideChanged(enumeration elide)
This signal is emitted when the \l textElide changes. \a elide is the
new value of the \l Qt::TextElideMode type.
*/
/*!
\internal
Constructs a new axis object that is a child of \a parent. The ownership is taken by
@ -571,6 +594,25 @@ void QAbstractAxis::setAlignment(Qt::Alignment alignment)
}
}
Qt::TextElideMode QAbstractAxis::textElide() const
{
Q_D(const QAbstractAxis);
return d->m_textElide;
}
void QAbstractAxis::setTextElide(Qt::TextElideMode elide)
{
Q_D(QAbstractAxis);
if (d->m_textElide == elide) {
qCDebug(lcAxis2D) << "QAbstractAxis::setTextElide. Text elide is already set to:"
<< elide;
return;
}
d->m_textElide = elide;
Q_EMIT textElideChanged(d->m_textElide);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
QAbstractAxisPrivate::QAbstractAxisPrivate() {}

View File

@ -15,7 +15,6 @@
QT_BEGIN_NAMESPACE
Q_DECLARE_LOGGING_CATEGORY(lcAxis2D)
class QAbstractAxisPrivate;
@ -48,7 +47,10 @@ class Q_GRAPHS_EXPORT QAbstractAxis : public QObject
Q_PROPERTY(QFont titleFont READ titleFont WRITE setTitleFont NOTIFY titleFontChanged FINAL)
//alignment
Q_PROPERTY(Qt::Alignment alignment READ alignment WRITE setAlignment NOTIFY
alignmentChanged REVISION(6, 9))
alignmentChanged REVISION(6, 9))
Q_PROPERTY(Qt::TextElideMode textElide READ textElide WRITE setTextElide NOTIFY textElideChanged
REVISION(6, 10))
QML_FOREIGN(QAbstractAxis)
QML_UNCREATABLE("")
QML_NAMED_ELEMENT(AbstractAxis)
@ -107,6 +109,9 @@ public:
Qt::Alignment alignment() const;
void setAlignment(Qt::Alignment alignment);
Qt::TextElideMode textElide() const;
void setTextElide(Qt::TextElideMode elide);
//range handling
void setMin(const QVariant &min);
void setMax(const QVariant &max);
@ -125,6 +130,7 @@ Q_SIGNALS:
void titleVisibleChanged(bool visible);
void titleFontChanged(const QFont &font);
Q_REVISION(6, 9) void alignmentChanged(Qt::Alignment alignment);
Q_REVISION(6, 10) void textElideChanged(Qt::TextElideMode elide);
void update();
void rangeChanged(qreal min, qreal max);

View File

@ -68,6 +68,7 @@ private:
QString m_title;
Qt::Alignment m_alignment = Qt::AlignAbsolute;
Qt::TextElideMode m_textElide = Qt::ElideNone;
Q_DECLARE_PUBLIC(QAbstractAxis)
};

View File

@ -1145,7 +1145,8 @@ void AxisRenderer::updateAxisLabelItems(QList<QQuickItem *> &textItems,
}
void AxisRenderer::setLabelTextProperties(QQuickItem *item, const QString &text, bool xAxis,
QQuickText::HAlignment hAlign, QQuickText::VAlignment vAlign)
QQuickText::HAlignment hAlign, QQuickText::VAlignment vAlign,
Qt::TextElideMode elide)
{
if (auto textItem = qobject_cast<QQuickText *>(item)) {
// If the component is a Text item (default), then text
@ -1161,6 +1162,23 @@ void AxisRenderer::setLabelTextProperties(QQuickItem *item, const QString &text,
textItem->setFont(theme()->axisYLabelFont());
textItem->setColor(theme()->axisY().labelTextColor());
}
QQuickText::TextElideMode e;
switch (elide) {
case Qt::ElideLeft:
e = QQuickText::ElideLeft;
break;
case Qt::ElideRight:
e = QQuickText::ElideRight;
break;
case Qt::ElideMiddle:
e = QQuickText::ElideMiddle;
break;
default:
e = QQuickText::ElideNone;
}
textItem->setElideMode(e);
} else {
// Check for specific dynamic properties
if (item->property("text").isValid())
@ -1192,11 +1210,13 @@ void AxisRenderer::updateBarXAxisLabels(AxisProperties &ax, const QRectF rect)
if (ax.axis->alignment() == Qt::AlignTop || ax.axis->alignment() == Qt::AlignLeft) {
setLabelTextProperties(textItem, category, true,
QQuickText::HAlignment::AlignHCenter,
QQuickText::VAlignment::AlignBottom);
QQuickText::VAlignment::AlignBottom,
axis->textElide());
} else {
setLabelTextProperties(textItem, category, true,
QQuickText::HAlignment::AlignHCenter,
QQuickText::VAlignment::AlignTop);
QQuickText::VAlignment::AlignTop,
axis->textElide());
}
textItem->setHeight(rect.height());
textItem->setVisible(true);
@ -1231,11 +1251,13 @@ void AxisRenderer::updateBarYAxisLabels(AxisProperties &ax, const QRectF rect)
if (ax.axis->alignment() == Qt::AlignRight || ax.axis->alignment() == Qt::AlignBottom) {
setLabelTextProperties(textItem, category, false,
QQuickText::HAlignment::AlignLeft,
QQuickText::VAlignment::AlignVCenter);
QQuickText::VAlignment::AlignVCenter,
axis->textElide());
} else {
setLabelTextProperties(textItem, category, false,
QQuickText::HAlignment::AlignRight,
QQuickText::VAlignment::AlignVCenter);
QQuickText::VAlignment::AlignVCenter,
axis->textElide());
}
textItem->setHeight(rect.height() / categoriesCount);
textItem->setVisible(true);
@ -1300,11 +1322,13 @@ void AxisRenderer::updateValueYAxisLabels(AxisProperties &ax, const QRectF rect)
if (ax.axis->alignment() == Qt::AlignRight || ax.axis->alignment() == Qt::AlignBottom) {
setLabelTextProperties(textItem, label, false,
QQuickText::HAlignment::AlignLeft,
QQuickText::VAlignment::AlignVCenter);
QQuickText::VAlignment::AlignVCenter,
axis->textElide());
} else {
setLabelTextProperties(textItem, label, false,
QQuickText::HAlignment::AlignRight,
QQuickText::VAlignment::AlignVCenter);
QQuickText::VAlignment::AlignVCenter,
axis->textElide());
}
textItem->setHeight(0);
textItem->setVisible(true);
@ -1370,11 +1394,13 @@ void AxisRenderer::updateValueXAxisLabels(AxisProperties &ax, const QRectF rect)
if (ax.axis->alignment() == Qt::AlignTop || ax.axis->alignment() == Qt::AlignLeft) {
setLabelTextProperties(textItem, label, true,
QQuickText::HAlignment::AlignHCenter,
QQuickText::VAlignment::AlignBottom);
QQuickText::VAlignment::AlignBottom,
axis->textElide());
} else {
setLabelTextProperties(textItem, label, true,
QQuickText::HAlignment::AlignHCenter,
QQuickText::VAlignment::AlignTop);
QQuickText::VAlignment::AlignTop,
axis->textElide());
}
textItem->setHeight(rect.height());
textItem->setVisible(true);
@ -1421,11 +1447,13 @@ void AxisRenderer::updateDateTimeYAxisLabels(AxisProperties &ax, const QRectF re
if (ax.axis->alignment() == Qt::AlignRight || ax.axis->alignment() == Qt::AlignBottom) {
setLabelTextProperties(textItem, label, false,
QQuickText::HAlignment::AlignLeft,
QQuickText::VAlignment::AlignVCenter);
QQuickText::VAlignment::AlignVCenter,
axis->textElide());
} else {
setLabelTextProperties(textItem, label, false,
QQuickText::HAlignment::AlignRight,
QQuickText::VAlignment::AlignVCenter);
QQuickText::VAlignment::AlignVCenter,
axis->textElide());
}
textItem->setHeight(0);
textItem->setVisible(true);
@ -1473,11 +1501,13 @@ void AxisRenderer::updateDateTimeXAxisLabels(AxisProperties &ax, const QRectF re
if (ax.axis->alignment() == Qt::AlignTop || ax.axis->alignment() == Qt::AlignLeft) {
setLabelTextProperties(textItem, label, true,
QQuickText::HAlignment::AlignHCenter,
QQuickText::VAlignment::AlignBottom);
QQuickText::VAlignment::AlignBottom,
axis->textElide());
} else {
setLabelTextProperties(textItem, label, true,
QQuickText::HAlignment::AlignHCenter,
QQuickText::VAlignment::AlignTop);
QQuickText::VAlignment::AlignTop,
axis->textElide());
}
textItem->setHeight(rect.height());
textItem->setVisible(true);

View File

@ -110,8 +110,11 @@ private:
int getValueDecimalsFromRange(double range);
void setLabelTextProperties(QQuickItem *item, const QString &text, bool xAxis,
QQuickText::HAlignment hAlign = QQuickText::HAlignment::AlignHCenter,
QQuickText::VAlignment vAlign = QQuickText::VAlignment::AlignVCenter);
void updateAxisLabelItems(QList<QQuickItem *> &textItems, qsizetype neededSize, QQmlComponent *component);
QQuickText::VAlignment vAlign = QQuickText::VAlignment::AlignVCenter,
Qt::TextElideMode elide = Qt::ElideNone);
void updateAxisLabelItems(QList<QQuickItem *> &textItems, qsizetype neededSize,
QQmlComponent *component);
QVector2D windowToAxisCoords(QVector2D coords);
bool zoom(qreal delta);

View File

@ -55,6 +55,7 @@ void tst_abstractaxis::initialProperties()
QCOMPARE(m_axis->isTitleVisible(), true);
QCOMPARE(m_axis->titleFont(), QFont());
QCOMPARE(m_axis->alignment(), Qt::AlignAbsolute);
QCOMPARE(m_axis->textElide(), Qt::ElideNone);
}
void tst_abstractaxis::initializeProperties()
@ -73,6 +74,7 @@ void tst_abstractaxis::initializeProperties()
QSignalSpy spy9(m_axis, &QAbstractAxis::titleVisibleChanged);
QSignalSpy spy10(m_axis, &QAbstractAxis::titleFontChanged);
QSignalSpy spy11(m_axis, &QAbstractAxis::alignmentChanged);
QSignalSpy spy12(m_axis, &QAbstractAxis::textElideChanged);
auto font = QFont("Arial", 20, 2, true);
auto labelDelegate = new QQmlComponent(this);
@ -89,6 +91,7 @@ void tst_abstractaxis::initializeProperties()
m_axis->setTitleVisible(false);
m_axis->setTitleFont(font);
m_axis->setAlignment(Qt::AlignTop);
m_axis->setTextElide(Qt::ElideRight);
QCOMPARE(m_axis->isVisible(), false);
QCOMPARE(m_axis->isLineVisible(), false);
@ -102,6 +105,7 @@ void tst_abstractaxis::initializeProperties()
QCOMPARE(m_axis->isTitleVisible(), false);
QCOMPARE(m_axis->titleFont(), font);
QCOMPARE(m_axis->alignment(), Qt::AlignTop);
QCOMPARE(m_axis->textElide(), Qt::ElideRight);
QCOMPARE(spy0.size(), 1);
QCOMPARE(spy1.size(), 1);
@ -115,6 +119,7 @@ void tst_abstractaxis::initializeProperties()
QCOMPARE(spy9.size(), 1);
QCOMPARE(spy10.size(), 1);
QCOMPARE(spy11.size(), 1);
QCOMPARE(spy12.size(), 1);
}
void tst_abstractaxis::showHide()

View File

@ -37,6 +37,7 @@ Item {
titleText: "Initialized"
titleVisible: false
visible: false
textElide: Qt.ElideLeft
}
TestCase {
@ -64,6 +65,7 @@ Item {
compare(initial.titleText, "")
compare(initial.titleVisible, true)
compare(initial.visible, true)
compare(initial.textElide, Qt.ElideNone)
}
function test_3_initial_change() {
@ -85,6 +87,7 @@ Item {
initial.titleText = "Dummy"
initial.titleVisible = false
initial.visible = false
initial.textElide = Qt.ElideRight
// Properties from BarCategoryAxis
compare(initial.categories, ["one", "two"])
@ -104,6 +107,7 @@ Item {
compare(initial.titleText, "Dummy")
compare(initial.titleVisible, false)
compare(initial.visible, false)
compare(initial.textElide, Qt.ElideRight)
}
function test_4_initial_modify() {
initial.clear()
@ -156,6 +160,7 @@ Item {
compare(initialized.titleText, "Initialized")
compare(initialized.titleVisible, false)
compare(initialized.visible, false)
compare(initialized.textElide, Qt.ElideLeft)
}
function test_2_initialized_change() {
@ -175,6 +180,7 @@ Item {
initialized.titleText = "Dummy"
initialized.titleVisible = true
initialized.visible = true
initialized.textElide = Qt.ElideMiddle
// Properties from BarCategoryAxis
compare(initialized.categories, ["one", "two"])
@ -194,6 +200,7 @@ Item {
compare(initialized.titleText, "Dummy")
compare(initialized.titleVisible, true)
compare(initialized.visible, true)
compare(initialized.textElide, Qt.ElideMiddle)
// Signals
compare(countSpy.count, 1)
@ -213,6 +220,7 @@ Item {
compare(titleColorSpy.count, 1)
compare(titleVisibleSpy.count, 1)
compare(alignmentSpy.count, 0)
compare(textElideSpy.count, 1)
}
function test_3_initialized_clear() {
@ -380,4 +388,9 @@ Item {
target: initialized
signalName: "alignmentChanged"
}
SignalSpy {
id: textElideSpy
target: initialized
signalName: "textElideChanged"
}
}