Add readonly visual min and max properties to QValueAxis and QDateTimeAxis

Task-number: QTBUG-142046
Change-Id: I25ab89809d28f3efa27bc83a7a455d3ab2a82a90
Reviewed-by: Sami Varanka <sami.varanka@qt.io>
Reviewed-by: Tomi Korpipää <tomi.korpipaa@qt.io>
This commit is contained in:
Niko Korkala 2025-11-26 16:23:19 +02:00
parent 8e44b5cc66
commit 12e2be4741
8 changed files with 201 additions and 66 deletions

View File

@ -332,6 +332,7 @@ void QDateTimeAxis::setZoom(qreal zoom)
}
d->m_zoom = zoom;
d->calculateVisualRange();
emit zoomChanged(zoom);
emit update();
}
@ -352,6 +353,7 @@ void QDateTimeAxis::setPan(qreal pan)
}
d->m_pan = pan;
d->calculateVisualRange();
emit panChanged(pan);
emit update();
}
@ -362,6 +364,18 @@ qreal QDateTimeAxis::pan() const
return d->m_pan;
}
QDateTime QDateTimeAxis::visualMin() const
{
Q_D(const QDateTimeAxis);
return QDateTime::fromMSecsSinceEpoch(d->m_visualMin, d->m_timeZone);
}
QDateTime QDateTimeAxis::visualMax() const
{
Q_D(const QDateTimeAxis);
return QDateTime::fromMSecsSinceEpoch(d->m_visualMax, d->m_timeZone);
}
///////////////////////////////////////////////////////////////////////////////
QDateTimeAxisPrivate::QDateTimeAxisPrivate() {}
@ -407,8 +421,30 @@ void QDateTimeAxisPrivate::setRange(qreal min, qreal max)
emit q->maxChanged(QDateTime::fromMSecsSinceEpoch(max, QTimeZone::UTC));
}
if (changed)
if (changed) {
calculateVisualRange();
emit q->rangeChanged(min, max);
}
}
void QDateTimeAxisPrivate::calculateVisualRange()
{
Q_Q(QDateTimeAxis);
qreal diff = m_max - m_min;
qreal center = diff / 2.0f + m_min + m_pan;
diff /= m_zoom;
qreal max = center + diff / 2.0f;
qreal min = center - diff / 2.0f;
if (!qFuzzyCompare(m_visualMin, min)) {
m_visualMin = min;
emit q->visualMinChanged(min);
}
if (!qFuzzyCompare(m_visualMax, max)) {
m_visualMax = max;
emit q->visualMaxChanged(max);
}
}
QT_END_NAMESPACE

View File

@ -25,6 +25,8 @@ class Q_GRAPHS_EXPORT QDateTimeAxis : public QAbstractAxis
QString timeZone READ timeZone WRITE setTimeZone NOTIFY timeZoneChanged REVISION(6, 11))
Q_PROPERTY(qreal zoom READ zoom WRITE setZoom NOTIFY zoomChanged REVISION(6, 11))
Q_PROPERTY(qreal pan READ pan WRITE setPan NOTIFY panChanged REVISION(6, 11))
Q_PROPERTY(QDateTime visualMin READ visualMin NOTIFY visualMinChanged REVISION(6, 11))
Q_PROPERTY(QDateTime visualMax READ visualMax NOTIFY visualMaxChanged REVISION(6, 11))
QML_NAMED_ELEMENT(DateTimeAxis)
@ -62,6 +64,9 @@ public:
qreal pan() const;
void setPan(qreal pan);
QDateTime visualMin() const;
QDateTime visualMax() const;
Q_SIGNALS:
void minChanged(const QDateTime &min);
void maxChanged(const QDateTime &max);
@ -71,6 +76,8 @@ Q_SIGNALS:
Q_REVISION(6, 11) void timeZoneChanged(const QString &timeZone);
Q_REVISION(6, 11) void zoomChanged(qreal zoom);
Q_REVISION(6, 11) void panChanged(qreal pan);
Q_REVISION(6, 11) void visualMinChanged(qreal min);
Q_REVISION(6, 11) void visualMaxChanged(qreal max);
private:
Q_DECLARE_PRIVATE(QDateTimeAxis)

View File

@ -33,6 +33,8 @@ protected:
QString m_format = QStringLiteral("dd-MMMM-yy");
qreal m_zoom = 1.0;
qreal m_pan = 0.0;
qreal m_visualMin;
qreal m_visualMax;
public:
void setMin(const QVariant &min) override;
@ -41,6 +43,7 @@ public:
void setRange(qreal min, qreal max) override;
qreal min() override { return m_min; }
qreal max() override { return m_max; }
void calculateVisualRange();
private:
Q_DECLARE_PUBLIC(QDateTimeAxis)

View File

@ -366,6 +366,7 @@ void QValueAxis::setZoom(qreal zoom)
Q_D(QValueAxis);
if (d->m_zoom != zoom) {
d->m_zoom = zoom;
d->calculateVisualRange();
emit update();
emit zoomChanged(zoom);
} else {
@ -385,6 +386,7 @@ void QValueAxis::setPan(qreal pan)
Q_D(QValueAxis);
if (d->m_pan != pan) {
d->m_pan = pan;
d->calculateVisualRange();
emit update();
emit panChanged(pan);
} else {
@ -399,6 +401,18 @@ qreal QValueAxis::pan() const
return d->m_pan;
}
qreal QValueAxis::visualMin() const
{
Q_D(const QValueAxis);
return d->m_visualMin;
}
qreal QValueAxis::visualMax() const
{
Q_D(const QValueAxis);
return d->m_visualMax;
}
/*!
Returns the type of the axis.
*/
@ -477,9 +491,29 @@ void QValueAxisPrivate::setRange(qreal min, qreal max)
emit q->maxChanged(max);
}
if (changed)
if (changed) {
calculateVisualRange();
emit q->rangeChanged(min, max);
}
}
void QValueAxisPrivate::calculateVisualRange()
{
Q_Q(QValueAxis);
qreal diff = m_max - m_min;
qreal center = diff / 2.0f + m_min + m_pan;
diff /= m_zoom;
qreal min = center - diff / 2.0f;
qreal max = center + diff / 2.0f;
if (!qFuzzyCompare(m_visualMin, min)) {
m_visualMin = min;
emit q->visualMinChanged(min);
}
if (!qFuzzyCompare(m_visualMax, max)) {
m_visualMax = max;
emit q->visualMaxChanged(max);
}
}
QT_END_NAMESPACE

View File

@ -28,6 +28,8 @@ class Q_GRAPHS_EXPORT QValueAxis : public QAbstractAxis
qreal tickInterval READ tickInterval WRITE setTickInterval NOTIFY tickIntervalChanged FINAL)
Q_PROPERTY(qreal zoom READ zoom WRITE setZoom NOTIFY zoomChanged REVISION(6, 9))
Q_PROPERTY(qreal pan READ pan WRITE setPan NOTIFY panChanged REVISION(6, 9))
Q_PROPERTY(qreal visualMin READ visualMin NOTIFY visualMinChanged REVISION(6, 11))
Q_PROPERTY(qreal visualMax READ visualMax NOTIFY visualMaxChanged REVISION(6, 11))
QML_NAMED_ELEMENT(ValueAxis)
public:
@ -67,6 +69,9 @@ public:
void setPan(qreal pan);
qreal pan() const;
qreal visualMin() const;
qreal visualMax() const;
Q_SIGNALS:
void minChanged(qreal min);
void maxChanged(qreal max);
@ -78,6 +83,8 @@ Q_SIGNALS:
void tickIntervalChanged(qreal tickInterval);
Q_REVISION(6, 9) void zoomChanged(qreal zoom);
Q_REVISION(6, 9) void panChanged(qreal pan);
Q_REVISION(6, 11) void visualMinChanged(qreal visualMin);
Q_REVISION(6, 11) void visualMaxChanged(qreal visualMax);
private:
Q_DECLARE_PRIVATE(QValueAxis)

View File

@ -28,6 +28,7 @@ public:
qreal min() override { return m_min; }
qreal max() override { return m_max; }
void setRange(qreal min,qreal max) override;
void calculateVisualRange();
protected:
void setMin(const QVariant &min) override;
@ -44,6 +45,8 @@ private:
qreal m_tickInterval;
qreal m_zoom = 1.0;
qreal m_pan = 0.0;
qreal m_visualMin = m_min;
qreal m_visualMax = m_max;
Q_DECLARE_PUBLIC(QValueAxis)
};

View File

@ -12,51 +12,50 @@ Rectangle {
width: 800
height: 600
color: "#202020"
RowLayout {
id:bar
ColumnLayout {
id: infoLayout
anchors {
left: parent.left
right: parent.right
leftMargin: 25
}
height: 100
spacing: 0
RowLayout {
Layout.fillHeight: true
Layout.fillWidth: true
Text {
Layout.leftMargin: 20
font.pixelSize: 24
color: "#ffffff"
text: "X:"
}
Slider {
id: sliderX
value: (new Date(1950,1,1)).getTime()
from: (new Date(1900,1,1)).getTime()
to: (new Date(2000,1,1)).getTime()
}
Text {
font.pixelSize: 24
color: "#ffffff"
text: "Y:"
}
Slider {
id: sliderY
value: (new Date(1950,1,1)).getTime()
from: (new Date(1900,1,1)).getTime()
to: (new Date(2000,1,1)).getTime()
}
Text {
Layout.leftMargin: 20
font.pixelSize: 24
color: "#ffffff"
text: "X Ticks:"
}
SpinBox {
onValueChanged: xAxis.tickInterval = value
}
Text {
Layout.leftMargin: 20
font.pixelSize: 24
@ -67,7 +66,6 @@ Rectangle {
placeholderText: "MMMM-yyyy"
onAccepted: xAxis.labelFormat = text
}
CheckBox {
id: zoomAreaEnabled
text: "Zoom area enabled"
@ -80,12 +78,43 @@ Rectangle {
}
}
}
RowLayout {
Layout.fillHeight: true
spacing: 50
Column {
Label {
id: visualXMin
text: "X Axis visualMin: " + xAxis.visualMin
color: "white"
}
Label {
id: visualXMax
text: "X Axis visualMax: " + xAxis.visualMax
color: "white"
}
}
Column {
Label {
id: visualYMin
text: "Y Axis visualMin: " + yAxis.visualMin
color: "white"
}
Label {
id: visualYMax
text: "Y Axis visualMax: " + yAxis.visualMax
color: "white"
}
}
}
}
GraphsView {
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.top: bar.bottom
anchors.top: infoLayout.bottom
anchors.margins: 10
zoomStyle: GraphsView.ZoomStyle.Center;
panStyle: zoomAreaEnabled.checked ? GraphsView.PanStyle.None : GraphsView.PanStyle.Drag

View File

@ -152,6 +152,22 @@ Rectangle {
toValue: 40
onSliderValueChanged: yAxis.max = sliderValue;
}
CustomLabel {
id: visualRangeMinXLabel
text: qsTr("X Axis visualMin: %1").arg(Number(xAxis.visualMin).toLocaleString())
}
CustomLabel {
id: visualRangeMaxXLabel
text: qsTr("X Axis visualMax: %1").arg(Number(xAxis.visualMax).toLocaleString())
}
CustomLabel {
id: visualRangeMinYLabel
text: qsTr("Y Axis visualMin: %1").arg(Number(yAxis.visualMin).toLocaleString())
}
CustomLabel {
id: visualRangeMaxYLabel
text: qsTr("Y Axis visualMax: %1").arg(Number(yAxis.visualMax).toLocaleString())
}
}
GraphsView {