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

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

lic

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