223 const int W = width();
224 const int H = height();
225 const double spp =
static_cast<double>(m_spp);
227 if (W <= 0 || spp <= 0.0 || m_sfreq <= 0.0)
231 p.setRenderHint(QPainter::Antialiasing,
false);
232 p.setRenderHint(QPainter::TextAntialiasing,
true);
239 p.fillRect(QRect(0, 0, W,
kTimeZoneH), QColor(245, 245, 247));
245 p.setPen(QPen(QColor(190, 190, 205), 1));
249 p.setPen(QPen(QColor(185, 185, 195), 1));
250 p.drawLine(0, H - 1, W, H - 1);
253 if (!m_referenceMarkers.isEmpty()) {
254 QFont markerFont = p.font();
255 markerFont.setPixelSize(9);
256 markerFont.setBold(
true);
257 p.setFont(markerFont);
259 constexpr int kMarkerChipH = 12;
260 constexpr int kMarkerPadX = 5;
261 const int markerChipY = 2;
264 const float xF = (
static_cast<float>(marker.sample) - m_scrollSample) /
static_cast<float>(spp);
265 if (xF < -2.f || xF > W + 2.f) {
269 const int xi =
static_cast<int>(std::round(xF));
270 QColor markerColor = marker.color;
271 markerColor.setAlpha(210);
272 p.setPen(QPen(markerColor, 1));
273 p.drawLine(xi, 0, xi, H - 1);
275 const QString label = marker.label.isEmpty()
276 ? QString::number(marker.sample)
278 const int chipW = qMax(20, p.fontMetrics().horizontalAdvance(label) + 2 * kMarkerPadX);
279 QRect chipRect(xi - chipW / 2, markerChipY, chipW, kMarkerChipH);
280 chipRect.moveLeft(qBound(2, chipRect.left(), qMax(2, W - chipRect.width() - 2)));
282 QColor fillColor = marker.color;
283 fillColor.setAlpha(220);
284 p.fillRect(chipRect, fillColor);
286 p.drawText(chipRect, Qt::AlignCenter, label);
291 if (!m_events.isEmpty()) {
293 evFont.setPixelSize(9);
294 evFont.setBold(
true);
297 constexpr int kChipW = 26;
298 constexpr int kChipH = 11;
305 int lastChipRight = -kChipW;
308 float xF = (
static_cast<float>(ev.sample) - m_scrollSample) /
static_cast<float>(spp);
309 if (xF < -2.f || xF > W + 2.f)
311 int ix =
static_cast<int>(xF);
314 QColor col = ev.color;
316 p.setPen(QPen(col, 1));
322 int chipX = ix - kChipW / 2;
323 chipX = qMax(0, chipX);
324 if (chipX + kChipW > W)
326 if (chipX < lastChipRight + 2)
329 QRectF chip(chipX, kChipY, kChipW, kChipH);
330 QColor fill = ev.color;
332 p.fillRect(chip, fill);
334 QString lbl = ev.label.isEmpty() ? QStringLiteral(
"?") : ev.label;
335 p.drawText(chip, Qt::AlignCenter, lbl);
337 lastChipRight = chipX + kChipW;
342 const double pxPerSec = m_sfreq / spp;
343 double tickIntervalS = kNiceIntervals[0];
344 for (
double iv : kNiceIntervals) {
346 if (iv * pxPerSec >= kMinMajorPx)
350 const double tickSamples = tickIntervalS * m_sfreq;
351 const double minorSamples = tickSamples / 5.0;
352 const double origin =
static_cast<double>(m_firstFileSample);
355 QFont font = QFontDatabase::systemFont(QFontDatabase::FixedFont);
356 font.setPointSizeF(8.0);
358 const QFontMetrics fm(font);
362 double firstMinorS = std::ceil((m_scrollSample - origin - minorSamples) / minorSamples)
363 * minorSamples + origin;
364 p.setPen(QPen(QColor(165, 165, 175), 1));
365 for (
double s = firstMinorS; ; s += minorSamples) {
366 double xPx = (s - m_scrollSample) / spp;
367 if (xPx > W + 2)
break;
368 if (xPx < -2)
continue;
369 int xi =
static_cast<int>(std::round(xPx));
376 double firstMajorS = std::ceil((m_scrollSample - origin - tickSamples) / tickSamples)
377 * tickSamples + origin;
378 for (
double s = firstMajorS; ; s += tickSamples) {
379 double xPx = (s - m_scrollSample) / spp;
380 if (xPx > W + 2)
break;
381 if (xPx < -2)
continue;
383 int xi =
static_cast<int>(std::round(xPx));
385 p.setPen(QPen(QColor(100, 100, 115), 1));
388 double elapsedSec = (s - origin) / m_sfreq;
389 if (elapsedSec >= -tickIntervalS * 0.5) {
391 if (m_useClockTime && elapsedSec >= 0.0) {
392 int totalMs =
static_cast<int>(elapsedSec * 1000.0 + 0.5);
393 int m = totalMs / 60000;
394 int sec = (totalMs % 60000) / 1000;
395 int ms = totalMs % 1000;
396 label = QString(
"%1:%2.%3")
397 .arg(m, 2, 10, QChar(
'0'))
398 .arg(sec, 2, 10, QChar(
'0'))
399 .arg(ms, 3, 10, QChar(
'0'));
401 label = formatTime(elapsedSec);
403 const int lw = fm.horizontalAdvance(label);
405 int lx = xi - lw / 2;
406 lx = qBound(2, lx, W - lw - 2);
407 int ly =
kTimeZoneH - 1 - kMajorH - kLabelGap;
409 p.setPen(QColor(65, 65, 80));
410 p.drawText(lx, ly, label);
420 if (m_sfreq <= 0.0 || m_spp <= 0.0f) {
421 QWidget::contextMenuEvent(event);
425 const int sample = sampleAtX(event->pos().x());
426 const int nearbyMarkerIndex = nearestReferenceMarkerIndex(sample);
429 QAction *addMarkerAction = menu.addAction(tr(
"Add Marker Here"));
430 QAction *removeMarkerAction =
nullptr;
431 QAction *clearMarkersAction =
nullptr;
433 if (nearbyMarkerIndex >= 0) {
434 removeMarkerAction = menu.addAction(tr(
"Remove Nearest Marker"));
437 if (!m_referenceMarkers.isEmpty()) {
439 clearMarkersAction = menu.addAction(tr(
"Clear All Markers"));
442 QAction *selectedAction = menu.exec(event->globalPos());
443 if (!selectedAction) {
447 if (selectedAction == addMarkerAction) {
449 }
else if (selectedAction == removeMarkerAction) {
451 }
else if (selectedAction == clearMarkersAction) {