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

Last change on this file since 16 was 15, checked in by Bayard Gildas, 9 years ago

sources reformatted with flair-format-dir script

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