Skip to content

Commit 5de22ff

Browse files
committed
Add time and frequency pointers
1 parent 82f5779 commit 5de22ff

7 files changed

Lines changed: 101 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: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ PlotView::PlotView(InputSource *input) : cursors(this), viewRange({0, 0})
5050
auto tunerOutput = std::dynamic_pointer_cast<SampleSource<std::complex<float>>>(spectrogramPlot->output());
5151

5252
enableScales(true);
53+
timePointerEnabled = false;
54+
frequencyPointerEnabled = false;
5355

5456
enableAnnotations(true);
5557
enableAnnotationCommentsTooltips(true);
@@ -223,6 +225,21 @@ void PlotView::enableCursors(bool enabled)
223225
viewport()->update();
224226
}
225227

228+
void PlotView::enableTimePointer(bool enabled)
229+
{
230+
timePointerEnabled = enabled;
231+
spectrogramPlot->enableTimeFrequencyPointers(timePointerEnabled, frequencyPointerEnabled);
232+
233+
viewport()->update();
234+
}
235+
236+
void PlotView::enableFrequencyPointer(bool enabled)
237+
{
238+
frequencyPointerEnabled = enabled;
239+
spectrogramPlot->enableTimeFrequencyPointers(timePointerEnabled, frequencyPointerEnabled);
240+
241+
viewport()->update();
242+
}
226243
bool PlotView::viewportEvent(QEvent *event) {
227244
// Handle wheel events for zooming (before the parent's handler to stop normal scrolling)
228245
if (event->type() == QEvent::Wheel) {
@@ -286,6 +303,9 @@ bool PlotView::viewportEvent(QEvent *event) {
286303
if (cursorsEnabled)
287304
if (cursors.mouseEvent(event->type(), mouseEvent))
288305
return true;
306+
307+
if (timePointerEnabled || frequencyPointerEnabled)
308+
updateView();
289309
}
290310

291311
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: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ SpectrogramPlot::SpectrogramPlot(std::shared_ptr<SampleSource<std::complex<float
4242
sampleRate = 0;
4343
frequencyScaleEnabled = false;
4444
sigmfAnnotationsEnabled = true;
45+
timePointerEnabled = false;
46+
frequencyPointerEnabled = false;
4547

4648
for (int i = 0; i < 256; i++) {
4749
float p = (float)i / 256;
@@ -72,6 +74,54 @@ void SpectrogramPlot::paintFront(QPainter &painter, QRect &rect, range_t<size_t>
7274

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

77127
void SpectrogramPlot::paintFrequencyScale(QPainter &painter, QRect &rect)
@@ -356,6 +406,11 @@ bool SpectrogramPlot::mouseEvent(QEvent::Type type, QMouseEvent *event)
356406
if (tunerEnabled())
357407
return tuner.mouseEvent(type, event);
358408

409+
if (timePointerEnabled || frequencyPointerEnabled) {
410+
mouseX = event->x();
411+
mouseY = event->y();
412+
}
413+
359414
return false;
360415
}
361416

@@ -448,6 +503,11 @@ void SpectrogramPlot::tunerMoved()
448503
emit repaint();
449504
}
450505

506+
void SpectrogramPlot::enableTimeFrequencyPointers(bool timePointer, bool frequencyPointer) {
507+
timePointerEnabled = timePointer;
508+
frequencyPointerEnabled = frequencyPointer;
509+
}
510+
451511
uint qHash(const TileCacheKey &key, uint seed)
452512
{
453513
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)