44 #include "../rtfiffrawview.h" 46 #include "../scalingview.h" 54 #include <QPainterPath> 71 : QAbstractItemDelegate(parent)
76 , m_iUpperItemIndex(0)
84 for(
int i = 0; i<model->rowCount(); i++)
85 m_painterPaths.append(QPainterPath());
88 QColor colorMarker(233,0,43);
89 colorMarker.setAlpha(160);
91 m_penMarker = QPen(colorMarker, 2, Qt::DashLine);
93 m_penGrid = QPen(Qt::black, 1, Qt::DashLine);
94 m_penTimeSpacers = QPen(Qt::black, 1, Qt::DashLine);
96 m_penFreeze = QPen(Qt::darkGray, 1, Qt::SolidLine);
97 m_penFreezeSelected = QPen(Qt::darkRed, 1, Qt::SolidLine);
99 m_penFreezeBad = QPen(Qt::darkGray, 0.1, Qt::SolidLine);
100 m_penFreezeSelectedBad = QPen(Qt::darkRed, 1, Qt::SolidLine);
102 m_penNormal = QPen(Qt::darkBlue, 1, Qt::SolidLine);
103 m_penNormalSelected = QPen(Qt::red, 1, Qt::SolidLine);
105 m_penNormalBad = QPen(Qt::darkBlue, 0.1, Qt::SolidLine);
106 m_penNormalSelectedBad = QPen(Qt::red, 1, Qt::SolidLine);
111 void createPaths(
const QModelIndex &index,
112 const QStyleOptionViewItem &option,
114 QPainterPath &lastPath,
116 QPointF &markerPosition,
118 const QVector<float> &data,
119 const QVector<float> &lastData)
124 qint32 kind = t_pModel->
getKind(index.row());
129 float dScaleY = option.rect.height()/(2*fMaxValue);
131 float y_base = path.currentPosition().y();
132 QPointF qSamplePosition;
134 float dDx = ((float)option.rect.width()) / t_pModel->
getMaxSamples();
142 float newY = y_base-dValue;
144 qSamplePosition.setY(newY);
145 qSamplePosition.setX(path.currentPosition().x());
147 path.moveTo(qSamplePosition);
152 for(i = 1; i < data.size(); ++i) {
153 float val = data[i] - data[0];
154 dValue = val*dScaleY;
157 float newY = y_base-dValue;
159 qSamplePosition.setY(newY);
160 qSamplePosition.setX(path.currentPosition().x()+dDx);
162 path.lineTo(qSamplePosition);
165 if(i == (qint32)(markerPosition.x()/dDx)) {
166 ellipsePos.setX(path.currentPosition().x()+dDx);
167 ellipsePos.setY(newY+(option.rect.height()/2));
169 amplitude = QString::number(data[i]);
174 qint32 sample_offset = t_pModel->
numVLines() + 1;
175 qSamplePosition.setX(qSamplePosition.x() + dDx*sample_offset);
178 float val = lastData[i] - lastData[0];
179 dValue = val*dScaleY;
180 float newY = y_base-dValue;
181 qSamplePosition.setY(newY);
183 lastPath.moveTo(qSamplePosition);
185 for(i += sample_offset; i < lastData.size(); ++i) {
186 val = lastData[i] - lastData[0];
187 dValue = val*dScaleY;
189 newY = y_base-dValue;
191 qSamplePosition.setY(newY);
192 qSamplePosition.setX(lastPath.currentPosition().x()+dDx);
194 lastPath.lineTo(qSamplePosition);
197 if(i == (qint32)(markerPosition.x()/dDx)) {
198 ellipsePos.setX(lastPath.currentPosition().x()+dDx);
199 ellipsePos.setY(newY+(option.rect.height()/2));
201 amplitude = QString::number(lastData[i]);
209 const QStyleOptionViewItem &option,
210 const QModelIndex &index)
const 212 float t_fPlotHeight = option.rect.height();
213 painter->setRenderHint(QPainter::Antialiasing,
true);
215 switch(index.column()) {
219 painter->rotate(-90);
220 painter->drawText(QRectF(-option.rect.y()-t_fPlotHeight,0,t_fPlotHeight,20),Qt::AlignCenter,index.model()->data(index,Qt::DisplayRole).toString());
227 QBrush backgroundBrush = index.model()->data(index, Qt::BackgroundRole).value<QBrush>();
228 bool bIsBadChannel = index.model()->data(index.model()->index(index.row(), 2), Qt::DisplayRole).toBool();
232 if (index.row() == m_iUpperItemIndex) {
234 painter->setBrushOrigin(option.rect.topLeft());
235 QRect rect = option.rect;
236 rect.setHeight(2000);
237 painter->fillRect(rect, backgroundBrush);
244 QBrush brush(QColor(254,74,93,40));
245 painter->setBrushOrigin(option.rect.topLeft());
246 painter->fillRect(option.rect, brush);
259 QVariant variant = index.model()->data(index,Qt::DisplayRole);
260 RowVectorPair data = variant.value<RowVectorPair>();
264 if(data.second > 0) {
265 QPainterPath path(QPointF(option.rect.x(),option.rect.y()));
276 createGridPath(index, option, path, data);
279 painter->setPen(m_penGrid);
280 painter->drawPath(path);
284 createTimeSpacersPath(index, option, path, data);
287 painter->setPen(m_penTimeSpacers);
288 painter->drawPath(path);
292 path = QPainterPath(QPointF(option.rect.x(),option.rect.y()));
294 createTriggerPath(painter, index, option, path, data);
298 if(index.row() == t_pModel->getCurrentTriggerIndex() &&
299 t_pModel->triggerDetectionActive()) {
300 path = QPainterPath(QPointF(option.rect.x(),option.rect.y()));
301 QPointF textPosition;
302 createTriggerThresholdPath(index, option, path, data, textPosition);
305 painter->setPen(QPen(Qt::red, 1, Qt::DashLine));
306 painter->drawPath(path);
307 painter->drawText(textPosition, QString(
"%1 Threshold").arg(t_pModel->getTriggerName()));
311 path = QPainterPath(QPointF(option.rect.x(),option.rect.y()));
314 createPlotPath(index, option, path, data);
316 painter->setRenderHint(QPainter::Antialiasing,
true);
318 painter->translate(0, t_fPlotHeight/2);
321 if(t_pModel->isFreezed()) {
322 if(option.state & QStyle::State_Selected)
323 painter->setPen(m_penFreezeSelectedBad);
325 painter->setPen(m_penFreezeBad);
327 if(option.state & QStyle::State_Selected)
328 painter->setPen(m_penNormalSelectedBad);
330 painter->setPen(m_penNormalBad);
333 if(t_pModel->isFreezed()) {
334 if(option.state & QStyle::State_Selected)
335 painter->setPen(m_penFreezeSelected);
337 painter->setPen(m_penFreeze);
339 if(option.state & QStyle::State_Selected)
340 painter->setPen(m_penNormalSelected);
342 painter->setPen(m_penNormal);
346 painter->drawPath(path);
350 path = QPainterPath(QPointF(option.rect.x(),option.rect.y()));
351 createCurrentPositionMarkerPath(index, option, path);
354 painter->setPen(m_penMarker);
355 painter->drawPath(path);
358 path = QPainterPath(QPointF(option.rect.x(),option.rect.y()));
359 createMarkerPath(index, option, path);
362 painter->setPen(QPen(Qt::green, 1, Qt::SolidLine));
363 painter->drawPath(path);
374 const QModelIndex &index)
const 376 QSize size = option.rect.size();
378 switch(index.column()) {
380 size = QSize(20,option.rect.height());
383 QList< QVector<float> > data = index.model()->data(index).value< QList<QVector<float> > >();
398 m_markerPosition = position;
399 m_iActiveRow = activeRow;
406 m_penNormal.setColor(signalColor);
407 m_penNormalBad.setColor(signalColor);
414 return m_penNormal.color();
421 m_iUpperItemIndex = iUpperItemIndex;
426 void RtFiffRawViewDelegate::createPlotPath(
const QModelIndex &index,
427 const QStyleOptionViewItem &option,
429 const RowVectorPair &data)
const 432 int iPlotSizePx = option.rect.width();
434 double dPixelsPerSample =
static_cast<double>(iPlotSizePx) / static_cast<double>(iNumSamples);
442 double dScaleY = option.rect.height()/(2 * dMaxYValueEstimate);
443 double dChannelOffset = path.currentPosition().y();
457 path.moveTo(calcPoint(path, 0., 0., dChannelOffset, dScaleY));
465 for(
int j = 0; j < data.second; ++j) {
466 if(j < iTimeCursorSample) {
468 dY = data.first[j] - data.first[0];
471 dY = data.first[j] - firstValuePreviousPlot;
473 path.lineTo(calcPoint(path, dPixelsPerSample, dY, dChannelOffset, dScaleY));
479 void RtFiffRawViewDelegate::createCurrentPositionMarkerPath(
const QModelIndex &index,
const QStyleOptionViewItem &option, QPainterPath& path)
const 484 float dDx = ((float)option.rect.width()) / t_pModel->
getMaxSamples();
485 currentSampleIndex = currentSampleIndex*dDx;
487 float yStart = option.rect.topLeft().y();
488 float yEnd = option.rect.bottomRight().y();
490 path.moveTo(currentSampleIndex,yStart);
491 path.lineTo(currentSampleIndex,yEnd);
496 void RtFiffRawViewDelegate::createGridPath(
const QModelIndex &index,
const QStyleOptionViewItem &option, QPainterPath& path, RowVectorPair &data)
const 505 float distance = float (option.rect.width())/(t_pModel->
numVLines()+1);
507 float yStart = option.rect.topLeft().y();
509 float yEnd = option.rect.bottomRight().y();
511 for(qint8 i = 0; i < t_pModel->
numVLines(); ++i) {
512 float x = distance*(i+1);
513 path.moveTo(x,yStart);
521 void RtFiffRawViewDelegate::createTimeSpacersPath(
const QModelIndex &index,
const QStyleOptionViewItem &option, QPainterPath& path, RowVectorPair &data)
const 530 float distanceSec = float (option.rect.width())/(t_pModel->
numVLines()+1);
533 float yStart = option.rect.topLeft().y();
535 float yEnd = option.rect.bottomRight().y();
537 for(qint8 t = 0; t < t_pModel->
numVLines()+1; ++t) {
539 float x = (distanceSec*t)+(distanceSpacers*(i+1));
540 path.moveTo(x,yStart);
549 void RtFiffRawViewDelegate::createTriggerPath(QPainter *painter,
550 const QModelIndex &index,
551 const QStyleOptionViewItem &option,
553 RowVectorPair &data)
const 562 QMap<double, QColor> mapTriggerTypeColors = t_pModel->
getTriggerColor();
564 float yStart = option.rect.topLeft().y();
565 float yEnd = option.rect.bottomRight().y();
566 float dDx = ((float)option.rect.width()) / t_pModel->
getMaxSamples();
571 for(
int u = 0; u < detectedTriggers.size(); ++u) {
574 int triggerPos = detectedTriggers[u].first;
577 if(mapTriggerTypeColors.contains(detectedTriggers[u].second)) {
578 painter->setPen(QPen(mapTriggerTypeColors[detectedTriggers[u].second], 1.5, Qt::SolidLine));
581 if(triggerPos <= currentSampleIndex + t_pModel->getCurrentOverlapAddDelay()) {
582 path.moveTo(triggerPos*dDx,yStart);
583 path.lineTo(triggerPos*dDx,yEnd);
586 painter->drawPath(path);
591 for(
int u = 0; u < detectedTriggersOld.size(); ++u) {
594 int triggerPos = detectedTriggersOld[u].first;
599 if(mapTriggerTypeColors.contains(detectedTriggersOld[u].second)) {
600 painter->setPen(QPen(mapTriggerTypeColors[detectedTriggersOld[u].second], 1.5, Qt::SolidLine));
603 path.moveTo(triggerPos*dDx,yStart);
604 path.lineTo(triggerPos*dDx,yEnd);
606 painter->drawPath(path);
614 void RtFiffRawViewDelegate::createTriggerThresholdPath(
const QModelIndex &index,
615 const QStyleOptionViewItem &option,
618 QPointF &textPosition)
const 625 qint32 kind = t_pModel->
getKind(index.row());
626 double dMaxValue = 1e-9f;
629 case FIFFV_STIM_CH: {
631 if(t_pModel->
getScaling().contains(FIFFV_STIM_CH))
632 dMaxValue = t_pModel->
getScaling()[FIFFV_STIM_CH];
637 double dScaleY = option.rect.height()/(2*dMaxValue);
640 path.moveTo(option.rect.topLeft().x(), option.rect.topLeft().y()+option.rect.height()/2+dScaleY*triggerThreshold);
641 path.lineTo(option.rect.topRight().x(), option.rect.topLeft().y()+option.rect.height()/2+dScaleY*triggerThreshold);
643 textPosition = QPointF(option.rect.topLeft().x()+5, option.rect.topLeft().y()+option.rect.height()/2+dScaleY*triggerThreshold-5);
648 void RtFiffRawViewDelegate::createMarkerPath(
const QModelIndex &index,
649 const QStyleOptionViewItem &option,
650 QPainterPath& path)
const 658 double dDx =
static_cast<double>(option.rect.width()) / static_cast<double>(iMaxSample);
660 float yStart = option.rect.topLeft().y();
661 float yEnd = option.rect.bottomRight().y();
663 int iEarliestDrawnSample = iOffset - iMaxSample + iTimeCursorSample;
664 int iLatestDrawnSample = iOffset + iTimeCursorSample;
668 for(
auto& e : *events)
670 int iEventSample = e.sample;
671 int iLastStartingSample = iOffset - iMaxSample;
672 int iDrawPositionInSamples = (iEventSample - iLastStartingSample) % iMaxSample;
674 float iPositionInPixels =
static_cast<float>(iDrawPositionInSamples) * dDx;
676 path.moveTo(iPositionInPixels,yStart);
677 path.lineTo(iPositionInPixels,yEnd);
683 QPointF RtFiffRawViewDelegate::calcPoint(QPainterPath& path,
687 const double yScale)
const 689 double x = path.currentPosition().x() + dx;
690 double yScaled = -((yScale * y) - yBase);
695 return QPointF(x, yScaled);
int getCurrentOverlapAddDelay() const
std::unique_ptr< std::vector< EVENTSLIB::Event > > getEventsToDisplay(int iBegin, int iEnd) const
qint32 getCurrentSampleIndex() const
RtFiffRawViewDelegate(RtFiffRawView *parent=0)
DISPSHARED_EXPORT float getScalingValue(const QMap< qint32, float > &qMapChScaling, int iChannelKind, int iChannelUnit)
QList< QPair< int, double > > getDetectedTriggers() const
QList< QPair< int, double > > getDetectedTriggersOld() const
qint32 getMaxSamples() const
const QMap< qint32, float > & getScaling() const
int getNumberOfTimeSpacers() const
void setUpperItemIndex(int iUpperItemIndex)
FIFFLIB::fiff_int_t getKind(qint32 row) const
Declaration of the RtFiffRawViewModel Class.
void initPainterPaths(const QAbstractTableModel *model)
virtual QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
The RtFiffRawViewModel class implements the data access model for a real-time multi sample array data...
The RtFiffRawView class provides a real-time channel view display.
void setSignalColor(const QColor &signalColor)
FIFFLIB::fiff_int_t getUnit(qint32 row) const
QMap< double, QColor > getTriggerColor() const
virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
double getMaxValueFromRawViewModel(int row) const
Declaration of the RtFiffRawViewDelegate Class.
void markerMoved(QPoint position, int activeRow)
int getFirstSampleOffset() const
double getTriggerThreshold() const
double getLastBlockFirstValue(int row) const