]> git.zerfleddert.de Git - proxmark3-svn/blame - client/proxguiqt.cpp
First stab at new graphing; dual buffers, immediate results
[proxmark3-svn] / client / proxguiqt.cpp
CommitLineData
a553f267 1//-----------------------------------------------------------------------------
212ef3a0 2// Copyright (C) 2009 Michael Gernoth <michael at gernoth.net>
3//
a553f267 4// This code is licensed to you under the terms of the GNU GPL, version 2 or,
5// at your option, any later version. See the LICENSE.txt file for the text of
6// the license.
7//-----------------------------------------------------------------------------
8// GUI (QT)
9//-----------------------------------------------------------------------------
10
6658905f 11#include <iostream>
12#include <QPainterPath>
13#include <QBrush>
14#include <QPen>
15#include <QTimer>
16#include <QCloseEvent>
17#include <QMouseEvent>
18#include <QKeyEvent>
19#include <math.h>
20#include <limits.h>
c86cc308 21#include <stdio.h>
0d704c7f
MHS
22#include <QSlider>
23#include <QHBoxLayout>
24#include <string.h>
6658905f 25#include "proxguiqt.h"
26#include "proxgui.h"
0d704c7f
MHS
27#include <QtGui>
28//#include "data_operations.h"
29#include <ctime>
6658905f 30
7ddb9900 31int GridOffset= 0;
32bool GridLocked= 0;
33int startMax;
18856d88 34int PageWidth;
7ddb9900 35
6658905f 36void ProxGuiQT::ShowGraphWindow(void)
37{
38 emit ShowGraphWindowSignal();
39}
40
41void ProxGuiQT::RepaintGraphWindow(void)
42{
43 emit RepaintGraphWindowSignal();
44}
45
46void ProxGuiQT::HideGraphWindow(void)
47{
48 emit HideGraphWindowSignal();
49}
50
51void ProxGuiQT::_ShowGraphWindow(void)
52{
53 if(!plotapp)
54 return;
55
56 if (!plotwidget)
57 plotwidget = new ProxWidget();
58
59 plotwidget->show();
60}
61
62void ProxGuiQT::_RepaintGraphWindow(void)
63{
64 if (!plotapp || !plotwidget)
65 return;
66
67 plotwidget->update();
68}
69
70void ProxGuiQT::_HideGraphWindow(void)
71{
72 if (!plotapp || !plotwidget)
73 return;
74
75 plotwidget->hide();
76}
77
78void ProxGuiQT::MainLoop()
79{
80 plotapp = new QApplication(argc, argv);
81
82 connect(this, SIGNAL(ShowGraphWindowSignal()), this, SLOT(_ShowGraphWindow()));
83 connect(this, SIGNAL(RepaintGraphWindowSignal()), this, SLOT(_RepaintGraphWindow()));
84 connect(this, SIGNAL(HideGraphWindowSignal()), this, SLOT(_HideGraphWindow()));
85
86 plotapp->exec();
87}
88
89ProxGuiQT::ProxGuiQT(int argc, char **argv) : plotapp(NULL), plotwidget(NULL),
90 argc(argc), argv(argv)
91{
0d704c7f 92
6658905f 93}
94
95ProxGuiQT::~ProxGuiQT(void)
96{
97 if (plotwidget) {
98 delete plotwidget;
99 plotwidget = NULL;
100 }
101
102 if (plotapp) {
103 plotapp->quit();
104 delete plotapp;
105 plotapp = NULL;
106 }
107}
108
0d704c7f
MHS
109//--------------------
110
111void ProxWidget::applyOperation()
6658905f 112{
0d704c7f
MHS
113 printf("ApplyOperation()");
114 memcpy(GraphBuffer,s_Buff, GraphTraceLen);
115 RepaintGraphWindow();
6658905f 116
0d704c7f
MHS
117}
118void ProxWidget::stickOperation()
119{
120 printf("stickOperation()");
121}
122void ProxWidget::vchange_autocorr(int v)
123{
124 autoCorr(GraphBuffer,s_Buff, GraphTraceLen, v);
125 printf("vchange_autocorr(%d)\n", v);
126 RepaintGraphWindow();
127}
128void ProxWidget::vchange_dthr_up(int v)
129{
130 int down = opsController->horizontalSlider_dirthr_down->value();
131 directionalThreshold(GraphBuffer,s_Buff, GraphTraceLen, v, down);
132 printf("vchange_dthr_up(%d)", v);
133 RepaintGraphWindow();
6658905f 134
0d704c7f
MHS
135}
136void ProxWidget::vchange_dthr_down(int v)
137{
138 printf("vchange_dthr_down(%d)", v);
139 int up = opsController->horizontalSlider_dirthr_up->value();
140 directionalThreshold(GraphBuffer,s_Buff, GraphTraceLen, v, up);
141 RepaintGraphWindow();
6658905f 142
0d704c7f
MHS
143}
144ProxWidget::ProxWidget(QWidget *parent, ProxGuiQT *master) : QWidget(parent)
145{
146 this->master = master;
147 resize(800,500);
148
149 /** Setup the controller widget **/
150
151 QWidget* controlWidget = new QWidget();
152 opsController = new Ui::Form();
153 opsController->setupUi(controlWidget);
154 //Due to quirks in QT Designer, we need to fiddle a bit
155 opsController->horizontalSlider_dirthr_down->setMinimum(-128);
156 opsController->horizontalSlider_dirthr_down->setMaximum(0);
157 opsController->horizontalSlider_dirthr_down->setValue(-20);
158
159
160 QObject::connect(opsController->pushButton_apply, SIGNAL(clicked()), this, SLOT(applyOperation()));
161 QObject::connect(opsController->pushButton_sticky, SIGNAL(clicked()), this, SLOT(stickOperation()));
162 QObject::connect(opsController->horizontalSlider_window, SIGNAL(valueChanged(int)), this, SLOT(vchange_autocorr(int)));
163 QObject::connect(opsController->horizontalSlider_dirthr_up, SIGNAL(valueChanged(int)), this, SLOT(vchange_dthr_up(int)));
164 QObject::connect(opsController->horizontalSlider_dirthr_down, SIGNAL(valueChanged(int)), this, SLOT(vchange_dthr_down(int)));
165
166 controlWidget->show();
167
168 // Set up the plot widget, which does the actual plotting
169
170 plot = new Plot(this);
171 /*
172 QSlider* slider = new QSlider(Qt::Horizontal);
173 slider->setFocusPolicy(Qt::StrongFocus);
174 slider->setTickPosition(QSlider::TicksBothSides);
175 slider->setTickInterval(10);
176 slider->setSingleStep(1);
177 */
178 QVBoxLayout *layout = new QVBoxLayout;
179 //layout->addWidget(slider);
180 layout->addWidget(plot);
181 setLayout(layout);
182 printf("Proxwidget Constructor just set layout\r\n");
183}
0bf5872f 184
0d704c7f 185//----------- Plotting
6658905f 186
0d704c7f
MHS
187int Plot::xCoordOf(int i )
188{
189 return 40 + (int)((i - GraphStart)*GraphPixelsPerPoint);
190}
6658905f 191
0d704c7f
MHS
192int Plot::yCoordOf(int v, QRect r, int maxVal)
193{
194 int z = (r.bottom() - r.top())/2;
195 return -(z * v) / maxVal + z;
196}
6658905f 197
0d704c7f
MHS
198int Plot::valueOf_yCoord(int y, QRect r, int maxVal)
199{
200 int z = (r.bottom() - r.top())/2;
201 return (y-z) * maxVal / z;
202}
203static const QColor GREEN = QColor(100, 255, 100);
204static const QColor RED = QColor(255, 100, 100);
205static const QColor BLUE = QColor(100,100,255);
206static const QColor GREY = QColor(240,240,240);
6658905f 207
0d704c7f
MHS
208QColor Plot::getColor(int graphNum)
209{
210 switch (graphNum){
211 case 0: return GREEN;//Green
212 case 1: return RED;//Red
213 case 2: return BLUE;//Blue
214 default: return GREY;
215 }
216}
f4434ad2 217
0d704c7f
MHS
218void Plot::PlotGraph(int *buffer, int len, QRect r,QPainter *painter, int graphNum)
219{
220 clock_t begin = clock();
221 QPainterPath penPath;
222
223 startMax = (len - (int)((r.right() - r.left() - 40) / GraphPixelsPerPoint));
6658905f 224 if(startMax < 0) {
225 startMax = 0;
226 }
227 if(GraphStart > startMax) {
228 GraphStart = startMax;
229 }
230
0d704c7f
MHS
231 int vMin = INT_MAX, vMax = INT_MIN,vMean = 0, v = 0,absVMax = 0;
232 int sample_index =GraphStart ;
233 for( ; sample_index < len && xCoordOf(sample_index) < r.right() ; sample_index++) {
6658905f 234
0d704c7f
MHS
235 v = buffer[sample_index];
236 if(v < vMin) vMin = v;
237 if(v > vMax) vMax = v;
238 vMean += v;
6658905f 239 }
240
0d704c7f
MHS
241 vMean /= (sample_index - GraphStart);
242
243 if(fabs( (double) vMin) > absVMax) absVMax = (int)fabs( (double) vMin);
244 if(fabs( (double) vMax) > absVMax) absVMax = (int)fabs( (double) vMax);
245 absVMax = (int)(absVMax*1.2 + 1);
246
6658905f 247 // number of points that will be plotted
248 int span = (int)((r.right() - r.left()) / GraphPixelsPerPoint);
249 // one label every 100 pixels, let us say
250 int labels = (r.right() - r.left() - 40) / 100;
251 if(labels <= 0) labels = 1;
252 int pointsPerLabel = span / labels;
253 if(pointsPerLabel <= 0) pointsPerLabel = 1;
254
0d704c7f
MHS
255 int x = xCoordOf(0)+40;
256 int y = yCoordOf(buffer[0],r,absVMax);
257 penPath.moveTo(x, y);
6658905f 258
0d704c7f
MHS
259 int zeroY = yCoordOf( 0 , r , absVMax);
260 for(int i = GraphStart; i < len && xCoordOf(i) < r.right(); i++) {
6658905f 261
0d704c7f
MHS
262 x = xCoordOf(i);
263 v = buffer[i];
264
265 y = yCoordOf( v, r, absVMax);//(y * (r.top() - r.bottom()) / (2*absYMax)) + zeroHeight;
266
267 penPath.lineTo(x, y);
6658905f 268
269 if(GraphPixelsPerPoint > 10) {
270 QRect f(QPoint(x - 3, y - 3),QPoint(x + 3, y + 3));
0d704c7f 271 painter->fillRect(f, QColor(100, 255, 100));
6658905f 272 }
273
274 if(((i - GraphStart) % pointsPerLabel == 0) && i != GraphStart) {
6658905f 275 char str[100];
276 sprintf(str, "+%d", (i - GraphStart));
277
0d704c7f 278 painter->setPen(QColor(255, 255, 255));
6658905f 279 QRect size;
0d704c7f 280 QFontMetrics metrics(painter->font());
6658905f 281 size = metrics.boundingRect(str);
0d704c7f 282 painter->drawText(x - (size.right() - size.left()), zeroY + 9, str);
6658905f 283 }
284
0d704c7f
MHS
285 }
286 painter->setPen(getColor(graphNum));
287 painter->drawPath(penPath);
288 char str[200];
289 sprintf(str, "max=%5d min=%5d mean=%5d n=%5d/%5d CursorA=[%5d] CursorB=[%5d]",
290 vMax, vMin, vMean, sample_index, len, buffer[CursorAPos], buffer[CursorBPos]);
291
292 painter->drawText(120, r.bottom() - 25 - 15 * graphNum, str);
293
294 //Draw y-axis
295
296 int xo = r.left()+40+(graphNum*40);
297 painter->drawLine(xo, r.top(),xo, r.bottom());
298
299 int vMarkers = (absVMax - (absVMax % 10)) / 10;
300 int minYDist = 20; //Minimum pixel-distance between markers
301
302 char yLbl[20];
303
304 int n = 0;
305 int lasty0 = 65535;
306
307 for(int v = vMarkers; yCoordOf(v,r,absVMax) > r.top() && n < 20; v+= vMarkers ,n++)
308 {
309 int y0 = yCoordOf(v,r,absVMax);
310 int y1 = yCoordOf(-v,r,absVMax);
311
312 if(lasty0 - y0 < minYDist) continue;
313
314 painter->drawLine(xo-5,y0, xo+5, y0);
315
316 sprintf(yLbl, "%d", v);
317 painter->drawText(xo+5,y0-2,yLbl);
318
319 painter->drawLine(xo-5, y1, xo+5, y1);
320 sprintf(yLbl, "%d",-v);
321 painter->drawText(xo+5, y1-2 , yLbl);
322 lasty0 = y0;
323 }
324
325
326 clock_t end = clock();
327 double elapsed_secs = double(end - begin) / CLOCKS_PER_SEC;
328 printf("Plot time %f\n", elapsed_secs);
329}
330void Plot::plotGridLines(QPainter* painter,QRect r)
331{
332 int zeroHeight = r.top() + (r.bottom() - r.top()) / 2;
333
334 int i;
335 int grid_delta_x = (int) (PlotGridX * GraphPixelsPerPoint);
336 int grid_delta_y = (int) (PlotGridY * GraphPixelsPerPoint);
337
338 if (PlotGridX > 0 && grid_delta_x > 1) {
339 for(i = 40 + (GridOffset * GraphPixelsPerPoint); i < r.right(); i += grid_delta_x)
340 painter->drawLine(r.left()+i, r.top(), r.left()+i, r.bottom());
341 }
342 if (PlotGridY > 0 && grid_delta_y > 1){
343 for(i = 0; i < ((r.top() + r.bottom())>>1); i += grid_delta_y) {
344 painter->drawLine(r.left() + 40,zeroHeight + i,r.right(),zeroHeight + i);
345 painter->drawLine(r.left() + 40,zeroHeight - i,r.right(),zeroHeight - i);
6658905f 346
6658905f 347 }
348 }
349
0d704c7f
MHS
350}
351
352void Plot::paintEvent(QPaintEvent *event)
353{
354
355 QPainter painter(this);
356 QRect r;
357 QBrush brush(QColor(100, 255, 100));
358 QPen pen(QColor(100, 255, 100));
359
360 painter.setFont(QFont("Courier New", 10));
361
362 if(GraphStart < 0) {
363 GraphStart = 0;
364 }
365
366 if (CursorAPos > GraphTraceLen)
367 CursorAPos= 0;
368 if(CursorBPos > GraphTraceLen)
369 CursorBPos= 0;
370
371 r = rect();
372
373 //Black foreground
374 painter.fillRect(r, QColor(0, 0, 0));
375
376 //Draw y-axis
377 //painter.setPen(QColor(255, 255, 255));
378 //painter.drawLine(r.left()+40, r.top(),r.left() + 40, r.bottom());
379
380 int zeroHeight = r.top() + (r.bottom() - r.top()) / 2;
381 // Draw 0-line
382 painter.setPen(QColor(100, 100, 100));
383 painter.drawLine(r.left(), zeroHeight, r.right(), zeroHeight);
384
385 PageWidth= (int)((r.right() - r.left() - 40) / GraphPixelsPerPoint);
386
387 // plot X and Y grid lines
388 plotGridLines(&painter, r);
389
390 //Start painting graph
391 PlotGraph(s_Buff, GraphTraceLen,r,&painter,1);
392 PlotGraph(GraphBuffer, GraphTraceLen,r,&painter,0);
393 // End graph drawing
394
395 //Draw the two cursors
396 if(CursorAPos > GraphStart && xCoordOf(CursorAPos) < r.right())
397 {
398 painter.setPen(QColor(255, 255, 0));
399 painter.drawLine(xCoordOf(CursorAPos),r.top(),xCoordOf(CursorAPos),r.bottom());
400 }
401 if(CursorBPos > GraphStart && xCoordOf(CursorBPos) < r.right())
402 {
403 painter.setPen(QColor(255, 0, 255));
404 painter.drawLine(xCoordOf(CursorBPos),r.top(),xCoordOf(CursorBPos),r.bottom());
6658905f 405 }
406
6658905f 407
346ad5fb 408 char str[200];
0d704c7f
MHS
409 sprintf(str, "@%5d dt=%5d [%2.2f] zoom=%2.2f CursorA= %5d CursorB= %5d GridX=%5d GridY=%5d (%s)",
410 GraphStart, CursorBPos - CursorAPos, (CursorBPos - CursorAPos)/CursorScaleFactor,
411 GraphPixelsPerPoint,CursorAPos,CursorBPos,PlotGridXdefault,PlotGridYdefault,GridLocked?"Locked":"Unlocked");
6658905f 412 painter.setPen(QColor(255, 255, 255));
0d704c7f
MHS
413 painter.drawText(120, r.bottom() - 10, str);
414
6658905f 415}
416
0d704c7f
MHS
417
418Plot::Plot(QWidget *parent) : QWidget(parent), GraphStart(0), GraphPixelsPerPoint(1)
6658905f 419{
0d704c7f
MHS
420 //Need to set this, otherwise we don't receive keypress events
421 setFocusPolicy( Qt::StrongFocus);
9484ff3d 422 resize(600, 300);
6658905f 423
424 QPalette palette(QColor(0,0,0,0));
425 palette.setColor(QPalette::WindowText, QColor(255,255,255));
426 palette.setColor(QPalette::Text, QColor(255,255,255));
427 palette.setColor(QPalette::Button, QColor(100, 100, 100));
428 setPalette(palette);
429 setAutoFillBackground(true);
cee48e2b 430 CursorAPos = 0;
431 CursorBPos = 0;
0d704c7f
MHS
432
433 setWindowTitle(tr("Sliders"));
434
435
6658905f 436}
437
0d704c7f 438void Plot::closeEvent(QCloseEvent *event)
6658905f 439{
440 event->ignore();
441 this->hide();
442}
443
0d704c7f 444void Plot::mouseMoveEvent(QMouseEvent *event)
6658905f 445{
446 int x = event->x();
447 x -= 40;
448 x = (int)(x / GraphPixelsPerPoint);
449 x += GraphStart;
450 if((event->buttons() & Qt::LeftButton)) {
451 CursorAPos = x;
452 } else if (event->buttons() & Qt::RightButton) {
453 CursorBPos = x;
454 }
455
456
457 this->update();
458}
459
0d704c7f 460void Plot::keyPressEvent(QKeyEvent *event)
6658905f 461{
18856d88 462 int offset;
463 int gridchanged;
464
465 gridchanged= 0;
18856d88 466 if(event->modifiers() & Qt::ShiftModifier) {
467 if (PlotGridX)
468 offset= PageWidth - (PageWidth % PlotGridX);
469 else
470 offset= PageWidth;
ff2e9c1c 471 } else
472 if(event->modifiers() & Qt::ControlModifier)
473 offset= 1;
474 else
475 offset= (int)(20 / GraphPixelsPerPoint);
18856d88 476
6658905f 477 switch(event->key()) {
478 case Qt::Key_Down:
479 if(GraphPixelsPerPoint <= 50) {
480 GraphPixelsPerPoint *= 2;
481 }
482 break;
483
484 case Qt::Key_Up:
485 if(GraphPixelsPerPoint >= 0.02) {
486 GraphPixelsPerPoint /= 2;
487 }
488 break;
489
490 case Qt::Key_Right:
491 if(GraphPixelsPerPoint < 20) {
18856d88 492 if (PlotGridX && GridLocked && GraphStart < startMax){
493 GridOffset -= offset;
494 GridOffset %= PlotGridX;
495 gridchanged= 1;
496 }
497 GraphStart += offset;
6658905f 498 } else {
18856d88 499 if (PlotGridX && GridLocked && GraphStart < startMax){
7ddb9900 500 GridOffset--;
18856d88 501 GridOffset %= PlotGridX;
502 gridchanged= 1;
503 }
3bc2349d 504 GraphStart++;
6658905f 505 }
18856d88 506 if(GridOffset < 0) {
7ddb9900 507 GridOffset += PlotGridX;
18856d88 508 }
509 if (gridchanged)
510 if (GraphStart > startMax) {
511 GridOffset += (GraphStart - startMax);
512 GridOffset %= PlotGridX;
513 }
6658905f 514 break;
515
516 case Qt::Key_Left:
517 if(GraphPixelsPerPoint < 20) {
18856d88 518 if (PlotGridX && GridLocked && GraphStart > 0){
519 GridOffset += offset;
520 GridOffset %= PlotGridX;
521 gridchanged= 1;
522 }
523 GraphStart -= offset;
6658905f 524 } else {
18856d88 525 if (PlotGridX && GridLocked && GraphStart > 0){
7ddb9900 526 GridOffset++;
18856d88 527 GridOffset %= PlotGridX;
528 gridchanged= 1;
529 }
3bc2349d 530 GraphStart--;
6658905f 531 }
18856d88 532 if (gridchanged){
533 if (GraphStart < 0)
534 GridOffset += GraphStart;
535 if(GridOffset < 0)
536 GridOffset += PlotGridX;
537 GridOffset %= PlotGridX;
538 }
7ddb9900 539 break;
540
541 case Qt::Key_G:
542 if(PlotGridX || PlotGridY) {
543 PlotGridX= 0;
544 PlotGridY= 0;
545 } else {
546 PlotGridX= PlotGridXdefault;
547 PlotGridY= PlotGridYdefault;
548 }
549 break;
550
551 case Qt::Key_H:
552 puts("Plot Window Keystrokes:\n");
ff2e9c1c 553 puts(" Key Action\n");
554 puts(" DOWN Zoom in");
555 puts(" G Toggle grid display");
556 puts(" H Show help");
557 puts(" L Toggle lock grid relative to samples");
558 puts(" LEFT Move left");
559 puts(" <CTL>LEFT Move left 1 sample");
560 puts(" <SHIFT>LEFT Page left");
561 puts(" LEFT-MOUSE-CLICK Set yellow cursor");
562 puts(" Q Hide window");
563 puts(" RIGHT Move right");
564 puts(" <CTL>RIGHT Move right 1 sample");
565 puts(" <SHIFT>RIGHT Page right");
566 puts(" RIGHT-MOUSE-CLICK Set purple cursor");
567 puts(" UP Zoom out");
7ddb9900 568 puts("");
569 puts("Use client window 'data help' for more plot commands\n");
570 break;
571
572 case Qt::Key_L:
573 GridLocked= !GridLocked;
574 break;
575
576 case Qt::Key_Q:
577 this->hide();
6658905f 578 break;
579
580 default:
581 QWidget::keyPressEvent(event);
582 return;
583 break;
584 }
585
586 this->update();
587}
Impressum, Datenschutz