Add more customization support to CANDataGrid. Used that new functionality in Flow View
to allow for bitfield triggers. Click a cell to trigger on it. Now playback will stop if that cell changes state while playing back.
This commit is contained in:
@@ -14,6 +14,9 @@ CANDataGrid::CANDataGrid(QWidget *parent) :
|
||||
memset(data, 0, 8);
|
||||
memset(refData, 0, 8);
|
||||
memset(usedData, 0, 8);
|
||||
for (int x = 0; x < 8; x++)
|
||||
for (int y = 0; y < 8; y++)
|
||||
textStates[x][y] = GridTextState::NORMAL;
|
||||
}
|
||||
|
||||
CANDataGrid::~CANDataGrid()
|
||||
@@ -40,6 +43,25 @@ void CANDataGrid::mousePressEvent(QMouseEvent *event)
|
||||
}
|
||||
}
|
||||
|
||||
void CANDataGrid::setCellTextState(int x, int y, GridTextState state)
|
||||
{
|
||||
if (x < 0) return;
|
||||
if (x > 7) return;
|
||||
if (y < 0) return;
|
||||
if (y > 7) return;
|
||||
textStates[x][y] = state;
|
||||
this->update();
|
||||
}
|
||||
|
||||
GridTextState CANDataGrid::geCellTextState(int x, int y)
|
||||
{
|
||||
if (x < 0) return GridTextState::NORMAL;
|
||||
if (x > 7) return GridTextState::NORMAL;
|
||||
if (y < 0) return GridTextState::NORMAL;
|
||||
if (y > 7) return GridTextState::NORMAL;
|
||||
return textStates[x][y];
|
||||
}
|
||||
|
||||
void CANDataGrid::paintEvent(QPaintEvent *event)
|
||||
{
|
||||
Q_UNUSED(event);
|
||||
@@ -50,6 +72,7 @@ void CANDataGrid::paintEvent(QPaintEvent *event)
|
||||
QBrush blackBrush, whiteBrush, redBrush, greenBrush, grayBrush;
|
||||
QPainter painter(this);
|
||||
|
||||
|
||||
QRect viewport = painter.viewport();
|
||||
|
||||
int xSpan = viewport.right() - viewport.left();
|
||||
@@ -79,6 +102,9 @@ void CANDataGrid::paintEvent(QPaintEvent *event)
|
||||
painter.setFont(mainFont);
|
||||
QFont smallFont;
|
||||
smallFont.setPixelSize(qMin(xSector, ySector) - 15);
|
||||
QFont boldFont;
|
||||
boldFont.setPixelSize(qMin(xSector, ySector) - 10);
|
||||
boldFont.setBold(true);
|
||||
|
||||
painter.drawText(QRect(viewport.left(), viewport.top(), xSpan, ySector), Qt::AlignCenter, tr("BITS"));
|
||||
|
||||
@@ -142,7 +168,25 @@ void CANDataGrid::paintEvent(QPaintEvent *event)
|
||||
|
||||
//painter.fillRect(viewport.left() + (x+2) * xSector, viewport.top() + (y+2) * ySector, xSector, ySector, redBrush);
|
||||
painter.drawRect(viewport.left() + (x+2) * xSector, viewport.top() + (y+2) * ySector, xSector, ySector);
|
||||
switch (textStates[x][y])
|
||||
{
|
||||
case GridTextState::NORMAL:
|
||||
painter.setPen(QPen(Qt::gray));
|
||||
painter.setFont(mainFont);
|
||||
break;
|
||||
case GridTextState::BOLD_BLUE:
|
||||
painter.setPen(QPen(Qt::blue));
|
||||
painter.setFont(boldFont);
|
||||
break;
|
||||
case GridTextState::INVERT:
|
||||
painter.setFont(mainFont);
|
||||
QColor brushColor = painter.brush().color();
|
||||
painter.setPen(QColor(255-brushColor.red(), 255-brushColor.green(), 255-brushColor.blue()));
|
||||
break;
|
||||
}
|
||||
|
||||
painter.drawText(viewport.left() + (x+2) * xSector + (xSector / 8), viewport.top() + (y + 3) * ySector - (ySector / 3), QString::number(y * 8 + (7-x)));
|
||||
painter.setPen(QPen(Qt::gray));
|
||||
}
|
||||
}
|
||||
upperLeft.setX(viewport.left() + 2 * xSector);
|
||||
|
||||
@@ -7,6 +7,27 @@ namespace Ui {
|
||||
class CANDataGrid;
|
||||
}
|
||||
|
||||
/*
|
||||
* CANDataGrid is a custom QT widget that proves that it's possible to shoehorn 12x too much crap into one widget. The purported
|
||||
* goal of the widget was to show an 8x8 grid of bits that show whether each bit in a given message is set or not. It allows one to quickly
|
||||
* visualize the bits within a CAN frame's data bytes. From there it evolved to also show whether a given bit was freshly set recently, freshly
|
||||
* unset recently, or has stayed set or unset for a while. It can also gray out bytes that don't exist in the current CAN frame.
|
||||
* This is handled by the calling code.
|
||||
*
|
||||
* After that functionality was added so it could also emit a signal when it is clicked. The signal will tell you which "bit" cell was clicked.
|
||||
*
|
||||
* Then, support was added for modifying the text color of each cell. This can be used for whatever the calling code wants. An example is
|
||||
* FlowView that uses all of the above functionality plus this functionality in order to show which bits are set as triggers for stopping
|
||||
* the flowview playback.
|
||||
*/
|
||||
|
||||
enum GridTextState
|
||||
{
|
||||
NORMAL,
|
||||
BOLD_BLUE,
|
||||
INVERT
|
||||
};
|
||||
|
||||
class CANDataGrid : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
@@ -19,6 +40,8 @@ public:
|
||||
void updateData(unsigned char *, bool);
|
||||
void setUsed(unsigned char *, bool);
|
||||
void saveImage(QString filename, int width, int height);
|
||||
void setCellTextState(int x, int y, GridTextState state);
|
||||
GridTextState geCellTextState(int x, int y);
|
||||
|
||||
protected:
|
||||
void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
|
||||
@@ -31,6 +54,7 @@ private:
|
||||
unsigned char refData[8];
|
||||
unsigned char data[8];
|
||||
unsigned char usedData[8];
|
||||
GridTextState textStates[8][8];
|
||||
QPoint upperLeft, gridSize;
|
||||
};
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ FlowViewWindow::FlowViewWindow(const QVector<CANFrame> *frames, QWidget *parent)
|
||||
memset(refBytes, 0, 8);
|
||||
memset(currBytes, 0, 8);
|
||||
memset(triggerValues, -1, sizeof(int) * 8);
|
||||
triggerBits = 0;
|
||||
|
||||
//ui->graphView->setInteractions();
|
||||
|
||||
@@ -102,6 +103,7 @@ FlowViewWindow::FlowViewWindow(const QVector<CANFrame> *frames, QWidget *parent)
|
||||
connect(ui->graphView, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextMenuRequestGraph(QPoint)));
|
||||
ui->flowView->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(ui->flowView, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(contextMenuRequestFlow(QPoint)));
|
||||
connect(ui->flowView, SIGNAL(gridClicked(int,int)), this, SLOT(gotCellClick(int, int)));
|
||||
|
||||
playbackTimer->setInterval(ui->spinPlayback->value()); //set the timer to the default value of the control
|
||||
}
|
||||
@@ -207,6 +209,15 @@ bool FlowViewWindow::eventFilter(QObject *obj, QEvent *event)
|
||||
}
|
||||
}
|
||||
|
||||
void FlowViewWindow::gotCellClick(int x, int y)
|
||||
{
|
||||
int bitnum = (7-x) + (8 * y);
|
||||
triggerBits = triggerBits ^ (1ull << bitnum);
|
||||
if (triggerBits & (1ull << bitnum)) ui->flowView->setCellTextState(x, y, GridTextState::BOLD_BLUE);
|
||||
else ui->flowView->setCellTextState(x, y, GridTextState::NORMAL);
|
||||
qDebug() << "Bit Num: " << bitnum << " Hex of trigger bits: " << QString::number(triggerBits, 16);
|
||||
}
|
||||
|
||||
void FlowViewWindow::updateTriggerValues()
|
||||
{
|
||||
triggerValues[0] = Utility::ParseStringToNum(ui->txtTrigger0->text());
|
||||
@@ -725,6 +736,26 @@ void FlowViewWindow::updatePosition(bool forward)
|
||||
memcpy(refBytes, currBytes, 8);
|
||||
}
|
||||
|
||||
//figure out which bits changed since the previous frame and then AND that with the trigger bits. If any bits
|
||||
//get through that then they're changed and a trigger so we stop playback at this frame.
|
||||
uint64_t changedBits = 0;
|
||||
uint8_t cngByte;
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
cngByte = currBytes[i] ^ frameCache.at(currentPosition).data[i];
|
||||
changedBits |= (uint64_t)cngByte << (8ull * i);
|
||||
}
|
||||
|
||||
qDebug() << "ChangedBits: " << QString::number(changedBits, 16);
|
||||
qDebug() << "TriggerBits: " << QString::number(triggerBits, 16);
|
||||
changedBits &= triggerBits;
|
||||
qDebug() << "Final ChangedBits: " << QString::number(changedBits, 16);
|
||||
if (changedBits)
|
||||
{
|
||||
playbackActive = false;
|
||||
playbackTimer->stop();
|
||||
}
|
||||
|
||||
memcpy(currBytes, frameCache.at(currentPosition).data, 8);
|
||||
|
||||
if (ui->cbSync->checkState() == Qt::Checked) emit sendCenterTimeID(frameCache[currentPosition].ID, frameCache[currentPosition].timestamp / 1000000.0);
|
||||
|
||||
@@ -37,6 +37,7 @@ private slots:
|
||||
void plottableDoubleClick(QCPAbstractPlottable* plottable, QMouseEvent* event);
|
||||
void gotCenterTimeID(int32_t ID, double timestamp);
|
||||
void updateTriggerValues();
|
||||
void gotCellClick(int x, int y);
|
||||
|
||||
signals:
|
||||
void sendCenterTimeID(int32_t ID, double timestamp);
|
||||
@@ -49,6 +50,7 @@ private:
|
||||
unsigned char refBytes[8];
|
||||
unsigned char currBytes[8];
|
||||
int triggerValues[8];
|
||||
uint64_t triggerBits;
|
||||
int currentPosition;
|
||||
QTimer *playbackTimer;
|
||||
bool playbackActive;
|
||||
|
||||
Reference in New Issue
Block a user