44 #include "../rtfiffrawview.h"
46 #include "../scalingview.h"
54 #include <QPainterPath>
64 using namespace DISPLIB;
71 : QAbstractItemDelegate(parent)
76 , m_iUpperItemIndex(0)
85 for(
int i = 0; i<model->rowCount(); i++)
86 m_painterPaths.append(QPainterPath());
89 QColor colorMarker(233,0,43);
90 colorMarker.setAlpha(160);
92 m_penMarker = QPen(colorMarker, 2, Qt::DashLine);
94 m_penGrid = QPen(Qt::black, 1, Qt::DashLine);
95 m_penTimeSpacers = QPen(Qt::black, 1, Qt::DashLine);
97 m_penFreeze = QPen(Qt::darkGray, 1, Qt::SolidLine);
98 m_penFreezeSelected = QPen(Qt::darkRed, 1, Qt::SolidLine);
100 m_penFreezeBad = QPen(Qt::darkGray, 0.1, Qt::SolidLine);
101 m_penFreezeSelectedBad = QPen(Qt::darkRed, 1, Qt::SolidLine);
103 m_penNormal = QPen(Qt::darkBlue, 1, Qt::SolidLine);
104 m_penNormalSelected = QPen(Qt::red, 1, Qt::SolidLine);
106 m_penNormalBad = QPen(Qt::darkBlue, 0.1, Qt::SolidLine);
107 m_penNormalSelectedBad = QPen(Qt::red, 1, Qt::SolidLine);
112 void createPaths(
const QModelIndex &index,
113 const QStyleOptionViewItem &option,
115 QPainterPath &lastPath,
117 QPointF &markerPosition,
119 const QVector<float> &data,
120 const QVector<float> &lastData)
125 qint32 kind = t_pModel->
getKind(index.row());
130 float dScaleY = option.rect.height()/(2*fMaxValue);
132 float y_base = path.currentPosition().y();
133 QPointF qSamplePosition;
135 float dDx = ((float)option.rect.width()) / t_pModel->
getMaxSamples();
143 float newY = y_base-dValue;
145 qSamplePosition.setY(newY);
146 qSamplePosition.setX(path.currentPosition().x());
148 path.moveTo(qSamplePosition);
153 for(i = 1; i < data.size(); ++i) {
154 float val = data[i] - data[0];
155 dValue = val*dScaleY;
158 float newY = y_base-dValue;
160 qSamplePosition.setY(newY);
161 qSamplePosition.setX(path.currentPosition().x()+dDx);
163 path.lineTo(qSamplePosition);
166 if(i == (qint32)(markerPosition.x()/dDx)) {
167 ellipsePos.setX(path.currentPosition().x()+dDx);
168 ellipsePos.setY(newY+(option.rect.height()/2));
170 amplitude = QString::number(data[i]);
175 qint32 sample_offset = t_pModel->
numVLines() + 1;
176 qSamplePosition.setX(qSamplePosition.x() + dDx*sample_offset);
179 float val = lastData[i] - lastData[0];
180 dValue = val*dScaleY;
181 float newY = y_base-dValue;
182 qSamplePosition.setY(newY);
184 lastPath.moveTo(qSamplePosition);
186 for(i += sample_offset; i < lastData.size(); ++i) {
187 val = lastData[i] - lastData[0];
188 dValue = val*dScaleY;
190 newY = y_base-dValue;
192 qSamplePosition.setY(newY);
193 qSamplePosition.setX(lastPath.currentPosition().x()+dDx);
195 lastPath.lineTo(qSamplePosition);
198 if(i == (qint32)(markerPosition.x()/dDx)) {
199 ellipsePos.setX(lastPath.currentPosition().x()+dDx);
200 ellipsePos.setY(newY+(option.rect.height()/2));
202 amplitude = QString::number(lastData[i]);
210 const QStyleOptionViewItem &option,
211 const QModelIndex &index)
const
213 float t_fPlotHeight = option.rect.height();
214 painter->setRenderHint(QPainter::Antialiasing,
true);
216 switch(index.column()) {
220 painter->rotate(-90);
221 painter->drawText(QRectF(-option.rect.y()-t_fPlotHeight,0,t_fPlotHeight,20),Qt::AlignCenter,index.model()->data(index,Qt::DisplayRole).toString());
228 QBrush backgroundBrush = index.model()->data(index, Qt::BackgroundRole).value<QBrush>();
229 bool bIsBadChannel = index.model()->data(index.model()->index(index.row(), 2), Qt::DisplayRole).toBool();
233 if (index.row() == m_iUpperItemIndex) {
235 painter->setBrushOrigin(option.rect.topLeft());
236 QRect rect = option.rect;
237 rect.setHeight(2000);
238 painter->fillRect(rect, backgroundBrush);
245 QBrush brush(QColor(254,74,93,40));
246 painter->setBrushOrigin(option.rect.topLeft());
247 painter->fillRect(option.rect, brush);
260 QVariant variant = index.model()->data(index,Qt::DisplayRole);
261 RowVectorPair data = variant.value<RowVectorPair>();
265 if(data.second > 0) {
266 QPainterPath path(QPointF(option.rect.x(),option.rect.y()));
277 createGridPath(index, option, path, data);
280 painter->setPen(m_penGrid);
281 painter->drawPath(path);
285 createTimeSpacersPath(index, option, path, data);
288 painter->setPen(m_penTimeSpacers);
289 painter->drawPath(path);
293 path = QPainterPath(QPointF(option.rect.x(),option.rect.y()));
295 createTriggerPath(painter, index, option, path, data);
299 if(index.row() == t_pModel->getCurrentTriggerIndex() &&
300 t_pModel->triggerDetectionActive()) {
301 path = QPainterPath(QPointF(option.rect.x(),option.rect.y()));
302 QPointF textPosition;
303 createTriggerThresholdPath(index, option, path, data, textPosition);
306 painter->setPen(QPen(Qt::red, 1, Qt::DashLine));
307 painter->drawPath(path);
308 painter->drawText(textPosition, QString(
"%1 Threshold").arg(t_pModel->getTriggerName()));
312 path = QPainterPath(QPointF(option.rect.x(),option.rect.y()));
315 createPlotPath(index, option, path, data);
317 painter->setRenderHint(QPainter::Antialiasing,
true);
319 painter->translate(0, t_fPlotHeight/2);
322 if(t_pModel->isFreezed()) {
323 if(option.state & QStyle::State_Selected)
324 painter->setPen(m_penFreezeSelectedBad);
326 painter->setPen(m_penFreezeBad);
328 if(option.state & QStyle::State_Selected)
329 painter->setPen(m_penNormalSelectedBad);
331 painter->setPen(m_penNormalBad);
334 if(t_pModel->isFreezed()) {
335 if(option.state & QStyle::State_Selected)
336 painter->setPen(m_penFreezeSelected);
338 painter->setPen(m_penFreeze);
340 if(option.state & QStyle::State_Selected)
341 painter->setPen(m_penNormalSelected);
343 painter->setPen(m_penNormal);
347 painter->drawPath(path);
351 path = QPainterPath(QPointF(option.rect.x(),option.rect.y()));
352 createCurrentPositionMarkerPath(index, option, path);
355 painter->setPen(m_penMarker);
356 painter->drawPath(path);
359 path = QPainterPath(QPointF(option.rect.x(),option.rect.y()));
360 createMarkerPath(index, option, path);
363 painter->setPen(QPen(Qt::green, 1, Qt::SolidLine));
364 painter->drawPath(path);
375 const QModelIndex &index)
const
377 QSize size = option.rect.size();
379 switch(index.column()) {
381 size = QSize(20,option.rect.height());
384 QList< QVector<float> > data = index.model()->data(index).value< QList<QVector<float> > >();
399 m_markerPosition = position;
400 m_iActiveRow = activeRow;
407 m_penNormal.setColor(signalColor);
408 m_penNormalBad.setColor(signalColor);
415 return m_penNormal.color();
422 m_iUpperItemIndex = iUpperItemIndex;
427 void RtFiffRawViewDelegate::createPlotPath(
const QModelIndex &index,
428 const QStyleOptionViewItem &option,
430 const RowVectorPair &data)
const
433 int iPlotSizePx = option.rect.width();
435 double dPixelsPerSample =
static_cast<double>(iPlotSizePx) /
static_cast<double>(iNumSamples);
443 double dScaleY = option.rect.height()/(2 * dMaxYValueEstimate);
444 double dChannelOffset = path.currentPosition().y();
458 path.moveTo(calcPoint(path, 0., 0., dChannelOffset, dScaleY));
468 for (
int j = 0; j < data.second; ++j) {
470 path.lineTo(calcPoint(path, dPixelsPerSample, dY,
471 dChannelOffset, dScaleY));
477 void RtFiffRawViewDelegate::createCurrentPositionMarkerPath(
const QModelIndex &index,
const QStyleOptionViewItem &option, QPainterPath& path)
const
482 float dDx = ((float)option.rect.width()) / t_pModel->
getMaxSamples();
483 currentSampleIndex = currentSampleIndex*dDx;
485 float yStart = option.rect.topLeft().y();
486 float yEnd = option.rect.bottomRight().y();
488 path.moveTo(currentSampleIndex,yStart);
489 path.lineTo(currentSampleIndex,yEnd);
494 void RtFiffRawViewDelegate::createGridPath(
const QModelIndex &index,
const QStyleOptionViewItem &option, QPainterPath& path, RowVectorPair &data)
const
503 float distance = float (option.rect.width())/(t_pModel->
numVLines()+1);
505 float yStart = option.rect.topLeft().y();
507 float yEnd = option.rect.bottomRight().y();
509 for(qint8 i = 0; i < t_pModel->
numVLines(); ++i) {
510 float x = distance*(i+1);
511 path.moveTo(x,yStart);
519 void RtFiffRawViewDelegate::createTimeSpacersPath(
const QModelIndex &index,
const QStyleOptionViewItem &option, QPainterPath& path, RowVectorPair &data)
const
528 float distanceSec = float (option.rect.width())/(t_pModel->
numVLines()+1);
531 float yStart = option.rect.topLeft().y();
533 float yEnd = option.rect.bottomRight().y();
535 for(qint8 t = 0; t < t_pModel->
numVLines()+1; ++t) {
537 float x = (distanceSec*t)+(distanceSpacers*(i+1));
538 path.moveTo(x,yStart);
547 void RtFiffRawViewDelegate::createTriggerPath(QPainter *painter,
548 const QModelIndex &index,
549 const QStyleOptionViewItem &option,
551 RowVectorPair &data)
const
560 QMap<double, QColor> mapTriggerTypeColors = t_pModel->
getTriggerColor();
562 float yStart = option.rect.topLeft().y();
563 float yEnd = option.rect.bottomRight().y();
564 float dDx = ((float)option.rect.width()) / t_pModel->
getMaxSamples();
569 for(
int u = 0; u < detectedTriggers.size(); ++u) {
572 int triggerPos = detectedTriggers[u].first;
575 if(mapTriggerTypeColors.contains(detectedTriggers[u].second)) {
576 painter->setPen(QPen(mapTriggerTypeColors[detectedTriggers[u].second], 1.5, Qt::SolidLine));
579 if(triggerPos <= currentSampleIndex + t_pModel->getCurrentOverlapAddDelay()) {
580 path.moveTo(triggerPos*dDx,yStart);
581 path.lineTo(triggerPos*dDx,yEnd);
584 painter->drawPath(path);
589 for(
int u = 0; u < detectedTriggersOld.size(); ++u) {
592 int triggerPos = detectedTriggersOld[u].first;
597 if(mapTriggerTypeColors.contains(detectedTriggersOld[u].second)) {
598 painter->setPen(QPen(mapTriggerTypeColors[detectedTriggersOld[u].second], 1.5, Qt::SolidLine));
601 path.moveTo(triggerPos*dDx,yStart);
602 path.lineTo(triggerPos*dDx,yEnd);
604 painter->drawPath(path);
612 void RtFiffRawViewDelegate::createTriggerThresholdPath(
const QModelIndex &index,
613 const QStyleOptionViewItem &option,
616 QPointF &textPosition)
const
623 qint32 kind = t_pModel->
getKind(index.row());
624 double dMaxValue = 1e-9f;
627 case FIFFV_STIM_CH: {
629 if(t_pModel->
getScaling().contains(FIFFV_STIM_CH))
630 dMaxValue = t_pModel->
getScaling()[FIFFV_STIM_CH];
635 double dScaleY = option.rect.height()/(2*dMaxValue);
638 path.moveTo(option.rect.topLeft().x(), option.rect.topLeft().y()+option.rect.height()/2+dScaleY*triggerThreshold);
639 path.lineTo(option.rect.topRight().x(), option.rect.topLeft().y()+option.rect.height()/2+dScaleY*triggerThreshold);
641 textPosition = QPointF(option.rect.topLeft().x()+5, option.rect.topLeft().y()+option.rect.height()/2+dScaleY*triggerThreshold-5);
646 void RtFiffRawViewDelegate::createMarkerPath(
const QModelIndex &index,
647 const QStyleOptionViewItem &option,
648 QPainterPath& path)
const
656 double dDx =
static_cast<double>(option.rect.width()) /
static_cast<double>(iMaxSample);
658 float yStart = option.rect.topLeft().y();
659 float yEnd = option.rect.bottomRight().y();
661 int iEarliestDrawnSample = iOffset - iMaxSample + iTimeCursorSample;
662 int iLatestDrawnSample = iOffset + iTimeCursorSample;
666 for(
auto& e : *events)
668 int iEventSample = e.sample;
669 int iLastStartingSample = iOffset - iMaxSample;
670 int iDrawPositionInSamples = (iEventSample - iLastStartingSample) % iMaxSample;
672 float iPositionInPixels =
static_cast<float>(iDrawPositionInSamples) * dDx;
674 path.moveTo(iPositionInPixels,yStart);
675 path.lineTo(iPositionInPixels,yEnd);
681 QPointF RtFiffRawViewDelegate::calcPoint(QPainterPath& path,
685 const double yScale)
const
687 double x = path.currentPosition().x() + dx;
688 double yScaled = -((yScale * y) - yBase);
693 return QPointF(x, yScaled);