source: flair-src/trunk/tools/FlairGCS/src/Scope.cpp@ 9

Last change on this file since 9 was 9, checked in by Sanahuja Guillaume, 8 years ago

gcs

File size: 8.8 KB
Line 
1#include "Scope.h"
2#include "Scrollbar.h"
3#include <qwt_plot_curve.h>
4#include <qwt_plot_grid.h>
5#include <qwt_plot_magnifier.h>
6#include <qwt_plot_canvas.h>
7#include <qwt_scale_widget.h>
8#include <qwt_legend_label.h>
9#include <qwt_legend.h>
10#include <qwt_plot_panner.h>
11#include <QMouseEvent>
12#include <QMenu>
13#include <QTimer>
14#include <QTime>
15#include <QApplication>
16
17#define WHEEL_DIVIDOR 30
18
19Scope::Scope(QString title,float ymin,float ymax,float view_size_s,unsigned int refresh_rate_ms,unsigned int history_size): QwtPlot() {
20 this->ymin=ymin;
21 this->ymax=ymax;
22 this->history_size=history_size;
23 this->view_size_s=view_size_s;
24 orig_view_size_s=view_size_s;
25
26 //scroll bar
27 scrollbar=new ScrollBar(Qt::Horizontal,canvas());
28 connect(scrollbar,SIGNAL(valueChanged(Qt::Orientation,float,float)),this,SLOT(scrollBarMoved(Qt::Orientation,float,float)));
29 scrolling=true;
30
31 //minimum size; sinon widget trop grand
32 setMinimumHeight(10);
33 setMinimumWidth(1);
34
35 alignScales();//is it necessary?
36
37 // Initialize data
38 elapsed_time_s=0;
39
40 // Assign a title
41 setTitle(title);
42
43 // Axis
44 setAxisTitle(QwtPlot::xBottom, "Time (s)");
45 setAxisScale(QwtPlot::xBottom,0, view_size_s);
46
47 setAxisTitle(QwtPlot::yLeft, "Values");
48 setAxisScale(QwtPlot::yLeft, ymin, ymax);
49
50 // grid
51 QwtPlotGrid *grid = new QwtPlotGrid;
52 grid->setPen(QPen(Qt::black, 0, Qt::DotLine));
53 grid->attach(this);
54
55 //zoomer
56 QwtPlotMagnifier * zoomer = new QwtPlotMagnifier(canvas());
57 zoomer->setWheelModifiers( Qt::ControlModifier );
58 zoomer->setMouseButton(Qt::NoButton);
59 zoomer->setAxisEnabled(xBottom,0);
60
61 //scroller
62 QwtPlotPanner *scroller =new QwtPlotPanner(canvas());
63 scroller->setAxisEnabled(xBottom,0);
64
65 //legend
66 QwtLegend* new_legend=new QwtLegend();
67 new_legend->setDefaultItemMode(QwtLegendData::Checkable);
68 insertLegend(new_legend, QwtPlot::BottomLegend);
69
70 connect( new_legend, SIGNAL( checked( const QVariant &, bool, int ) ), SLOT( legendChecked( const QVariant &, bool ) ) );
71
72 QTimer *timer = new QTimer(this);
73 connect(timer, SIGNAL(timeout()), this, SLOT(replot()));
74 timer->start(refresh_rate_ms);
75}
76
77Scope::~Scope() {
78 for(int i=0;i<curves.count();i++) {
79 free(curves.at(i)->data_x);
80 free(curves.at(i)->data_y);
81 delete curves.at(i)->plot;
82 free(curves.at(i));
83 }
84}
85
86void Scope::resetXView(void) {
87 //setAxisScale(QwtPlot::xBottom,0, orig_view_size_s);
88 changeViewSize(orig_view_size_s);
89}
90
91void Scope::resetYView(void) {
92 setAxisScale(QwtPlot::yLeft, ymin, ymax);
93}
94
95bool Scope::eventFilter(QObject *o, QEvent *e) {
96 switch(e->type()) {
97 case QEvent::Resize: {
98 const int fw = ((QwtPlotCanvas *)canvas())->frameWidth();
99
100 QRect rect;
101 rect.setSize(((QResizeEvent *)e)->size());
102 rect.setRect(rect.x() + fw, rect.y() + fw,
103 rect.width() - 2 * fw, rect.height() - 2 * fw);
104
105 scrollbar->setGeometry(0, 0, rect.width(), 10);
106 return true;
107 }
108 case QEvent::Wheel: {
109 //ctrl+wheel is already handled for y zoom
110 if(!(QApplication::keyboardModifiers() & Qt::ControlModifier)) {
111 QWheelEvent *wheelevent = static_cast<QWheelEvent *> (e);
112 if(view_size_s+wheelevent->delta()/WHEEL_DIVIDOR>0) changeViewSize(view_size_s+wheelevent->delta()/WHEEL_DIVIDOR);
113 }
114 return true;
115 }
116 default:
117 break;
118 }
119 return QwtPlot::eventFilter(o, e);
120}
121
122void Scope::changeViewSize(float new_view_size_s) {
123 view_size_s=new_view_size_s;
124
125 if(scrolling==false) {
126 //4 cas: on utilise le temps au milieu de la vue actuelle
127
128 //le temps total est plus petit que le view_size_s, on affiche tout:
129 if(elapsed_time_s<view_size_s) {
130 scrolling=true;
131 } else {
132 double min=(min_scroll+max_scroll)/2-view_size_s/2;
133 double max=(min_scroll+max_scroll)/2+view_size_s/2;
134 //on va du debut jusqu'a view size
135 if( min<0) {
136 min=0;
137 max=view_size_s;
138 }
139 //on va de fin-viewsize jusqu'a la fin
140 if(max>elapsed_time_s) {
141 min=elapsed_time_s-view_size_s;
142 max=elapsed_time_s;
143 }
144 scrollbar->moveSlider(min,max);//move slider coupe le signal, on fait aussi le scrollbar
145 scrollBarMoved(Qt::Horizontal,min,max);
146 }
147 }
148}
149
150void Scope::legendChecked( const QVariant &itemInfo, bool on ) {
151 QwtPlotItem *plotItem=infoToItem(itemInfo);
152 if(plotItem) showCurve( plotItem, on );
153}
154
155void Scope::showCurve(QwtPlotItem *item, bool on) {
156 item->setVisible(on);
157
158 QwtLegend *lgd=qobject_cast<QwtLegend*>(legend());
159
160 QList<QWidget*> legendWidgets=lgd->legendWidgets(itemToInfo(item));
161
162 if(legendWidgets.size()==1) {
163 QwtLegendLabel *legendLabel=qobject_cast<QwtLegendLabel*>(legendWidgets[0]);
164
165 if(legendLabel) legendLabel->setChecked( on );
166 }
167}
168
169int Scope::addCurve(QPen pen,QString legend) {
170 Curve* curve=(Curve*)malloc(sizeof(Curve));
171 curve->data_x=(double*)calloc(history_size,sizeof(double));
172 curve->data_y=(double*)calloc(history_size,sizeof(double));
173 curve->index=0;
174 curve->min_index=0;
175 curve->max_index=0;
176
177 // Insert new curve
178 curve->plot=new QwtPlotCurve(legend);
179 curve->plot->attach(this);
180 curve->plot->setPen(pen);
181 curves.append(curve);
182
183 showCurve(curve->plot, true);
184
185 return curves.count()-1;
186}
187
188void Scope::updateCurve(Curve* curve) {
189 if(scrolling==true) {
190 curve->plot->setRawSamples(&curve->data_x[curve->min_index], &curve->data_y[curve->min_index], curve->max_index-curve->min_index);
191 }
192
193 if(curve->index==history_size) {
194 //printf("a revoir qd on arrive a la fin, il faudrait faire un realloc pour rien perdre\n");
195 //attention le setrawdata s'attend a ce que l'adresse change pas, ce qui n'est pas le cas avec lerealloc
196 //il faudra refaire un setrawdata ici
197 curve->index=0;
198 curve->min_index=0;
199 scrolling=true;
200 }
201
202 //determine les index pour la visualisation
203 if(scrolling==true) {
204 curve->max_index=curve->index;
205 computeMinIndex(curve,elapsed_time_s-view_size_s);
206 }
207
208 scrollbar->setBase(0,elapsed_time_s);
209 if(scrolling==true) {
210 scrollbar->moveSlider(elapsed_time_s-view_size_s,elapsed_time_s);
211
212 if(elapsed_time_s<view_size_s) {
213 setAxisScale(QwtPlot::xBottom,0, view_size_s);
214 } else {
215 setAxisScale(QwtPlot::xBottom,elapsed_time_s-view_size_s, elapsed_time_s);
216 }
217 } else {
218 scrollbar->moveSlider(min_scroll,max_scroll);
219 }
220}
221
222void Scope::alignScales(void) {
223 // The code below shows how to align the scales to
224 // the canvas frame, but is also a good example demonstrating
225 // why the spreaded API needs polishing.
226/*
227 plot->canvas()->setFrameStyle(QFrame::Box | QFrame::Plain );
228 plot->canvas()->setLineWidth(1);
229*/
230 for(int i = 0;i<QwtPlot::axisCnt;i++) {
231 QwtScaleWidget *scaleWidget = (QwtScaleWidget *)axisWidget(i);
232 if(scaleWidget) scaleWidget->setMargin(0);
233
234 QwtScaleDraw *scaleDraw=(QwtScaleDraw *)axisScaleDraw(i);
235 if(scaleDraw) scaleDraw->enableComponent(QwtAbstractScaleDraw::Backbone, false);
236 }
237}
238
239void Scope::scrollBarMoved(Qt::Orientation o, float min, float max)
240{
241 min_scroll=min;
242 max_scroll=max;
243
244 if(max==scrollbar->maxBaseValue()) {
245 scrolling=true;
246 } else {
247 scrolling=false;
248 setAxisScale(QwtPlot::xBottom,min,max);
249
250 //determine les index pour la visualisation
251 for(int i=0;i<curves.count();i++) {
252 computeMinIndex(curves.at(i),min);
253 computeMaxIndex(curves.at(i),max);
254 curves.at(i)->plot->setRawSamples(&curves.at(i)->data_x[curves.at(i)->min_index], &curves.at(i)->data_y[curves.at(i)->min_index], curves.at(i)->max_index-curves.at(i)->min_index);
255 }
256 }
257}
258
259//TODO: faire une dichotomie
260void Scope::computeMinIndex(Curve* curve,float displayed_min_time) {
261 if(curve->data_x[curve->index]>displayed_min_time) {
262 if(curve->data_x[curve->min_index]<displayed_min_time) {
263 while(curve->data_x[curve->min_index]<displayed_min_time && curve->min_index!=curve->index) curve->min_index++;
264 } else {
265 while(curve->data_x[curve->min_index]>displayed_min_time && curve->min_index!=0) curve->min_index--;
266 }
267 }
268}
269
270void Scope::computeMaxIndex(Curve* curve,float displayed_max_time) {
271 if(curve->data_x[curve->max_index]<displayed_max_time) {
272 while(curve->data_x[curve->max_index]<displayed_max_time && curve->max_index!=curve->index) curve->max_index++;
273 } else {
274 while(curve->data_x[curve->max_index]>displayed_max_time) curve->max_index--;
275 }
276}
Note: See TracBrowser for help on using the repository browser.