1 //-----------------------------------------------------------------------------
2 // Copyright (C) 2009 Michael Gernoth <michael at gernoth.net>
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
7 //-----------------------------------------------------------------------------
9 //-----------------------------------------------------------------------------
12 #include <QPainterPath>
16 #include <QCloseEvent>
17 #include <QMouseEvent>
23 #include <QHBoxLayout>
25 #include "proxguiqt.h"
28 //#include "data_operations.h"
36 void ProxGuiQT::ShowGraphWindow(void)
38 emit
ShowGraphWindowSignal();
41 void ProxGuiQT::RepaintGraphWindow(void)
43 emit
RepaintGraphWindowSignal();
46 void ProxGuiQT::HideGraphWindow(void)
48 emit
HideGraphWindowSignal();
51 void ProxGuiQT::_ShowGraphWindow(void)
57 plotwidget
= new ProxWidget();
62 void ProxGuiQT::_RepaintGraphWindow(void)
64 if (!plotapp
|| !plotwidget
)
70 void ProxGuiQT::_HideGraphWindow(void)
72 if (!plotapp
|| !plotwidget
)
78 void ProxGuiQT::MainLoop()
80 plotapp
= new QApplication(argc
, argv
);
82 connect(this, SIGNAL(ShowGraphWindowSignal()), this, SLOT(_ShowGraphWindow()));
83 connect(this, SIGNAL(RepaintGraphWindowSignal()), this, SLOT(_RepaintGraphWindow()));
84 connect(this, SIGNAL(HideGraphWindowSignal()), this, SLOT(_HideGraphWindow()));
89 ProxGuiQT::ProxGuiQT(int argc
, char **argv
) : plotapp(NULL
), plotwidget(NULL
),
90 argc(argc
), argv(argv
)
95 ProxGuiQT::~ProxGuiQT(void)
109 //--------------------
111 void ProxWidget::applyOperation()
113 printf("ApplyOperation()");
114 memcpy(GraphBuffer
,s_Buff
, sizeof(int) * GraphTraceLen
);
115 RepaintGraphWindow();
118 void ProxWidget::stickOperation()
120 printf("stickOperation()");
122 void ProxWidget::vchange_autocorr(int v
)
124 autoCorr(GraphBuffer
,s_Buff
, GraphTraceLen
, v
);
125 printf("vchange_autocorr(%d)\n", v
);
126 RepaintGraphWindow();
128 void ProxWidget::vchange_dthr_up(int v
)
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();
136 void ProxWidget::vchange_dthr_down(int v
)
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();
144 ProxWidget::ProxWidget(QWidget
*parent
, ProxGuiQT
*master
) : QWidget(parent
)
146 this->master
= master
;
149 /** Setup the controller widget **/
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);
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)));
166 controlWidget
->show();
168 // Set up the plot widget, which does the actual plotting
170 plot
= new Plot(this);
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);
178 QVBoxLayout
*layout
= new QVBoxLayout
;
179 //layout->addWidget(slider);
180 layout
->addWidget(plot
);
182 printf("Proxwidget Constructor just set layout\r\n");
185 //----------- Plotting
187 int Plot::xCoordOf(int i
, QRect r
)
189 return r
.left() + (int)((i
- GraphStart
)*GraphPixelsPerPoint
);
192 int Plot::yCoordOf(int v
, QRect r
, int maxVal
)
194 int z
= (r
.bottom() - r
.top())/2;
195 return -(z
* v
) / maxVal
+ z
;
198 int Plot::valueOf_yCoord(int y
, QRect r
, int maxVal
)
200 int z
= (r
.bottom() - r
.top())/2;
201 return (y
-z
) * maxVal
/ z
;
203 static const QColor GREEN
= QColor(100, 255, 100);
204 static const QColor RED
= QColor(255, 100, 100);
205 static const QColor BLUE
= QColor(100,100,255);
206 static const QColor GREY
= QColor(240,240,240);
208 QColor
Plot::getColor(int graphNum
)
211 case 0: return GREEN
;//Green
212 case 1: return RED
;//Red
213 case 2: return BLUE
;//Blue
214 default: return GREY
;
218 void Plot::PlotGraph(int *buffer
, int len
, QRect plotRect
, QRect annotationRect
,QPainter
*painter
, int graphNum
)
220 clock_t begin
= clock();
221 QPainterPath penPath
;
223 startMax
= (len
- (int)((plotRect
.right() - plotRect
.left() - 40) / GraphPixelsPerPoint
));
227 if(GraphStart
> startMax
) {
228 GraphStart
= startMax
;
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
,plotRect
) < plotRect
.right() ; sample_index
++) {
235 v
= buffer
[sample_index
];
236 if(v
< vMin
) vMin
= v
;
237 if(v
> vMax
) vMax
= v
;
241 vMean
/= (sample_index
- GraphStart
);
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 // number of points that will be plotted
247 int span
= (int)((plotRect
.right() - plotRect
.left()) / GraphPixelsPerPoint
);
248 // one label every 100 pixels, let us say
249 int labels
= (plotRect
.right() - plotRect
.left() - 40) / 100;
250 if(labels
<= 0) labels
= 1;
251 int pointsPerLabel
= span
/ labels
;
252 if(pointsPerLabel
<= 0) pointsPerLabel
= 1;
254 int x
= xCoordOf(0, plotRect
);
255 int y
= yCoordOf(buffer
[0],plotRect
,absVMax
);
256 penPath
.moveTo(x
, y
);
257 //int zeroY = yCoordOf( 0 , plotRect , absVMax);
258 for(int i
= GraphStart
; i
< len
&& xCoordOf(i
, plotRect
) < plotRect
.right(); i
++) {
260 x
= xCoordOf(i
, plotRect
);
263 y
= yCoordOf( v
, plotRect
, absVMax
);//(y * (r.top() - r.bottom()) / (2*absYMax)) + zeroHeight;
265 penPath
.lineTo(x
, y
);
267 if(GraphPixelsPerPoint
> 10) {
268 QRect
f(QPoint(x
- 3, y
- 3),QPoint(x
+ 3, y
+ 3));
269 painter
->fillRect(f
, QColor(100, 255, 100));
272 /* if(((i - GraphStart) % pointsPerLabel == 0) && i != GraphStart) {
274 sprintf(str, "+%d", (i - GraphStart));
276 painter->setPen(QColor(255, 255, 255));
278 QFontMetrics metrics(painter->font());
279 size = metrics.boundingRect(str);
280 painter->drawText(x - (size.right() - size.left()), zeroY + 9, str);
285 painter
->setPen(getColor(graphNum
));
288 int xo
= 5+(graphNum
*40);
289 painter
->drawLine(xo
, plotRect
.top(),xo
, plotRect
.bottom());
291 int vMarkers
= (absVMax
- (absVMax
% 10)) / 5;
292 int minYDist
= 40; //Minimum pixel-distance between markers
299 for(int v
= vMarkers
; yCoordOf(v
,plotRect
,absVMax
) > plotRect
.top() && n
< 20; v
+= vMarkers
,n
++)
301 int y0
= yCoordOf(v
,plotRect
,absVMax
);
302 int y1
= yCoordOf(-v
,plotRect
,absVMax
);
304 if(lasty0
- y0
< minYDist
) continue;
306 painter
->drawLine(xo
-5,y0
, xo
+5, y0
);
308 sprintf(yLbl
, "%d", v
);
309 painter
->drawText(xo
+5,y0
-2,yLbl
);
311 painter
->drawLine(xo
-5, y1
, xo
+5, y1
);
312 sprintf(yLbl
, "%d",-v
);
313 painter
->drawText(xo
+5, y1
-2 , yLbl
);
319 painter
->drawPath(penPath
);
321 sprintf(str
, "max=%5d min=%5d mean=%5d n=%5d/%5d CursorA=[%5d] CursorB=[%5d]",
322 vMax
, vMin
, vMean
, sample_index
, len
, buffer
[CursorAPos
], buffer
[CursorBPos
]);
323 painter
->drawText(20, annotationRect
.bottom() - 25 - 15 * graphNum
, str
);
325 clock_t end
= clock();
326 double elapsed_secs
= double(end
- begin
) / CLOCKS_PER_SEC
;
327 printf("Plot time %f\n", elapsed_secs
);
329 void Plot::plotGridLines(QPainter
* painter
,QRect r
)
331 int zeroHeight
= r
.top() + (r
.bottom() - r
.top()) / 2;
334 int grid_delta_x
= (int) (PlotGridX
* GraphPixelsPerPoint
);
335 int grid_delta_y
= (int) (PlotGridY
* GraphPixelsPerPoint
);
337 if (PlotGridX
> 0 && grid_delta_x
> 1) {
338 for(i
= 40 + (GridOffset
* GraphPixelsPerPoint
); i
< r
.right(); i
+= grid_delta_x
)
339 painter
->drawLine(r
.left()+i
, r
.top(), r
.left()+i
, r
.bottom());
341 if (PlotGridY
> 0 && grid_delta_y
> 1){
342 for(i
= 0; i
< ((r
.top() + r
.bottom())>>1); i
+= grid_delta_y
) {
343 painter
->drawLine(r
.left() + 40,zeroHeight
+ i
,r
.right(),zeroHeight
+ i
);
344 painter
->drawLine(r
.left() + 40,zeroHeight
- i
,r
.right(),zeroHeight
- i
);
350 #define HEIGHT_INFO 60
351 #define WIDTH_AXES 80
353 void Plot::paintEvent(QPaintEvent
*event
)
356 QPainter
painter(this);
358 QBrush
brush(QColor(100, 255, 100));
359 QPen
pen(QColor(100, 255, 100));
361 painter
.setFont(QFont("Courier New", 10));
367 if (CursorAPos
> GraphTraceLen
)
369 if(CursorBPos
> GraphTraceLen
)
373 QRect
plotRect(WIDTH_AXES
, 0, width()-WIDTH_AXES
, height()-HEIGHT_INFO
);
374 QRect
infoRect(0, height()-HEIGHT_INFO
, width(), HEIGHT_INFO
);
377 painter
.fillRect(rect(), QColor(60, 60, 60));
379 painter
.fillRect(plotRect
, QColor(0, 0, 0));
381 // painter.fillRect(infoRect, QColor(60, 60, 60));
383 int zeroHeight
= plotRect
.top() + (plotRect
.bottom() - plotRect
.top()) / 2;
385 painter
.setPen(QColor(100, 100, 100));
386 painter
.drawLine(plotRect
.left(), zeroHeight
, plotRect
.right(), zeroHeight
);
387 // plot X and Y grid lines
388 plotGridLines(&painter
, plotRect
);
390 //Start painting graph
391 PlotGraph(s_Buff
, GraphTraceLen
,plotRect
,infoRect
,&painter
,1);
392 PlotGraph(GraphBuffer
, GraphTraceLen
,plotRect
,infoRect
,&painter
,0);
395 //Draw the two cursors
396 if(CursorAPos
> GraphStart
&& xCoordOf(CursorAPos
, plotRect
) < plotRect
.right())
398 painter
.setPen(QColor(255, 255, 0));
399 painter
.drawLine(xCoordOf(CursorAPos
, plotRect
),plotRect
.top(),xCoordOf(CursorAPos
, plotRect
),plotRect
.bottom());
401 if(CursorBPos
> GraphStart
&& xCoordOf(CursorBPos
, plotRect
) < plotRect
.right())
403 painter
.setPen(QColor(255, 0, 255));
404 painter
.drawLine(xCoordOf(CursorBPos
, plotRect
),plotRect
.top(),xCoordOf(CursorBPos
, plotRect
),plotRect
.bottom());
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");
412 painter
.setPen(QColor(255, 255, 255));
413 painter
.drawText(20, infoRect
.bottom() - 10, str
);
418 Plot::Plot(QWidget
*parent
) : QWidget(parent
), GraphStart(0), GraphPixelsPerPoint(1)
420 //Need to set this, otherwise we don't receive keypress events
421 setFocusPolicy( Qt::StrongFocus
);
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));
429 setAutoFillBackground(true);
433 setWindowTitle(tr("Sliders"));
438 void Plot::closeEvent(QCloseEvent
*event
)
444 void Plot::mouseMoveEvent(QMouseEvent
*event
)
448 x
= (int)(x
/ GraphPixelsPerPoint
);
450 if((event
->buttons() & Qt::LeftButton
)) {
452 } else if (event
->buttons() & Qt::RightButton
) {
460 void Plot::keyPressEvent(QKeyEvent
*event
)
466 if(event
->modifiers() & Qt::ShiftModifier
) {
468 offset
= PageWidth
- (PageWidth
% PlotGridX
);
472 if(event
->modifiers() & Qt::ControlModifier
)
475 offset
= (int)(20 / GraphPixelsPerPoint
);
477 switch(event
->key()) {
479 if(GraphPixelsPerPoint
<= 50) {
480 GraphPixelsPerPoint
*= 2;
485 if(GraphPixelsPerPoint
>= 0.02) {
486 GraphPixelsPerPoint
/= 2;
491 if(GraphPixelsPerPoint
< 20) {
492 if (PlotGridX
&& GridLocked
&& GraphStart
< startMax
){
493 GridOffset
-= offset
;
494 GridOffset
%= PlotGridX
;
497 GraphStart
+= offset
;
499 if (PlotGridX
&& GridLocked
&& GraphStart
< startMax
){
501 GridOffset
%= PlotGridX
;
507 GridOffset
+= PlotGridX
;
510 if (GraphStart
> startMax
) {
511 GridOffset
+= (GraphStart
- startMax
);
512 GridOffset
%= PlotGridX
;
517 if(GraphPixelsPerPoint
< 20) {
518 if (PlotGridX
&& GridLocked
&& GraphStart
> 0){
519 GridOffset
+= offset
;
520 GridOffset
%= PlotGridX
;
523 GraphStart
-= offset
;
525 if (PlotGridX
&& GridLocked
&& GraphStart
> 0){
527 GridOffset
%= PlotGridX
;
534 GridOffset
+= GraphStart
;
536 GridOffset
+= PlotGridX
;
537 GridOffset
%= PlotGridX
;
542 if(PlotGridX
|| PlotGridY
) {
546 PlotGridX
= PlotGridXdefault
;
547 PlotGridY
= PlotGridYdefault
;
552 puts("Plot Window Keystrokes:\n");
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");
569 puts("Use client window 'data help' for more plot commands\n");
573 GridLocked
= !GridLocked
;
581 QWidget::keyPressEvent(event
);