Skip to content

Commit 8cdb08b

Browse files
committed
Add time and frequency pointers
1 parent 82f5779 commit 8cdb08b

7 files changed

Lines changed: 97 additions & 0 deletions

File tree

src/mainwindow.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ MainWindow::MainWindow()
4545
// Connect dock inputs
4646
connect(dock, &SpectrogramControls::openFile, this, &MainWindow::openFile);
4747
connect(dock->sampleRate, static_cast<void (QLineEdit::*)(const QString&)>(&QLineEdit::textChanged), this, static_cast<void (MainWindow::*)(QString)>(&MainWindow::setSampleRate));
48+
connect(dock->timePointerCheckBox, &QCheckBox::stateChanged, plots, &PlotView::enableTimePointer);
49+
connect(dock->frequencyPointerCheckBox, &QCheckBox::stateChanged, plots, &PlotView::enableFrequencyPointer);
4850
connect(dock, static_cast<void (SpectrogramControls::*)(int, int)>(&SpectrogramControls::fftOrZoomChanged), plots, &PlotView::setFFTAndZoom);
4951
connect(dock->powerMaxSlider, &QSlider::valueChanged, plots, &PlotView::setPowerMax);
5052
connect(dock->powerMinSlider, &QSlider::valueChanged, plots, &PlotView::setPowerMin);

src/plotview.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,21 @@ void PlotView::enableCursors(bool enabled)
223223
viewport()->update();
224224
}
225225

226+
void PlotView::enableTimePointer(bool enabled)
227+
{
228+
timePointerEnabled = enabled;
229+
spectrogramPlot->enableTimeFrequencyPointers(timePointerEnabled, frequencyPointerEnabled);
230+
231+
viewport()->update();
232+
}
233+
234+
void PlotView::enableFrequencyPointer(bool enabled)
235+
{
236+
frequencyPointerEnabled = enabled;
237+
spectrogramPlot->enableTimeFrequencyPointers(timePointerEnabled, frequencyPointerEnabled);
238+
239+
viewport()->update();
240+
}
226241
bool PlotView::viewportEvent(QEvent *event) {
227242
// Handle wheel events for zooming (before the parent's handler to stop normal scrolling)
228243
if (event->type() == QEvent::Wheel) {
@@ -286,6 +301,9 @@ bool PlotView::viewportEvent(QEvent *event) {
286301
if (cursorsEnabled)
287302
if (cursors.mouseEvent(event->type(), mouseEvent))
288303
return true;
304+
305+
if (timePointerEnabled || frequencyPointerEnabled)
306+
updateView();
289307
}
290308

291309
if (event->type() == QEvent::Leave) {

src/plotview.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ class PlotView : public QGraphicsView, Subscriber
4444

4545
public slots:
4646
void cursorsMoved();
47+
void enableTimePointer(bool enabled);
48+
void enableFrequencyPointer(bool enabled);
4749
void enableCursors(bool enabled);
4850
void enableScales(bool enabled);
4951
void enableAnnotations(bool enabled);
@@ -79,6 +81,8 @@ public slots:
7981
int zoomLevel = 1;
8082
int powerMin;
8183
int powerMax;
84+
bool timePointerEnabled;
85+
bool frequencyPointerEnabled;
8286
bool cursorsEnabled;
8387
double sampleRate = 0.0;
8488
bool timeScaleEnabled;

src/spectrogramcontrols.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,12 @@ SpectrogramControls::SpectrogramControls(const QString & title, QWidget * parent
4141
sampleRate->setValidator(double_validator);
4242
layout->addRow(new QLabel(tr("Sample rate:")), sampleRate);
4343

44+
// Frequency and time pointer settings
45+
frequencyPointerCheckBox = new QCheckBox(widget);
46+
layout->addRow(new QLabel(tr("Enable frequency pointer:")), frequencyPointerCheckBox);
47+
timePointerCheckBox = new QCheckBox(widget);
48+
layout->addRow(new QLabel(tr("Enable time pointer:")), timePointerCheckBox);
49+
4450
// Spectrogram settings
4551
layout->addRow(new QLabel()); // TODO: find a better way to add an empty row?
4652
layout->addRow(new QLabel(tr("<b>Spectrogram</b>")));

src/spectrogramcontrols.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ private slots:
6363
public:
6464
QPushButton *fileOpenButton;
6565
QLineEdit *sampleRate;
66+
QCheckBox *timePointerCheckBox;
67+
QCheckBox *frequencyPointerCheckBox;
6668
QSlider *fftSizeSlider;
6769
QSlider *zoomLevelSlider;
6870
QSlider *powerMaxSlider;

src/spectrogramplot.cpp

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,54 @@ void SpectrogramPlot::paintFront(QPainter &painter, QRect &rect, range_t<size_t>
7272

7373
if (sigmfAnnotationsEnabled)
7474
paintAnnotations(painter, rect, sampleRange);
75+
76+
if (timePointerEnabled || frequencyPointerEnabled)
77+
paintTimeFrequencyPointers(painter, rect, sampleRange);
78+
}
79+
80+
void SpectrogramPlot::paintTimeFrequencyPointers(QPainter &painter, QRect &rect, range_t<size_t> sampleRange)
81+
{
82+
if (sampleRate == 0) {
83+
return;
84+
}
85+
86+
if (sampleRate / 2 > UINT64_MAX) {
87+
return;
88+
}
89+
90+
int plotHeight = rect.height();
91+
if (inputSource->realSignal())
92+
plotHeight *= 2;
93+
94+
double bwPerPixel = (double)sampleRate / plotHeight;
95+
96+
painter.save();
97+
98+
QPen pen(Qt::white, 1, Qt::SolidLine);
99+
painter.setPen(pen);
100+
QFontMetrics fm(painter.font());
101+
102+
103+
char buf[128];
104+
if (frequencyPointerEnabled) {
105+
int freqHz = ((plotHeight / 2) - mouseY) * bwPerPixel;
106+
snprintf(buf, sizeof(buf), "Frequency: %d Hz", freqHz);
107+
108+
painter.drawLine(0, mouseY, mouseX, mouseY);
109+
painter.drawText(mouseX + 15, mouseY, buf);
110+
}
111+
if (timePointerEnabled) {
112+
float timeStart = sampleRange.minimum / sampleRate;
113+
float timeEnd = sampleRange.maximum / sampleRate;
114+
float secondsPerPixel = (timeEnd - timeStart) / rect.width();
115+
float timeAtPointer = timeStart + mouseX * secondsPerPixel;
116+
snprintf(buf, sizeof(buf), "Time: %.6f s", timeAtPointer);
117+
118+
painter.drawText(mouseX + 15, mouseY + fm.height(), buf);
119+
painter.drawLine(mouseX, 0, mouseX, mouseY);
120+
}
121+
122+
painter.restore();
75123
}
76124

77125
void SpectrogramPlot::paintFrequencyScale(QPainter &painter, QRect &rect)
@@ -356,6 +404,11 @@ bool SpectrogramPlot::mouseEvent(QEvent::Type type, QMouseEvent *event)
356404
if (tunerEnabled())
357405
return tuner.mouseEvent(type, event);
358406

407+
if (timePointerEnabled || frequencyPointerEnabled) {
408+
mouseX = event->x();
409+
mouseY = event->y();
410+
}
411+
359412
return false;
360413
}
361414

@@ -448,6 +501,11 @@ void SpectrogramPlot::tunerMoved()
448501
emit repaint();
449502
}
450503

504+
void SpectrogramPlot::enableTimeFrequencyPointers(bool timePointer, bool frequencyPointer) {
505+
timePointerEnabled = timePointer;
506+
frequencyPointerEnabled = frequencyPointer;
507+
}
508+
451509
uint qHash(const TileCacheKey &key, uint seed)
452510
{
453511
return key.fftSize ^ key.zoomLevel ^ key.sample ^ seed;

src/spectrogramplot.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ class SpectrogramPlot : public Plot
7474
bool tunerEnabled();
7575
void enableScales(bool enabled);
7676
void enableAnnotations(bool enabled);
77+
void enableTimeFrequencyPointers(bool timePointer, bool frequencyPointer);
7778
bool isAnnotationsEnabled();
7879
QString *mouseAnnotationComment(const QMouseEvent *event);
7980

@@ -103,6 +104,11 @@ public slots:
103104
double sampleRate;
104105
bool frequencyScaleEnabled;
105106
bool sigmfAnnotationsEnabled;
107+
bool timePointerEnabled;
108+
bool frequencyPointerEnabled;
109+
110+
int mouseX;
111+
int mouseY;
106112

107113
Tuner tuner;
108114
std::shared_ptr<TunerTransform> tunerTransform;
@@ -116,6 +122,7 @@ public slots:
116122
int linesPerTile();
117123
void paintFrequencyScale(QPainter &painter, QRect &rect);
118124
void paintAnnotations(QPainter &painter, QRect &rect, range_t<size_t> sampleRange);
125+
void paintTimeFrequencyPointers(QPainter &painter, QRect &rect, range_t<size_t> sampleRange);
119126
};
120127

121128
class AnnotationLocation

0 commit comments

Comments
 (0)