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