202 const int W = width();
203 const int H = height();
204 const double spp =
static_cast<double>(m_spp);
206 if (W <= 0 || spp <= 0.0 || m_sfreq <= 0.0)
210 p.setRenderHint(QPainter::Antialiasing,
false);
211 p.setRenderHint(QPainter::TextAntialiasing,
true);
218 p.fillRect(QRect(0, 0, W,
kTimeZoneH), QColor(245, 245, 247));
224 p.setPen(QPen(QColor(190, 190, 205), 1));
228 p.setPen(QPen(QColor(185, 185, 195), 1));
229 p.drawLine(0, H - 1, W, H - 1);
232 if (!m_referenceMarkers.isEmpty()) {
233 QFont markerFont = p.font();
234 markerFont.setPixelSize(9);
235 markerFont.setBold(
true);
236 p.setFont(markerFont);
238 constexpr int kMarkerChipH = 12;
239 constexpr int kMarkerPadX = 5;
240 const int markerChipY = 2;
243 const float xF = (
static_cast<float>(marker.sample) - m_scrollSample) /
static_cast<float>(spp);
244 if (xF < -2.f || xF > W + 2.f) {
248 const int xi =
static_cast<int>(std::round(xF));
249 QColor markerColor = marker.color;
250 markerColor.setAlpha(210);
251 p.setPen(QPen(markerColor, 1));
252 p.drawLine(xi, 0, xi, H - 1);
254 const QString label = marker.label.isEmpty()
255 ? QString::number(marker.sample)
257 const int chipW = qMax(20, p.fontMetrics().horizontalAdvance(label) + 2 * kMarkerPadX);
258 QRect chipRect(xi - chipW / 2, markerChipY, chipW, kMarkerChipH);
259 chipRect.moveLeft(qBound(2, chipRect.left(), qMax(2, W - chipRect.width() - 2)));
261 QColor fillColor = marker.color;
262 fillColor.setAlpha(220);
263 p.fillRect(chipRect, fillColor);
265 p.drawText(chipRect, Qt::AlignCenter, label);
270 if (!m_events.isEmpty()) {
272 evFont.setPixelSize(9);
273 evFont.setBold(
true);
276 constexpr int kChipW = 26;
277 constexpr int kChipH = 11;
284 int lastChipRight = -kChipW;
287 float xF = (
static_cast<float>(ev.sample) - m_scrollSample) /
static_cast<float>(spp);
288 if (xF < -2.f || xF > W + 2.f)
290 int ix =
static_cast<int>(xF);
293 QColor col = ev.color;
295 p.setPen(QPen(col, 1));
301 int chipX = ix - kChipW / 2;
302 chipX = qMax(0, chipX);
303 if (chipX + kChipW > W)
305 if (chipX < lastChipRight + 2)
308 QRectF chip(chipX, kChipY, kChipW, kChipH);
309 QColor fill = ev.color;
311 p.fillRect(chip, fill);
313 QString lbl = ev.label.isEmpty() ? QStringLiteral(
"?") : ev.label;
314 p.drawText(chip, Qt::AlignCenter, lbl);
316 lastChipRight = chipX + kChipW;
321 const double pxPerSec = m_sfreq / spp;
322 double tickIntervalS = kNiceIntervals[0];
323 for (
double iv : kNiceIntervals) {
325 if (iv * pxPerSec >= kMinMajorPx)
329 const double tickSamples = tickIntervalS * m_sfreq;
330 const double minorSamples = tickSamples / 5.0;
331 const double origin =
static_cast<double>(m_firstFileSample);
334 QFont font = QFontDatabase::systemFont(QFontDatabase::FixedFont);
335 font.setPointSizeF(8.0);
337 const QFontMetrics fm(font);
341 double firstMinorS = std::ceil((m_scrollSample - origin - minorSamples) / minorSamples) * minorSamples + origin;
342 p.setPen(QPen(QColor(165, 165, 175), 1));
343 for (
double s = firstMinorS;; s += minorSamples) {
344 double xPx = (s - m_scrollSample) / spp;
349 int xi =
static_cast<int>(std::round(xPx));
356 double firstMajorS = std::ceil((m_scrollSample - origin - tickSamples) / tickSamples) * tickSamples + origin;
357 for (
double s = firstMajorS;; s += tickSamples) {
358 double xPx = (s - m_scrollSample) / spp;
364 int xi =
static_cast<int>(std::round(xPx));
366 p.setPen(QPen(QColor(100, 100, 115), 1));
369 double elapsedSec = (s - origin) / m_sfreq;
370 if (elapsedSec >= -tickIntervalS * 0.5) {
372 if (m_useClockTime && elapsedSec >= 0.0) {
373 int totalMs =
static_cast<int>(elapsedSec * 1000.0 + 0.5);
374 int m = totalMs / 60000;
375 int sec = (totalMs % 60000) / 1000;
376 int ms = totalMs % 1000;
377 label = QString(
"%1:%2.%3")
378 .arg(m, 2, 10, QChar(
'0'))
379 .arg(sec, 2, 10, QChar(
'0'))
380 .arg(ms, 3, 10, QChar(
'0'));
382 label = formatTime(elapsedSec);
384 const int lw = fm.horizontalAdvance(label);
386 int lx = xi - lw / 2;
387 lx = qBound(2, lx, W - lw - 2);
388 int ly =
kTimeZoneH - 1 - kMajorH - kLabelGap;
390 p.setPen(QColor(65, 65, 80));
391 p.drawText(lx, ly, label);
401 if (m_sfreq <= 0.0 || m_spp <= 0.0f) {
402 QWidget::contextMenuEvent(event);
406 const int sample = sampleAtX(event->pos().x());
407 const int nearbyMarkerIndex = nearestReferenceMarkerIndex(sample);
410 QAction* addMarkerAction = menu.addAction(tr(
"Add Marker Here"));
411 QAction* removeMarkerAction =
nullptr;
412 QAction* clearMarkersAction =
nullptr;
414 if (nearbyMarkerIndex >= 0) {
415 removeMarkerAction = menu.addAction(tr(
"Remove Nearest Marker"));
418 if (!m_referenceMarkers.isEmpty()) {
420 clearMarkersAction = menu.addAction(tr(
"Clear All Markers"));
423 QAction* selectedAction = menu.exec(event->globalPos());
424 if (!selectedAction) {
428 if (selectedAction == addMarkerAction) {
430 }
else if (selectedAction == removeMarkerAction) {
432 }
else if (selectedAction == clearMarkersAction) {