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

Last change on this file since 10 was 10, checked in by Sanahuja Guillaume, 6 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.