datastreamswidget.cpp
1 /********************************************************************************
2  * FARSA DataStreamsWidget UI *
3  * Copyright (C) 2012-2013 *
4  * Gianluca Massera <emmegian@yahoo.it> *
5  * *
6  * This program is free software; you can redistribute it and/or modify *
7  * it under the terms of the GNU General Public License as published by *
8  * the Free Software Foundation; either version 2 of the License, or *
9  * (at your option) any later version. *
10  * *
11  * This program is distributed in the hope that it will be useful, *
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14  * GNU General Public License for more details. *
15  * *
16  * You should have received a copy of the GNU General Public License *
17  * along with this program; if not, write to the Free Software *
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *
19  ********************************************************************************/
20 
21 #include "datastreamswidget.h"
22 #include <QBoxLayout>
23 #include <QCheckBox>
24 #include <QPushButton>
25 #include <QFrame>
26 #include <QLabel>
27 #include <QMutexLocker>
28 #include <QProgressDialog>
29 
30 namespace farsa {
31 
33  QWidget(parent),
34  mutex( QMutex::Recursive ) {
35 
36  QVBoxLayout* lay = new QVBoxLayout( this );
37 
38  // top toolbar
39  QHBoxLayout* toolLay = new QHBoxLayout();
40  lay->addLayout( toolLay );
41  // regular automatic replot checkbox
42  QCheckBox* ck = new QCheckBox( "Automatic Update", this );
43  toolLay->addWidget( ck );
44  ck->setChecked( true );
45  connect( ck, SIGNAL(toggled(bool)), this, SLOT(enableAutomaticUpdates(bool)) );
46  QPushButton* bt = new QPushButton( "Update Plots", this );
47  toolLay->addWidget( bt );
48  bt->setEnabled( false );
49  bt->setAutoRepeat( true );
50  bt->setAutoRepeatDelay( 100 );
51  connect( bt, SIGNAL(clicked()), this, SLOT(updatePlots()) );
52  connect( ck, SIGNAL(toggled(bool)), bt, SLOT(setDisabled(bool)) );
53  bt = new QPushButton( "Dequeue All Data", this );
54  toolLay->addWidget( bt );
55  connect( bt, SIGNAL(clicked()), this, SLOT(dequeueAllData()) );
56 
57  // update the plot at regular intervals
58  replotTimer.setInterval( 20 );
59  replotTimer.setSingleShot( false );
60  replotTimer.start();
61  connect( &replotTimer, SIGNAL(timeout()), this, SLOT(updatePlots()) );
62 }
63 
65  /* nothing to do */
66 }
67 
68 int DataStreamsWidget::addPlot( QString name ) {
69  QMutexLocker locker( &mutex );
70 
71  QFrame* frame = new QFrame(this);
72  frame->setFrameStyle( QFrame::StyledPanel | QFrame::Plain );
73  QHBoxLayout* frameLay = new QHBoxLayout( frame );
74  QLabel* lb = new QLabel( name+"\nNo Data", frame );
75  frameLay->addWidget( lb );
76  DataStreamPlot* plot = new DataStreamPlot( frame );
77  plot->setMinimumSize( QSize(100,80) );
78  plot->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Ignored ) );
79  frameLay->addWidget( plot );
80  layout()->addWidget( frame );
81  plots.append( plot );
82  plotNames.append( name );
83  plotInfos.append( lb );
84  queuedValues.append( QQueue< QVector<float> >() );
85  return (plots.size()-1);
86 }
87 
89  QMutexLocker locker( &mutex );
90  return plots[plotID];
91 }
92 
94  QMutexLocker locker( &mutex );
95  return plots.size();
96 }
97 
98 void DataStreamsWidget::appendDatas( int plotID, QVector<float> values ) {
99  QMutexLocker locker( &mutex );
100  queuedValues[plotID].enqueue( values );
101 }
102 
103 void DataStreamsWidget::updatePlots() {
104  QMutexLocker locker( &mutex );
105  for( int p=0; p<plots.size(); p++ ) {
106  DataStreamPlot* plot = plots[p];
107  if ( !queuedValues[p].isEmpty() ) {
108  // consume one element of the queuedValues
109  QVector<float> values = queuedValues[p].dequeue();
110  for( int i=0; i<values.size(); i++ ) {
111  plot->appendData( i, values[i] );
112  }
113  }
114  plot->updatePlot();
115  plotInfos[p]->setText( QString("%1\n%2 Queued Data")
116  .arg(plotNames[p])
117  .arg(queuedValues[p].size()) );
118  }
119 }
120 
121 void DataStreamsWidget::enableAutomaticUpdates( bool enable ) {
122  if ( enable ) {
123  replotTimer.start();
124  } else {
125  replotTimer.stop();
126  }
127 }
128 
129 void DataStreamsWidget::dequeueAllData() {
130  QMutexLocker locker( &mutex );
131  // this operation can take long time
132  QProgressDialog progress( "Dequeuing All Pending Data...", "Stop", 0, plots.size(), this );
133 
134  for( int p=0; p<plots.size(); p++ ) {
135  QQueue< QVector<float> > queue = queuedValues[p];
136  while( !queue.isEmpty() ) {
137  QVector<float> values = queue.dequeue();
138  for( int i=0; i<values.size(); i++ ) {
139  plots[p]->appendData( i, values[i] );
140  }
141  }
142  progress.setValue(p);
143  }
144  progress.setValue(plots.size());
145 }
146 
147 } // end namespace farsa
void appendDatas(int plotID, QVector< float > values)
add new points to all of streams of the plotID DataStreamPlot
void updatePlot()
recalculate the x and y scale axis and replot the data
A macro to deprecate functions.
int getNumPlots()
return the number of plots added
void appendData(int streamID, float value)
append a point to the stream specified
int addPlot(QString name)
add a new DataStreamPlot to this widget and return its ID for retrieve it later
DataStreamsWidget(QWidget *parent=0)
constructor
virtual ~DataStreamsWidget()
destructor
DataStreamPlot * getPlot(int plotID)
return a pointer to the DataStreamPlot corresponding to the plotID specified
The DataStreamPlot display a series of data streams into the plot storing all the history of the data...