2626namespace {
2727 // Constants for time calculations (milliseconds)
2828 constexpr qint64 MS_PER_DAY = 86400000LL ;
29- constexpr qint64 MS_PER_HOUR = 3600000LL ;
3029
3130 // Cache for date components to avoid repeated QDateTime creation
3231 struct DateComponents {
@@ -61,8 +60,8 @@ namespace {
6160 return {year, month, day};
6261 }
6362
64- // Fast check if day matches specific day of month
65- inline bool isDayOfMonth (qint64 timestampMs, int targetDay ) {
63+ // Fast check if a timestamp is the first day of a month
64+ inline bool isFirstOfMonth (qint64 timestampMs) {
6665 qint64 days = timestampMs / MS_PER_DAY;
6766 qint64 z = days + 719468 ;
6867 qint64 era = (z >= 0 ? z : z - 146096 ) / 146097 ;
@@ -71,12 +70,15 @@ namespace {
7170 qint64 doy = doe - (365 *yoe + yoe/4 - yoe/100 );
7271 qint64 mp = (5 *doy + 2 )/153 ;
7372 int day = static_cast <int >(doy - (153 *mp+2 )/5 + 1 );
74- return day == targetDay ;
73+ return day == 1 ;
7574 }
7675
7776 // Cache QTimeZone::utc() result
78- static const QTimeZone& utcZone () {
79- static const QTimeZone tz = QTimeZone::UTC;
77+ const QTimeZone& utcZone () {
78+ // Construct from the "UTC" ID which works across Qt versions and
79+ // platforms (avoids referencing QTimeZone::UTC or QTimeZone::utc()
80+ // directly, which differ between builds).
81+ static const QTimeZone tz = QTimeZone (QByteArrayLiteral (" UTC" ));
8082 return tz;
8183 }
8284
@@ -87,6 +89,35 @@ namespace {
8789 dt.setTimeZone (utcZone ());
8890 return dt.toString (format);
8991 }
92+
93+ // Format Y-axis label (translation-unit helper)
94+ static QString formatYAxisLabel (double value, double minValue, double maxValue, int availableWidth,
95+ const QFont &font) {
96+ double range = maxValue - minValue;
97+
98+ if (std::abs (value) >= 1000000 ) {
99+ return QString::number (value / 1000000.0 , ' f' , 1 ) + " M" ;
100+ } else if (std::abs (value) >= 1000 ) {
101+ return QString::number (value / 1000.0 , ' f' , 1 ) + " K" ;
102+ }
103+
104+ int precision = 2 ;
105+ if (range < 1.0 ) precision = 4 ;
106+ else if (range < 10.0 ) precision = 3 ;
107+
108+ QString label = QString::number (value, ' f' , precision);
109+
110+ QFontMetrics fm (font);
111+ int textWidth = fm.horizontalAdvance (label);
112+
113+ while (textWidth > availableWidth && precision > 0 ) {
114+ precision--;
115+ label = QString::number (value, ' f' , precision);
116+ textWidth = fm.horizontalAdvance (label);
117+ }
118+
119+ return label;
120+ }
90121}
91122
92123namespace QTradingView {
@@ -170,7 +201,6 @@ void AxisRenderer::drawYAxis(QPainter* painter, const QRectF& leftAxisRect,
170201 painter->fillRect (leftAxisRect, m_backgroundColor);
171202 painter->fillRect (rightAxisRect, m_backgroundColor);
172203
173- QRectF paneRect = pane->rect ();
174204 double minValue = pane->minValue ();
175205 double maxValue = pane->maxValue ();
176206
@@ -227,7 +257,7 @@ void AxisRenderer::drawYAxis(QPainter* painter, const QRectF& leftAxisRect,
227257}
228258
229259// TODO: We assume dataProvider provides daily data. Adjust logic for different timeframes if needed.
230- std::vector<TimeLabel> AxisRenderer::calculateXAxisLabels (const ViewPort& viewport, const Series* series) const {
260+ std::vector<TimeLabel> AxisRenderer::calculateXAxisLabels (const ViewPort& viewport, const Series* series) {
231261 std::vector<TimeLabel> labels;
232262 if (!series || series->dataCount () == 0 ) {
233263 return labels; // No data, no labels
@@ -279,7 +309,7 @@ std::vector<TimeLabel> AxisRenderer::calculateXAxisLabels(const ViewPort& viewpo
279309 }
280310 } else if (visibleCount <= 90 ) {
281311 // Show month starts
282- if (isDayOfMonth (timestamp, 1 )) {
312+ if (isFirstOfMonth (timestamp)) {
283313 label = formatDate (timestamp, " MMM" );
284314 shouldLabel = true ;
285315 }
@@ -321,31 +351,4 @@ std::vector<TimeLabel> AxisRenderer::calculateXAxisLabels(const ViewPort& viewpo
321351 return labels;
322352}
323353
324- QString AxisRenderer::formatYAxisLabel (double value, double minValue, double maxValue, int availableWidth,
325- const QFont &font) const {
326- double range = maxValue - minValue;
327-
328- if (std::abs (value) >= 1000000 ) {
329- return QString::number (value / 1000000.0 , ' f' , 1 ) + " M" ;
330- } else if (std::abs (value) >= 1000 ) {
331- return QString::number (value / 1000.0 , ' f' , 1 ) + " K" ;
332- }
333-
334- int precision = 2 ;
335- if (range < 1.0 ) precision = 4 ;
336- else if (range < 10.0 ) precision = 3 ;
337-
338- QString label = QString::number (value, ' f' , precision);
339-
340- QFontMetrics fm (font);
341- int textWidth = fm.horizontalAdvance (label);
342-
343- while (textWidth > availableWidth && precision > 0 ) {
344- precision--;
345- label = QString::number (value, ' f' , precision);
346- textWidth = fm.horizontalAdvance (label);
347- }
348-
349- return label;
350- }
351354} // namespace QTradingView
0 commit comments