37#include <QResizeEvent>
65 setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
70 if (m_useClock == useClock)
72 m_useClock = useClock;
80 p.setRenderHint(QPainter::TextAntialiasing,
true);
84 const int W = width();
87 p.fillRect(QRect(0, 0, W, kTimeH), QColor(245, 245, 247));
90 p.fillRect(QRect(0, kTimeH, W, kStimH), QColor(238, 238, 246));
93 p.setPen(QPen(QColor(190, 190, 205), 1));
94 p.drawLine(0, kTimeH, W - 1, kTimeH);
97 p.setPen(QPen(QColor(185, 185, 195), 1));
98 p.drawLine(W - 1, 0, W - 1, height());
102 tf.setPointSizeF(8.0);
105 p.setPen(QColor(60, 60, 70));
106 p.drawText(QRect(0, 0, W, kTimeH / 2 + 2), Qt::AlignCenter, QStringLiteral(
"Time"));
110 subf.setPointSizeF(6.5);
112 p.setPen(QColor(130, 130, 145));
113 QString fmtLabel = m_useClock ? QStringLiteral(
"mm:ss\u00B7ms")
114 : QStringLiteral(
"seconds");
115 p.drawText(QRect(0, kTimeH / 2, W, kTimeH / 2),
116 Qt::AlignCenter, fmtLabel);
120 sf.setPointSizeF(7.5);
123 p.setPen(QColor(80, 80, 100));
124 p.drawText(QRect(0, kTimeH, W, kStimH), Qt::AlignCenter, QStringLiteral(
"Stim"));
128 bool m_useClock =
false;
139, m_sSettingsPath(sSettingsPath)
155void ChannelDataView::setupLayout()
157 auto* outerLayout =
new QVBoxLayout(
this);
158 outerLayout->setContentsMargins(0, 0, 0, 0);
159 outerLayout->setSpacing(0);
168 auto* renderRow =
new QHBoxLayout();
169 renderRow->setContentsMargins(0, 0, 0, 0);
170 renderRow->setSpacing(0);
173 auto* leftCol =
new QVBoxLayout();
174 leftCol->setContentsMargins(0, 0, 0, 0);
175 leftCol->setSpacing(0);
179 leftCol->addWidget(m_pRulerHeader, 0);
182 leftCol->addWidget(m_pLabelPanel, 1);
184 renderRow->addLayout(leftCol, 0);
187 auto* traceColumn =
new QVBoxLayout();
188 traceColumn->setContentsMargins(0, 0, 0, 0);
189 traceColumn->setSpacing(0);
192 traceColumn->addWidget(m_pTimeRuler, 0);
195 m_pRhiView->
setModel(m_pModel.data());
197 m_pRhiView->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
198 m_pRhiView->setFocusPolicy(Qt::ClickFocus);
199 traceColumn->addWidget(m_pRhiView, 1);
201 renderRow->addLayout(traceColumn, 1);
204 auto* rightCol =
new QVBoxLayout();
205 rightCol->setContentsMargins(0, 0, 0, 0);
206 rightCol->setSpacing(0);
210 auto* rulerSpacer =
new QWidget(
this);
212 rulerSpacer->setVisible(
true);
213 rightCol->addWidget(rulerSpacer, 0);
215 m_pChannelScrollBar =
new QScrollBar(Qt::Vertical,
this);
216 m_pChannelScrollBar->setMinimum(0);
217 m_pChannelScrollBar->setMaximum(0);
218 m_pChannelScrollBar->setValue(0);
219 m_pChannelScrollBar->setSingleStep(1);
220 m_pChannelScrollBar->setPageStep(12);
221 m_pChannelScrollBar->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
222 rightCol->addWidget(m_pChannelScrollBar, 1);
224 renderRow->addLayout(rightCol, 0);
226 outerLayout->addLayout(renderRow, 1);
230 m_pOverviewBar->
setModel(m_pModel.data());
231 outerLayout->addWidget(m_pOverviewBar, 0);
236 auto* bottomRow =
new QHBoxLayout();
237 bottomRow->setContentsMargins(0, 0, 0, 0);
238 bottomRow->setSpacing(0);
240 m_pScrollBar =
new QScrollBar(Qt::Horizontal,
this);
241 m_pScrollBar->setMinimum(0);
242 m_pScrollBar->setMaximum(0);
243 m_pScrollBar->setValue(0);
244 m_pScrollBar->setSingleStep(1);
245 m_pScrollBar->setPageStep(100);
246 m_pScrollBar->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
247 bottomRow->addWidget(m_pScrollBar, 1);
249 m_pScrollModeButton =
new QToolButton(
this);
250 m_pScrollModeButton->setCheckable(
true);
251 m_pScrollModeButton->setChecked(
true);
252 m_pScrollModeButton->setText(QStringLiteral(
"\u2195 Ch"));
253 m_pScrollModeButton->setToolTip(QStringLiteral(
254 "Vertical mouse wheel:\n"
255 "\u2195 Ch \u2013 scroll through channels\n"
256 "\u21c4 Time \u2013 scroll through time"));
257 bottomRow->addWidget(m_pScrollModeButton, 0);
259 outerLayout->addLayout(bottomRow, 0);
262 connect(m_pScrollBar, &QScrollBar::valueChanged,
263 this, &ChannelDataView::onScrollBarMoved);
265 connect(m_pChannelScrollBar, &QScrollBar::valueChanged,
266 this, &ChannelDataView::onChannelScrollBarMoved);
269 this, &ChannelDataView::onRhiScrollChanged);
272 this, &ChannelDataView::onChannelOffsetChanged);
280 connect(m_pScrollModeButton, &QToolButton::toggled,
this, [
this](
bool checked) {
283 m_pScrollModeButton->setText(checked ? QStringLiteral(
"\u2195 Ch")
284 : QStringLiteral(
"\u21c4 Time"));
316 this, [
this](
int,
int) { updateSamplesPerPixel(); });
319 this, &ChannelDataView::updateScrollBarRange);
322 this, &ChannelDataView::updateChannelScrollBarRange);
326 m_pLabelPanel, QOverload<>::of(&QWidget::update));
328 m_pLabelPanel, QOverload<>::of(&QWidget::update));
332 this, [
this](
float sample) {
333 if (m_pLabelPanel && m_pRhiView) {
334 m_pLabelPanel->setVisibleSampleRange(
335 static_cast<int>(sample),
336 static_cast<int>(sample) + m_pRhiView->visibleSampleCount());
343 this, [
this](
float sample) {
344 if (m_pOverviewBar && m_pRhiView) {
345 m_pOverviewBar->setViewport(
347 static_cast<float>(m_pRhiView->visibleSampleCount()));
351 this, [
this](
float) {
352 if (m_pOverviewBar && m_pRhiView) {
353 m_pOverviewBar->setViewport(
354 m_pRhiView->scrollSample(),
355 static_cast<float>(m_pRhiView->visibleSampleCount()));
361 if (m_pOverviewBar) {
362 m_pOverviewBar->setModel(m_pModel.data());
367 this, [
this](
float targetSample) {
369 m_pRhiView->scrollTo(targetSample, 150);
372 setFocusProxy(m_pRhiView);
373 setFocusPolicy(Qt::StrongFocus);
381 m_pModel->init(pInfo);
384 if (!m_scaleMap.isEmpty())
385 m_pModel->setScaleMap(m_scaleMap);
386 m_pModel->setSignalColor(m_signalColor);
390 m_pTimeRuler->setSfreq(pInfo->sfreq);
392 m_pRhiView->setSfreq(
static_cast<float>(pInfo->sfreq));
394 m_pOverviewBar->setSfreq(
static_cast<float>(pInfo->sfreq));
398 m_pLabelPanel->setModel(m_pModel.data());
399 m_pLabelPanel->setVisibleChannelCount(m_pRhiView ? m_pRhiView->visibleChannelCount() : 12);
402 updateSamplesPerPixel();
403 updateScrollBarRange();
404 updateChannelScrollBarRange();
411 m_firstFileSample = first;
412 m_lastFileSample = last;
414 m_pRhiView->setFirstFileSample(first);
415 m_pRhiView->setLastFileSample(last);
418 m_pTimeRuler->setFirstFileSample(first);
419 if (m_pOverviewBar) {
420 m_pOverviewBar->setFirstFileSample(first);
421 m_pOverviewBar->setLastFileSample(last);
423 updateScrollBarRange();
430 m_pModel->setData(matData, firstSample);
431 updateScrollBarRange();
438 m_pModel->appendData(matData);
439 updateScrollBarRange();
446 m_pRhiView->scrollTo(
static_cast<float>(sample), animate ? 200 : 0);
453 m_windowSizeSeconds = qMax(seconds, 0.01f);
454 updateSamplesPerPixel();
462 return m_windowSizeSeconds;
469 m_zoomFactor = qMax(factor, 0.001);
470 updateSamplesPerPixel();
487 m_pRhiView->setBackgroundColor(color);
502 m_signalColor = color;
503 m_pModel->setSignalColor(color);
511 return m_signalColor;
518 m_scaleMap = scaleMap;
519 m_pModel->setScaleMap(scaleMap);
533 m_hideBadChannels = hide;
535 m_pRhiView->setHideBadChannels(hide);
537 m_pLabelPanel->setHideBadChannels(hide);
538 updateChannelScrollBarRange();
545 return m_hideBadChannels;
552 QVector<int> indices;
553 if (!names.isEmpty() && m_pModel) {
554 int total = m_pModel->channelCount();
555 for (
int i = 0; i < total; ++i) {
563 m_pRhiView->setChannelIndices(indices);
565 m_pLabelPanel->setChannelIndices(indices);
568 updateChannelScrollBarRange();
575 m_pModel->setRemoveDC(dc);
582 m_pModel->setDetrendMode(mode);
589 return m_pModel->detrendMode();
597 m_pRhiView->setEvents(events);
600 m_pOverviewBar->setEvents(events);
603 QVector<TimeRulerEventMark> rulerMarks;
604 rulerMarks.reserve(events.size());
605 for (
const auto& ev : events)
606 rulerMarks.append({ev.sample, ev.color, ev.label});
607 m_pTimeRuler->setEvents(rulerMarks);
616 m_pRhiView->setEpochMarkers(triggerSamples);
622 m_pRhiView->setEpochMarkersVisible(visible);
627 return m_pRhiView ? m_pRhiView->epochMarkersVisible() :
false;
633 m_pRhiView->setClippingVisible(visible);
638 return m_pRhiView ? m_pRhiView->clippingVisible() :
false;
644 m_pRhiView->setZScoreMode(enabled);
649 return m_pRhiView ? m_pRhiView->zScoreMode() :
false;
657 m_pTimeRuler->setReferenceMarkers(markers);
665 m_pRhiView->setAnnotations(annotations);
667 m_pOverviewBar->setAnnotations(annotations);
675 m_pRhiView->setAnnotationSelectionEnabled(enabled);
683 m_pRhiView->setEventsVisible(visible);
688 return m_pRhiView ? m_pRhiView->eventsVisible() :
true;
696 m_pRhiView->setAnnotationsVisible(visible);
701 return m_pRhiView ? m_pRhiView->annotationsVisible() :
true;
709 m_pOverviewBar->setVisible(visible);
715 return m_pOverviewBar ? !m_pOverviewBar->isHidden() :
true;
723 m_pRhiView->setScrollSpeedFactor(factor);
728 return m_pRhiView ? m_pRhiView->scrollSpeedFactor() : 1.0f;
739 static const QStringList typeOrder = {
740 "MEG grad",
"MEG mag",
"EEG",
"EOG",
"ECG",
"EMG",
"STIM",
"MISC"};
742 const int n = m_pModel->channelCount();
743 QVector<int> indices(n);
744 std::iota(indices.begin(), indices.end(), 0);
746 std::stable_sort(indices.begin(), indices.end(), [&](
int a,
int b) {
747 int ia = typeOrder.indexOf(m_pModel->channelInfo(a).typeLabel);
748 int ib = typeOrder.indexOf(m_pModel->channelInfo(b).typeLabel);
750 ia = typeOrder.size();
752 ib = typeOrder.size();
757 m_pRhiView->setChannelIndices(indices);
759 m_pLabelPanel->setChannelIndices(indices);
760 updateChannelScrollBarRange();
766 m_pRhiView->setChannelIndices({});
768 m_pLabelPanel->setChannelIndices({});
769 updateChannelScrollBarRange();
777 m_pRhiView->setCrosshairEnabled(enabled);
782 return m_pRhiView ? m_pRhiView->crosshairEnabled() :
false;
789 return m_pRhiView ? m_pRhiView->renderToImage(size) : QImage();
797 m_pRhiView->setScalebarsVisible(visible);
802 return m_pRhiView ? m_pRhiView->scalebarsVisible() :
false;
810 m_pRhiView->setButterflyMode(enabled);
812 m_pLabelPanel->setButterflyMode(enabled);
817 return m_pRhiView ? m_pRhiView->butterflyMode() :
false;
825 m_pTimeRuler->toggleTimeFormat();
826 bool useClock = m_pTimeRuler ? m_pTimeRuler->clockTimeFormat() :
false;
828 m_pRhiView->setClockTimeFormat(useClock);
838 m_pRhiView->setClockTimeFormat(useClock);
845 return m_pTimeRuler ? m_pTimeRuler->clockTimeFormat() :
false;
852 return m_pRhiView ? m_pRhiView->visibleFirstSample() : 0;
859 return m_pRhiView ? m_pRhiView->visibleSampleCount() : 0;
866 return m_pRhiView ? m_pRhiView->geometry() : QRect();
876 if (viewportRect.width() <= 0) {
877 return viewportRect.left();
880 const double samplesPerPixel =
static_cast<double>(visibleSamples) /
static_cast<double>(viewportRect.width());
881 const double xOffset =
static_cast<double>(sample -
firstVisibleSample()) / samplesPerPixel;
883 return viewportRect.left() + qBound(0, qRound(xOffset), viewportRect.width() - 1);
893 if (viewportRect.width() <= 0) {
897 const int clampedX = qBound(viewportRect.left(), x, viewportRect.right());
898 const double samplesPerPixel =
static_cast<double>(visibleSamples) /
static_cast<double>(viewportRect.width());
900 return firstVisibleSample() + qRound(
static_cast<double>(clampedX - viewportRect.left()) * samplesPerPixel);
907 if (m_sSettingsPath.isEmpty())
910 s.setValue(m_sSettingsPath +
"/windowSizeSeconds", m_windowSizeSeconds);
911 s.setValue(m_sSettingsPath +
"/zoomFactor", m_zoomFactor);
912 s.setValue(m_sSettingsPath +
"/backgroundColor", m_bgColor);
913 s.setValue(m_sSettingsPath +
"/signalColor", m_signalColor);
920 if (m_sSettingsPath.isEmpty())
923 float rawWindowSec = s.value(m_sSettingsPath +
"/windowSizeSeconds", 10.f).toFloat();
924 m_windowSizeSeconds = qBound(0.5f, rawWindowSec, 120.f);
926 if (rawWindowSec != m_windowSizeSeconds)
927 s.remove(m_sSettingsPath +
"/windowSizeSeconds");
929 m_zoomFactor = s.value(m_sSettingsPath +
"/zoomFactor", 1.0).toDouble();
930 m_bgColor = s.value(m_sSettingsPath +
"/backgroundColor", QColor(250, 250, 250)).value<QColor>();
931 m_signalColor = s.value(m_sSettingsPath +
"/signalColor", QColor(Qt::darkGreen)).value<QColor>();
936 m_pRhiView->setBackgroundColor(m_bgColor);
938 m_pModel->setSignalColor(m_signalColor);
945 m_pModel->clearData();
947 m_pScrollBar->setMaximum(0);
948 m_pScrollBar->setValue(0);
951 m_pRhiView->setScrollSample(0.f);
953 m_pTimeRuler->setFirstFileSample(0);
954 m_pTimeRuler->setScrollSample(0.f);
955 m_pTimeRuler->setReferenceMarkers({});
974 QWidget::keyPressEvent(event);
978 float step = m_pRhiView->visibleSampleCount() * 0.1f;
979 float page = m_pRhiView->visibleSampleCount() * 0.9f;
981 switch (event->key()) {
983 m_pRhiView->scrollBy(-step, 150);
986 m_pRhiView->scrollBy(step, 150);
989 m_pRhiView->scrollBy(-page, 200);
991 case Qt::Key_PageDown:
992 m_pRhiView->scrollBy(page, 200);
995 m_pRhiView->scrollTo(
static_cast<float>(m_pModel->firstSample()), 300);
998 float lastStart =
static_cast<float>(
999 m_pModel->firstSample() + m_pModel->totalSamples() - m_pRhiView->visibleSampleCount());
1000 m_pRhiView->scrollTo(qMax(lastStart, 0.f), 300);
1004 m_pRhiView->zoomTo(m_pRhiView->samplesPerPixel() * 0.75f, 200);
1007 m_pRhiView->zoomTo(m_pRhiView->samplesPerPixel() * 1.33f, 200);
1016 switch (m_pModel->detrendMode()) {
1054 if (event->modifiers() & Qt::ShiftModifier) {
1058 QWidget::keyPressEvent(event);
1066 case Qt::Key_BracketRight:
1070 case Qt::Key_BracketLeft:
1078 QWidget::keyPressEvent(event);
1088 AbstractView::resizeEvent(event);
1089 updateSamplesPerPixel();
1090 updateScrollBarRange();
1095void ChannelDataView::onScrollBarMoved(
int value)
1097 if (m_scrollBarUpdating || !m_pRhiView)
1104void ChannelDataView::onRhiScrollChanged(
float sample)
1111 m_scrollBarUpdating =
true;
1112 m_pScrollBar->setValue(
static_cast<int>(sample));
1113 m_scrollBarUpdating =
false;
1118void ChannelDataView::updateScrollBarRange()
1120 if (!m_pScrollBar || !m_pRhiView)
1123 int visible = m_pRhiView->visibleSampleCount();
1126 if (m_firstFileSample >= 0 && m_lastFileSample >= 0) {
1128 minVal = m_firstFileSample;
1129 maxVal = qMax(m_firstFileSample, m_lastFileSample - visible + 1);
1132 int firstSamp = m_pModel->firstSample();
1133 int total = m_pModel->totalSamples();
1135 maxVal = qMax(firstSamp, firstSamp + total - visible);
1138 m_scrollBarUpdating =
true;
1139 m_pScrollBar->setMinimum(minVal);
1140 m_pScrollBar->setMaximum(maxVal);
1141 m_pScrollBar->setPageStep(visible);
1142 m_scrollBarUpdating =
false;
1147void ChannelDataView::updateSamplesPerPixel()
1149 if (!m_pRhiView || !m_pFiffInfo)
1152 float sfreq =
static_cast<float>(m_pFiffInfo->sfreq);
1153 int viewPx = m_pRhiView->width();
1158 float spp = (m_windowSizeSeconds * sfreq) / viewPx /
static_cast<float>(m_zoomFactor);
1159 m_pRhiView->setSamplesPerPixel(qMax(spp, 1e-4f));
1160 updateScrollBarRange();
1165void ChannelDataView::onChannelScrollBarMoved(
int value)
1167 if (m_channelScrollBarUpdating || !m_pRhiView)
1169 m_pRhiView->setFirstVisibleChannel(value);
1174void ChannelDataView::onChannelOffsetChanged(
int firstChannel)
1176 if (!m_pChannelScrollBar)
1178 m_channelScrollBarUpdating =
true;
1179 m_pChannelScrollBar->setValue(firstChannel);
1180 m_channelScrollBarUpdating =
false;
1185void ChannelDataView::updateChannelScrollBarRange()
1187 if (!m_pChannelScrollBar || !m_pRhiView)
1191 int totalCh = m_pRhiView ? m_pRhiView->totalLogicalChannels()
1192 : m_pModel->channelCount();
1193 int visibleCnt = m_pRhiView->visibleChannelCount();
1194 int maxVal = qMax(0, totalCh - visibleCnt);
1196 m_channelScrollBarUpdating =
true;
1197 m_pChannelScrollBar->setMaximum(maxVal);
1198 m_pChannelScrollBar->setPageStep(visibleCnt);
1199 m_channelScrollBarUpdating =
false;
Full FIFF measurement metadata: everything from FIFFB_MEAS / FIFFB_MEAS_INFO needed to interpret a re...
Horizontal time-axis ruler displayed beneath DISPLIB::ChannelDataView with sample / second ticks.
Circular-buffer Qt model exposing a rolling window of the live FIFF stream as a table.
QRhi-based GPU-accelerated channel time-series renderer used by the modern raw browser.
Vertical column of channel-name labels synced with DISPLIB::ChannelDataView's row geometry.
Composite real-time multi-channel time-series scroller (label panel, table view, time ruler,...
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 setData(const Eigen::MatrixXd &matData, int firstSample=0)
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 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)
QImage renderToImage(const QSize &size=QSize()) const
void setAnnotationSelectionEnabled(bool enabled)
void updateProcessingMode(ProcessingMode mode) override
bool clippingVisible() const
void cursorDataChanged(float timeSec, float amplitude, const QString &channelName, const QString &unitLabel)
QMap< qint32, float > scalingMap() const
void sampleRangeSelected(int startSample, int endSample)
void setEventsVisible(bool visible)
bool eventsVisible() const
bool crosshairEnabled() const
void addData(const Eigen::MatrixXd &matData)
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()