1 #include "candatagrid.h"
2 #include "ui_candatagrid.h"
3 
4 #include <QPainter>
5 #include <QDebug>
6 #include <QMouseEvent>
7 
CANDataGrid(QWidget * parent)8 CANDataGrid::CANDataGrid(QWidget *parent) :
9     QWidget(parent),
10     ui(new Ui::CANDataGrid)
11 {
12     ui->setupUi(this);
13 
14     memset(data, 0, 8);
15     memset(refData, 0, 8);
16     memset(usedData, 0, 8);
17     memset(usedSignalNum, 0, 64);
18     for (int x = 0; x < 8; x++)
19         for (int y = 0; y < 8; y++)
20             textStates[x][y] = GridTextState::NORMAL;
21 }
22 
~CANDataGrid()23 CANDataGrid::~CANDataGrid()
24 {
25     delete ui;
26 }
27 
mousePressEvent(QMouseEvent * event)28 void CANDataGrid::mousePressEvent(QMouseEvent *event)
29 {
30     QPoint clickedPoint = event->pos();
31     if (event->button() == Qt::LeftButton)
32     {
33         //qDebug() << "Mouse Loc " << clickedPoint;
34         clickedPoint -= upperLeft;
35         if (clickedPoint.x() < 0 || clickedPoint.y() < 0)
36         {
37             //qDebug() << "Clicked outside the grid you wanker";
38             return;
39         }
40         int x = clickedPoint.x() / gridSize.x();
41         int y = clickedPoint.y() / gridSize.y();
42         //qDebug() << "Grid square clicked " << x << " " << y;
43         emit gridClicked(x,y);
44     }
45 }
46 
setCellTextState(int x,int y,GridTextState state)47 void CANDataGrid::setCellTextState(int x, int y, GridTextState state)
48 {
49     if (x < 0) return;
50     if (x > 7) return;
51     if (y < 0) return;
52     if (y > 7) return;
53     textStates[x][y] = state;
54     this->update();
55 }
56 
getCellTextState(int x,int y)57 GridTextState CANDataGrid::getCellTextState(int x, int y)
58 {
59     if (x < 0) return GridTextState::NORMAL;
60     if (x > 7) return GridTextState::NORMAL;
61     if (y < 0) return GridTextState::NORMAL;
62     if (y > 7) return GridTextState::NORMAL;
63     return textStates[x][y];
64 }
65 
setUsedSignalNum(int bit,unsigned char signal)66 void CANDataGrid::setUsedSignalNum(int bit, unsigned char signal)
67 {
68     if (bit < 0) return;
69     if (bit > 63) return;
70     usedSignalNum[bit] = signal;
71 }
72 
getUsedSignalNum(int bit)73 unsigned char CANDataGrid::getUsedSignalNum(int bit)
74 {
75     if (bit < 0) return 0;
76     if (bit > 63) return 0;
77     return usedSignalNum[bit];
78 }
79 
80 
paintEvent(QPaintEvent * event)81 void CANDataGrid::paintEvent(QPaintEvent *event)
82 {
83     Q_UNUSED(event);
84     qDebug() << "CANDataGrid Paint Event";
85     int x, y;
86     unsigned char prevByte, thisByte;
87     bool thisBit, prevBit;
88     QBrush blackBrush, whiteBrush, redBrush, greenBrush, grayBrush;
89     QPainter painter(this);
90 
91 
92     QRect viewport = painter.viewport();
93 
94     int xSpan = viewport.right() - viewport.left();
95     int ySpan = viewport.bottom() - viewport.top();
96 
97     qDebug() << "XSpan" << xSpan << " YSpan " << ySpan;
98 
99     int xSector = xSpan / 10;
100     int ySector = ySpan / 10;
101 
102     blackBrush = QBrush(Qt::black);
103     whiteBrush = QBrush(Qt::white);
104     redBrush = QBrush(Qt::red);
105     greenBrush = QBrush(Qt::green);
106     grayBrush = QBrush(QColor(230,230,230));
107 
108     //the whole thing is broken up into 100 chunks which are allocated as such:
109     //The entirety of the upper row is taken up by "BITS"
110     //The next row down skips two columns and then has 7 6 5 4 3 2 1 0
111     //The bottom right 64 entries are the grid
112     //The left most column has "BYTES" written vertically down it
113     //the next left most column has "0 1 2 3 4 5 6 7" written down along the grid
114 
115     painter.setPen(QPen(QApplication::palette().color(QPalette::Text)));
116     QFont mainFont;
117     mainFont.setPixelSize(qMin(xSector, ySector) - 10);
118     painter.setFont(mainFont);
119     QFont smallFont;
120     smallFont.setPixelSize(qMin(xSector, ySector) - 15);
121     QFont boldFont;
122     boldFont.setPixelSize(qMin(xSector, ySector) - 10);
123     boldFont.setBold(true);
124 
125     painter.drawText(QRect(viewport.left(), viewport.top(), xSpan, ySector), Qt::AlignCenter, tr("BITS"));
126 
127     for (x = 0; x < 8; x++)
128     {
129         painter.drawText(QRect(viewport.left() + (x+2) * xSector, viewport.top() + ySector, xSector, ySector), Qt::AlignCenter, QString::number(7-x));
130     }
131     for (y = 0; y < 8; y++)
132     {
133         painter.drawText(QRect(viewport.left() + xSector, viewport.top() + ySector * (y + 2), xSector, ySector), Qt::AlignCenter, QString::number(y));
134     }
135 
136     painter.drawText(viewport.left() + 10, viewport.top() + ySector * 4, "B");
137     painter.drawText(viewport.left() + 10, viewport.top() + ySector * 5, "Y");
138     painter.drawText(viewport.left() + 10, viewport.top() + ySector * 6, "T");
139     painter.drawText(viewport.left() + 10, viewport.top() + ySector * 7, "E");
140     painter.drawText(viewport.left() + 10, viewport.top() + ySector * 8, "S");
141 
142     //now, color the bitfield by seeing if a given bit is freshly set/unset in the new data
143     //compared to the old. Bits that are not set in either are white, bits set in both are black
144     //bits that used to be set but now are unset are red, bits that used to be unset but now are set
145     //are green
146 
147     painter.setPen(QPen(Qt::gray));
148     //painter.setFont(smallFont);
149 
150     for (y = 0; y < 8; y++)
151     {
152         thisByte = data[y];
153         prevByte = refData[y];
154         for (x = 0; x < 8; x++)
155         {
156             thisBit = false;
157             prevBit = false;
158             if ((thisByte & (1 << (7-x))) == (1 << (7-x))) thisBit = true;
159             if ((prevByte & (1 << (7-x))) == (1 << (7-x))) prevBit = true;
160 
161             if (thisBit)
162             {
163                 if (prevBit)
164                 {
165                     painter.setBrush(blackBrush);
166                 }
167                 else
168                 {
169                     painter.setBrush(greenBrush);
170                 }
171             }
172             else
173             {
174                 if (prevBit)
175                 {
176                     painter.setBrush(redBrush);
177                 }
178                 else
179                 {
180                     if ((usedData[y] & (1 << (7-x))) == (1 << (7-x)))
181                     {
182                         grayBrush = QBrush(QColor(0xB6, 0xB6, 0xB6), Qt::BDiagPattern);
183                         painter.setBrush(grayBrush);
184                     }
185                     else painter.setBrush(whiteBrush);
186                 }
187             }
188 
189             //painter.fillRect(viewport.left() + (x+2) * xSector, viewport.top() + (y+2) * ySector, xSector, ySector, redBrush);
190             painter.drawRect(viewport.left() + (x+2) * xSector, viewport.top() + (y+2) * ySector, xSector, ySector);
191             switch (textStates[x][y])
192             {
193             case GridTextState::NORMAL:
194                 painter.setPen(QPen(Qt::gray));
195                 painter.setFont(mainFont);
196                 break;
197             case GridTextState::BOLD_BLUE:
198                 painter.setPen(QPen(Qt::blue));
199                 painter.setFont(boldFont);
200                 break;
201             case GridTextState::INVERT:
202                 painter.setFont(mainFont);
203                 QColor brushColor = painter.brush().color();
204                 painter.setPen(QColor(255-brushColor.red(), 255-brushColor.green(), 255-brushColor.blue()));
205                 break;
206             }
207 
208             painter.drawText(viewport.left() + (x+2) * xSector + (xSector / 8), viewport.top() + (y + 3) * ySector - (ySector / 3), QString::number(y * 8 + (7-x)));
209             painter.setPen(QPen(Qt::gray));
210         }
211     }
212     upperLeft.setX(viewport.left() + 2 * xSector);
213     upperLeft.setY(viewport.top() + 2 * ySector);
214     gridSize.setX(xSector);
215     gridSize.setY(ySector);
216 }
217 
saveImage(QString filename,int width,int height)218 void CANDataGrid::saveImage(QString filename, int width, int height)
219 {
220     Q_UNUSED(width); //currently unused but I want to use them in the future
221     Q_UNUSED(height);
222     //can't quite do the below commented out stuff
223     //it works but doesn't scale the image into that pixmap. Need to
224     //figure out how to draw the size of the pixmap
225     /*
226     QSize pSize;
227 
228     if (width == 0) pSize.setWidth(this->size().width());
229         else pSize.setWidth(width);
230 
231     if (height == 0) pSize.setHeight(this->size().height());
232         else pSize.setHeight(height);
233 
234     QPixmap pixmap(pSize);
235     */
236     QPixmap pixmap(this->size());
237 
238     this->render(&pixmap);
239     pixmap.save(filename); //QT will automatically pick the file format given the extension
240 }
241 
setReference(unsigned char * newRef,bool bUpdate=true)242 void CANDataGrid::setReference(unsigned char *newRef, bool bUpdate = true)
243 {
244     memcpy(refData, newRef, 8);
245     if (bUpdate) this->update();
246 }
247 
updateData(unsigned char * newData,bool bUpdate=true)248 void CANDataGrid::updateData(unsigned char *newData, bool bUpdate = true)
249 {
250     memcpy(data, newData, 8); //on a 64 bit processor this is probably optimized to a single instruction
251     if (bUpdate) this->update();
252 }
253 
setUsed(unsigned char * newData,bool bUpdate=false)254 void CANDataGrid::setUsed(unsigned char *newData, bool bUpdate = false)
255 {
256     memcpy(usedData, newData, 8);
257     if (bUpdate) this->update();
258 }
259