37#include <QResizeEvent>
64 setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
68 if (m_useClock == useClock)
return;
69 m_useClock = useClock;
77 p.setRenderHint(QPainter::TextAntialiasing,
true);
81 const int W = width();
84 p.fillRect(QRect(0, 0, W, kTimeH), QColor(245, 245, 247));
87 p.fillRect(QRect(0, kTimeH, W, kStimH), QColor(238, 238, 246));
90 p.setPen(QPen(QColor(190, 190, 205), 1));
91 p.drawLine(0, kTimeH, W - 1, kTimeH);
94 p.setPen(QPen(QColor(185, 185, 195), 1));
95 p.drawLine(W - 1, 0, W - 1, height());
99 tf.setPointSizeF(8.0);
102 p.setPen(QColor(60, 60, 70));
103 p.drawText(QRect(0, 0, W, kTimeH / 2 + 2), Qt::AlignCenter, QStringLiteral(
"Time"));
107 subf.setPointSizeF(6.5);
109 p.setPen(QColor(130, 130, 145));
110 QString fmtLabel = m_useClock ? QStringLiteral(
"mm:ss\u00B7ms")
111 : QStringLiteral(
"seconds");
112 p.drawText(QRect(0, kTimeH / 2, W, kTimeH / 2),
113 Qt::AlignCenter, fmtLabel);
117 sf.setPointSizeF(7.5);
120 p.setPen(QColor(80, 80, 100));
121 p.drawText(QRect(0, kTimeH, W, kStimH), Qt::AlignCenter, QStringLiteral(
"Stim"));
125 bool m_useClock =
false;
136 , m_sSettingsPath(sSettingsPath)
152void ChannelDataView::setupLayout()
154 auto *outerLayout =
new QVBoxLayout(
this);
155 outerLayout->setContentsMargins(0, 0, 0, 0);
156 outerLayout->setSpacing(0);
165 auto *renderRow =
new QHBoxLayout();
166 renderRow->setContentsMargins(0, 0, 0, 0);
167 renderRow->setSpacing(0);
170 auto *leftCol =
new QVBoxLayout();
171 leftCol->setContentsMargins(0, 0, 0, 0);
172 leftCol->setSpacing(0);
176 leftCol->addWidget(m_pRulerHeader, 0);
179 leftCol->addWidget(m_pLabelPanel, 1);
181 renderRow->addLayout(leftCol, 0);
184 auto *traceColumn =
new QVBoxLayout();
185 traceColumn->setContentsMargins(0, 0, 0, 0);
186 traceColumn->setSpacing(0);
189 traceColumn->addWidget(m_pTimeRuler, 0);
192 m_pRhiView->
setModel(m_pModel.data());
194 m_pRhiView->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
195 m_pRhiView->setFocusPolicy(Qt::ClickFocus);
196 traceColumn->addWidget(m_pRhiView, 1);
198 renderRow->addLayout(traceColumn, 1);
201 auto *rightCol =
new QVBoxLayout();
202 rightCol->setContentsMargins(0, 0, 0, 0);
203 rightCol->setSpacing(0);
207 auto *rulerSpacer =
new QWidget(
this);
209 rulerSpacer->setVisible(
true);
210 rightCol->addWidget(rulerSpacer, 0);
212 m_pChannelScrollBar =
new QScrollBar(Qt::Vertical,
this);
213 m_pChannelScrollBar->setMinimum(0);
214 m_pChannelScrollBar->setMaximum(0);
215 m_pChannelScrollBar->setValue(0);
216 m_pChannelScrollBar->setSingleStep(1);
217 m_pChannelScrollBar->setPageStep(12);
218 m_pChannelScrollBar->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
219 rightCol->addWidget(m_pChannelScrollBar, 1);
221 renderRow->addLayout(rightCol, 0);
223 outerLayout->addLayout(renderRow, 1);
227 m_pOverviewBar->
setModel(m_pModel.data());
228 outerLayout->addWidget(m_pOverviewBar, 0);
233 auto *bottomRow =
new QHBoxLayout();
234 bottomRow->setContentsMargins(0, 0, 0, 0);
235 bottomRow->setSpacing(0);
237 m_pScrollBar =
new QScrollBar(Qt::Horizontal,
this);
238 m_pScrollBar->setMinimum(0);
239 m_pScrollBar->setMaximum(0);
240 m_pScrollBar->setValue(0);
241 m_pScrollBar->setSingleStep(1);
242 m_pScrollBar->setPageStep(100);
243 m_pScrollBar->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
244 bottomRow->addWidget(m_pScrollBar, 1);
246 m_pScrollModeButton =
new QToolButton(
this);
247 m_pScrollModeButton->setCheckable(
true);
248 m_pScrollModeButton->setChecked(
true);
249 m_pScrollModeButton->setText(QStringLiteral(
"\u2195 Ch"));
250 m_pScrollModeButton->setToolTip(QStringLiteral(
251 "Vertical mouse wheel:\n"
252 "\u2195 Ch \u2013 scroll through channels\n"
253 "\u21c4 Time \u2013 scroll through time"));
254 bottomRow->addWidget(m_pScrollModeButton, 0);
256 outerLayout->addLayout(bottomRow, 0);
259 connect(m_pScrollBar, &QScrollBar::valueChanged,
260 this, &ChannelDataView::onScrollBarMoved);
262 connect(m_pChannelScrollBar, &QScrollBar::valueChanged,
263 this, &ChannelDataView::onChannelScrollBarMoved);
266 this, &ChannelDataView::onRhiScrollChanged);
269 this, &ChannelDataView::onChannelOffsetChanged);
277 connect(m_pScrollModeButton, &QToolButton::toggled,
this, [
this](
bool checked) {
280 m_pScrollModeButton->setText(checked ? QStringLiteral(
"\u2195 Ch")
281 : QStringLiteral(
"\u21c4 Time"));
313 this, [
this](
int,
int) { updateSamplesPerPixel(); });
316 this, &ChannelDataView::updateScrollBarRange);
319 this, &ChannelDataView::updateChannelScrollBarRange);
323 m_pLabelPanel, QOverload<>::of(&QWidget::update));
325 m_pLabelPanel, QOverload<>::of(&QWidget::update));
329 this, [
this](
float sample) {
330 if (m_pLabelPanel && m_pRhiView) {
331 m_pLabelPanel->setVisibleSampleRange(
332 static_cast<int>(sample),
333 static_cast<int>(sample) + m_pRhiView->visibleSampleCount());
340 this, [
this](
float sample) {
341 if (m_pOverviewBar && m_pRhiView) {
342 m_pOverviewBar->setViewport(
344 static_cast<float>(m_pRhiView->visibleSampleCount()));
348 this, [
this](
float) {
349 if (m_pOverviewBar && m_pRhiView) {
350 m_pOverviewBar->setViewport(
351 m_pRhiView->scrollSample(),
352 static_cast<float>(m_pRhiView->visibleSampleCount()));
358 if (m_pOverviewBar) {
359 m_pOverviewBar->setModel(m_pModel.data());
364 this, [
this](
float targetSample) {
366 m_pRhiView->scrollTo(targetSample, 150);
369 setFocusProxy(m_pRhiView);
370 setFocusPolicy(Qt::StrongFocus);
378 m_pModel->init(pInfo);
381 if (!m_scaleMap.isEmpty())
382 m_pModel->setScaleMap(m_scaleMap);
383 m_pModel->setSignalColor(m_signalColor);
387 m_pTimeRuler->setSfreq(pInfo->sfreq);
389 m_pRhiView->setSfreq(
static_cast<float>(pInfo->sfreq));
391 m_pOverviewBar->setSfreq(
static_cast<float>(pInfo->sfreq));
395 m_pLabelPanel->setModel(m_pModel.data());
396 m_pLabelPanel->setVisibleChannelCount(m_pRhiView ? m_pRhiView->visibleChannelCount() : 12);
399 updateSamplesPerPixel();
400 updateScrollBarRange();
401 updateChannelScrollBarRange();
408 m_firstFileSample = first;
409 m_lastFileSample = last;
411 m_pRhiView->setFirstFileSample(first);
412 m_pRhiView->setLastFileSample(last);
415 m_pTimeRuler->setFirstFileSample(first);
416 if (m_pOverviewBar) {
417 m_pOverviewBar->setFirstFileSample(first);
418 m_pOverviewBar->setLastFileSample(last);
420 updateScrollBarRange();
427 m_pModel->setData(data, firstSample);
428 updateScrollBarRange();
435 m_pModel->appendData(data);
436 updateScrollBarRange();
443 m_pRhiView->scrollTo(
static_cast<float>(sample), animate ? 200 : 0);
450 m_windowSizeSeconds = qMax(seconds, 0.01f);
451 updateSamplesPerPixel();
459 return m_windowSizeSeconds;
466 m_zoomFactor = qMax(factor, 0.001);
467 updateSamplesPerPixel();
484 m_pRhiView->setBackgroundColor(color);
499 m_signalColor = color;
500 m_pModel->setSignalColor(color);
508 return m_signalColor;
515 m_scaleMap = scaleMap;
516 m_pModel->setScaleMap(scaleMap);
530 m_hideBadChannels = hide;
532 m_pRhiView->setHideBadChannels(hide);
534 m_pLabelPanel->setHideBadChannels(hide);
535 updateChannelScrollBarRange();
542 return m_hideBadChannels;
549 QVector<int> indices;
550 if (!names.isEmpty() && m_pModel) {
551 int total = m_pModel->channelCount();
552 for (
int i = 0; i < total; ++i) {
560 m_pRhiView->setChannelIndices(indices);
562 m_pLabelPanel->setChannelIndices(indices);
565 updateChannelScrollBarRange();
572 m_pModel->setRemoveDC(dc);
579 m_pModel->setDetrendMode(mode);
586 return m_pModel->detrendMode();
594 m_pRhiView->setEvents(events);
597 m_pOverviewBar->setEvents(events);
600 QVector<TimeRulerEventMark> rulerMarks;
601 rulerMarks.reserve(events.size());
602 for (
const auto &ev : events)
603 rulerMarks.append({ev.sample, ev.color, ev.label});
604 m_pTimeRuler->setEvents(rulerMarks);
613 m_pRhiView->setEpochMarkers(triggerSamples);
619 m_pRhiView->setEpochMarkersVisible(visible);
624 return m_pRhiView ? m_pRhiView->epochMarkersVisible() :
false;
630 m_pRhiView->setClippingVisible(visible);
635 return m_pRhiView ? m_pRhiView->clippingVisible() :
false;
641 m_pRhiView->setZScoreMode(enabled);
646 return m_pRhiView ? m_pRhiView->zScoreMode() :
false;
654 m_pTimeRuler->setReferenceMarkers(markers);
662 m_pRhiView->setAnnotations(annotations);
664 m_pOverviewBar->setAnnotations(annotations);
672 m_pRhiView->setAnnotationSelectionEnabled(enabled);
680 m_pRhiView->setEventsVisible(visible);
685 return m_pRhiView ? m_pRhiView->eventsVisible() :
true;
693 m_pRhiView->setAnnotationsVisible(visible);
698 return m_pRhiView ? m_pRhiView->annotationsVisible() :
true;
706 m_pOverviewBar->setVisible(visible);
711 return m_pOverviewBar ? m_pOverviewBar->isVisible() :
true;
719 m_pRhiView->setScrollSpeedFactor(factor);
724 return m_pRhiView ? m_pRhiView->scrollSpeedFactor() : 1.0f;
735 static const QStringList typeOrder = {
736 "MEG grad",
"MEG mag",
"EEG",
"EOG",
"ECG",
"EMG",
"STIM",
"MISC"
739 const int n = m_pModel->channelCount();
740 QVector<int> indices(n);
741 std::iota(indices.begin(), indices.end(), 0);
743 std::stable_sort(indices.begin(), indices.end(), [&](
int a,
int b) {
744 int ia = typeOrder.indexOf(m_pModel->channelInfo(a).typeLabel);
745 int ib = typeOrder.indexOf(m_pModel->channelInfo(b).typeLabel);
746 if (ia < 0) ia = typeOrder.size();
747 if (ib < 0) ib = typeOrder.size();
752 m_pRhiView->setChannelIndices(indices);
754 m_pLabelPanel->setChannelIndices(indices);
755 updateChannelScrollBarRange();
761 m_pRhiView->setChannelIndices({});
763 m_pLabelPanel->setChannelIndices({});
764 updateChannelScrollBarRange();
772 m_pRhiView->setCrosshairEnabled(enabled);
777 return m_pRhiView ? m_pRhiView->crosshairEnabled() :
false;
785 m_pRhiView->setScalebarsVisible(visible);
790 return m_pRhiView ? m_pRhiView->scalebarsVisible() :
false;
798 m_pRhiView->setButterflyMode(enabled);
800 m_pLabelPanel->setButterflyMode(enabled);
805 return m_pRhiView ? m_pRhiView->butterflyMode() :
false;
813 m_pTimeRuler->toggleTimeFormat();
814 bool useClock = m_pTimeRuler ? m_pTimeRuler->clockTimeFormat() :
false;
816 m_pRhiView->setClockTimeFormat(useClock);
826 m_pRhiView->setClockTimeFormat(useClock);
833 return m_pTimeRuler ? m_pTimeRuler->clockTimeFormat() :
false;
840 return m_pRhiView ? m_pRhiView->visibleFirstSample() : 0;
847 return m_pRhiView ? m_pRhiView->visibleSampleCount() : 0;
854 return m_pRhiView ? m_pRhiView->geometry() : QRect();
864 if(viewportRect.width() <= 0) {
865 return viewportRect.left();
868 const double samplesPerPixel =
static_cast<double>(visibleSamples)
869 /
static_cast<double>(viewportRect.width());
870 const double xOffset =
static_cast<double>(sample -
firstVisibleSample()) / samplesPerPixel;
872 return viewportRect.left()
873 + qBound(0, qRound(xOffset), viewportRect.width() - 1);
883 if(viewportRect.width() <= 0) {
887 const int clampedX = qBound(viewportRect.left(), x, viewportRect.right());
888 const double samplesPerPixel =
static_cast<double>(visibleSamples)
889 /
static_cast<double>(viewportRect.width());
892 + qRound(
static_cast<double>(clampedX - viewportRect.left()) * samplesPerPixel);
899 if (m_sSettingsPath.isEmpty())
902 s.setValue(m_sSettingsPath +
"/windowSizeSeconds", m_windowSizeSeconds);
903 s.setValue(m_sSettingsPath +
"/zoomFactor", m_zoomFactor);
904 s.setValue(m_sSettingsPath +
"/backgroundColor", m_bgColor);
905 s.setValue(m_sSettingsPath +
"/signalColor", m_signalColor);
912 if (m_sSettingsPath.isEmpty())
915 float rawWindowSec = s.value(m_sSettingsPath +
"/windowSizeSeconds", 10.f).toFloat();
916 m_windowSizeSeconds = qBound(0.5f, rawWindowSec, 120.f);
918 if (rawWindowSec != m_windowSizeSeconds)
919 s.remove(m_sSettingsPath +
"/windowSizeSeconds");
921 m_zoomFactor = s.value(m_sSettingsPath +
"/zoomFactor", 1.0).toDouble();
922 m_bgColor = s.value(m_sSettingsPath +
"/backgroundColor", QColor(250, 250, 250)).value<QColor>();
923 m_signalColor = s.value(m_sSettingsPath +
"/signalColor", QColor(Qt::darkGreen)).value<QColor>();
928 m_pRhiView->setBackgroundColor(m_bgColor);
930 m_pModel->setSignalColor(m_signalColor);
937 m_pModel->clearData();
939 m_pScrollBar->setMaximum(0);
940 m_pScrollBar->setValue(0);
943 m_pRhiView->setScrollSample(0.f);
945 m_pTimeRuler->setFirstFileSample(0);
946 m_pTimeRuler->setScrollSample(0.f);
947 m_pTimeRuler->setReferenceMarkers({});
962 QWidget::keyPressEvent(event);
966 float step = m_pRhiView->visibleSampleCount() * 0.1f;
967 float page = m_pRhiView->visibleSampleCount() * 0.9f;
969 switch (event->key()) {
971 m_pRhiView->scrollTo(m_pRhiView->scrollSample() - step, 150);
974 m_pRhiView->scrollTo(m_pRhiView->scrollSample() + step, 150);
977 m_pRhiView->scrollTo(m_pRhiView->scrollSample() - page, 200);
979 case Qt::Key_PageDown:
980 m_pRhiView->scrollTo(m_pRhiView->scrollSample() + page, 200);
983 m_pRhiView->scrollTo(
static_cast<float>(m_pModel->firstSample()), 300);
987 float lastStart =
static_cast<float>(
988 m_pModel->firstSample() + m_pModel->totalSamples()
989 - m_pRhiView->visibleSampleCount());
990 m_pRhiView->scrollTo(qMax(lastStart, 0.f), 300);
995 m_pRhiView->zoomTo(m_pRhiView->samplesPerPixel() * 0.75f, 200);
998 m_pRhiView->zoomTo(m_pRhiView->samplesPerPixel() * 1.33f, 200);
1007 switch (m_pModel->detrendMode()) {
1039 if (event->modifiers() & Qt::ShiftModifier) {
1043 QWidget::keyPressEvent(event);
1051 case Qt::Key_BracketRight:
1055 case Qt::Key_BracketLeft:
1063 QWidget::keyPressEvent(event);
1073 AbstractView::resizeEvent(event);
1074 updateSamplesPerPixel();
1075 updateScrollBarRange();
1080void ChannelDataView::onScrollBarMoved(
int value)
1082 if (m_scrollBarUpdating || !m_pRhiView)
1089void ChannelDataView::onRhiScrollChanged(
float sample)
1096 m_scrollBarUpdating =
true;
1097 m_pScrollBar->setValue(
static_cast<int>(sample));
1098 m_scrollBarUpdating =
false;
1103void ChannelDataView::updateScrollBarRange()
1105 if (!m_pScrollBar || !m_pRhiView)
1108 int visible = m_pRhiView->visibleSampleCount();
1111 if (m_firstFileSample >= 0 && m_lastFileSample >= 0) {
1113 minVal = m_firstFileSample;
1114 maxVal = qMax(m_firstFileSample, m_lastFileSample - visible + 1);
1117 int firstSamp = m_pModel->firstSample();
1118 int total = m_pModel->totalSamples();
1120 maxVal = qMax(firstSamp, firstSamp + total - visible);
1123 m_scrollBarUpdating =
true;
1124 m_pScrollBar->setMinimum(minVal);
1125 m_pScrollBar->setMaximum(maxVal);
1126 m_pScrollBar->setPageStep(visible);
1127 m_scrollBarUpdating =
false;
1132void ChannelDataView::updateSamplesPerPixel()
1134 if (!m_pRhiView || !m_pFiffInfo)
1137 float sfreq =
static_cast<float>(m_pFiffInfo->sfreq);
1138 int viewPx = m_pRhiView->width();
1143 float spp = (m_windowSizeSeconds * sfreq) / viewPx /
static_cast<float>(m_zoomFactor);
1144 m_pRhiView->setSamplesPerPixel(qMax(spp, 1e-4f));
1145 updateScrollBarRange();
1150void ChannelDataView::onChannelScrollBarMoved(
int value)
1152 if (m_channelScrollBarUpdating || !m_pRhiView)
1154 m_pRhiView->setFirstVisibleChannel(value);
1159void ChannelDataView::onChannelOffsetChanged(
int firstChannel)
1161 if (!m_pChannelScrollBar)
1163 m_channelScrollBarUpdating =
true;
1164 m_pChannelScrollBar->setValue(firstChannel);
1165 m_channelScrollBarUpdating =
false;
1170void ChannelDataView::updateChannelScrollBarRange()
1172 if (!m_pChannelScrollBar || !m_pRhiView)
1176 int totalCh = m_pRhiView ? m_pRhiView->totalLogicalChannels()
1177 : m_pModel->channelCount();
1178 int visibleCnt = m_pRhiView->visibleChannelCount();
1179 int maxVal = qMax(0, totalCh - visibleCnt);
1181 m_channelScrollBarUpdating =
true;
1182 m_pChannelScrollBar->setMaximum(maxVal);
1183 m_pChannelScrollBar->setPageStep(visibleCnt);
1184 m_channelScrollBarUpdating =
false;
QRhi-based GPU-accelerated channel time-series renderer used by the modern raw browser.
Vertical column of channel-name labels synced with ChannelDataView's row geometry.
Circular-buffer Qt model exposing a rolling window of the live FIFF stream as a table.
Horizontal time-axis ruler displayed beneath ChannelDataView with sample / second ticks.
Composite real-time multi-channel time-series scroller (label panel, table view, time ruler,...
Full FIFF measurement metadata: everything from FIFFB_MEAS / FIFFB_MEAS_INFO needed to interpret a re...
FIFF file I/O, in-memory data structures and high-level readers/writers.
2-D display widgets and visualisation helpers (charts, topography, colour maps).
DetrendMode
Channel display metadata (read-only from the renderer's perspective).
AbstractView(QWidget *parent=0, Qt::WindowFlags f=Qt::Widget)
RulerHeaderWidget(QWidget *parent=nullptr)
void setClockTimeFormat(bool useClock)
void paintEvent(QPaintEvent *) override
QRect signalViewportRect() const
ChannelDataView(const QString &sSettingsPath=QString(), QWidget *parent=nullptr, Qt::WindowFlags f=Qt::Widget)
void setScalingMap(const QMap< qint32, float > &scaleMap)
void referenceMarkerRemoveRequested(int sample)
void eventsVisibleToggled(bool on)
void loadSettings() override
void clippingToggled(bool on)
int viewportXToSample(int x) const
void setButterflyMode(bool enabled)
void crosshairToggled(bool on)
void sortChannelsByType()
void setBackgroundColor(const QColor &color)
void setClockTimeFormat(bool useClock)
void setRemoveDC(bool dc)
int firstVisibleSample() const
void setWindowSize(float seconds)
void sampleClicked(int sample)
void saveSettings() override
DetrendMode detrendMode() const
bool badChannelsHidden() const
void referenceMarkersClearRequested()
void zScoreModeToggled(bool on)
void clearView() override
bool annotationsVisible() const
void annotationsVisibleToggled(bool on)
void setOverviewBarVisible(bool visible)
void updateGuiMode(GuiMode mode) override
void setSignalColor(const QColor &color)
void scrollPositionChanged(int sample)
void setData(const Eigen::MatrixXd &data, int firstSample=0)
void referenceMarkerAddRequested(int sample)
int visibleSampleCount() const
bool epochMarkersVisible() const
void setEpochMarkersVisible(bool visible)
void setEvents(const QVector< ChannelRhiView::EventMarker > &events)
float scrollSpeedFactor() const
void setZScoreMode(bool enabled)
void setDetrendMode(DetrendMode mode)
bool overviewBarVisible() const
void scrollToSample(int sample, bool animate=true)
QColor signalColor() const
void scalebarsToggled(bool on)
void setFileBounds(int first, int last)
bool butterflyMode() const
void resizeEvent(QResizeEvent *event) override
~ChannelDataView() override
void init(QSharedPointer< FIFFLIB::FiffInfo > pInfo)
void hideBadChannels(bool hide)
bool clockTimeFormat() const
void butterflyToggled(bool on)
void setEpochMarkers(const QVector< int > &triggerSamples)
void setClippingVisible(bool visible)
int sampleToViewportX(int sample) const
void epochMarkersToggled(bool on)
void overviewBarToggled(bool on)
void setAnnotationsVisible(bool visible)
void setScalebarsVisible(bool visible)
void setAnnotationSelectionEnabled(bool enabled)
void updateProcessingMode(ProcessingMode mode) override
bool clippingVisible() const
void cursorDataChanged(float timeSec, float amplitude, const QString &channelName, const QString &unitLabel)
void addData(const Eigen::MatrixXd &data)
QMap< qint32, float > scalingMap() const
void sampleRangeSelected(int startSample, int endSample)
void setEventsVisible(bool visible)
bool eventsVisible() const
bool crosshairEnabled() const
bool scalebarsVisible() const
void scrollSpeedChanged(float factor)
void setCrosshairEnabled(bool enabled)
void annotationBoundaryMoved(int annotationIndex, bool isStartBoundary, int newSample)
void keyPressEvent(QKeyEvent *event) override
void setReferenceMarkers(const QVector< TimeRulerReferenceMark > &markers)
void setAnnotations(const QVector< ChannelRhiView::AnnotationSpan > &annotations)
void setScrollSpeedFactor(float factor)
QColor backgroundColor() const
void setZoom(double factor)
void setChannelFilter(const QStringList &names)
Channel display metadata (read-only from the renderer's perspective).
Circular-buffer Qt model exposing a rolling window of the live FIFF stream as a table.
Vertical column of channel-name labels synced with ChannelDataView row geometry.
void channelScrollRequested(int targetFirst)
void setFirstVisibleChannel(int ch)
QRhi-based GPU-accelerated channel time-series renderer used by the modern raw browser.
void viewResized(int newWidth, int newHeight)
void channelOffsetChanged(int firstChannel)
void samplesPerPixelChanged(float spp)
void sampleRangeSelected(int startSample, int endSample)
void annotationBoundaryMoved(int annotationIndex, bool isStartBoundary, int newSample)
void setModel(ChannelDataModel *model)
void setFirstVisibleChannel(int ch)
void sampleClicked(int sample)
void setBackgroundColor(const QColor &color)
void setScrollSample(float sample)
void cursorDataChanged(float timeSec, float amplitude, const QString &channelName, const QString &unitLabel)
void scrollSampleChanged(float sample)
void setWheelScrollsChannels(bool channelsMode)
Minimap thumbnail of the entire recording shown above the raw browser.
void scrollRequested(float targetSample)
void setModel(ChannelDataModel *model)
Horizontal time-axis ruler displayed beneath ChannelDataView.
static constexpr int kTotalH
Total widget height (px).
void setScrollSample(float sample)
static constexpr int kTimeZoneH
Height of the time-tick zone (px).
static constexpr int kStimZoneH
Height of the stimulus lane (px).
void removeReferenceMarkerRequested(int sample)
void addReferenceMarkerRequested(int sample)
void setSamplesPerPixel(float spp)
void clearReferenceMarkersRequested()