Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #ifdef HAVE_QWT
00022
00023 #include "EventViewer.h"
00024 #include <QVBoxLayout>
00025 #include <QHBoxLayout>
00026 #include <QCheckBox>
00027 #include <QPushButton>
00028 #include <QDoubleSpinBox>
00029 #include <QFile>
00030 #include <QFileDialog>
00031 #include <QSettings>
00032 #include <QtDebug>
00033
00034 #include <qwt_plot.h>
00035 #include <qwt_plot_curve.h>
00036 #include <qwt_legend.h>
00037
00038 #if QWT_VERSION >= 0x060000
00039 #include <qwt_series_data.h>
00040 #else
00041 #include <qwt_data.h>
00042 #endif
00043
00044 #include <EventViewer.moc>
00045
00046 namespace Aseba
00047 {
00050
00051 #if QWT_VERSION >= 0x060000
00052 class EventDataWrapper : public QwtSeriesData<QPointF>
00053 {
00054 private:
00055 std::deque<double>& _x;
00056 std::deque<sint16>& _y;
00057
00058 public:
00059 EventDataWrapper(std::deque<double>& _x, std::deque<sint16>& _y) :
00060 _x(_x),
00061 _y(_y)
00062 { }
00063 virtual QRectF boundingRect () const { return qwtBoundingRect(*this); }
00064 virtual QPointF sample (size_t i) const { return QPointF(_x[i], double(_y[i])); }
00065 virtual size_t size () const { return _x.size(); }
00066 };
00067 #else
00068 class EventDataWrapper : public QwtData
00069 {
00070 private:
00071 std::deque<double>& _x;
00072 std::deque<sint16>& _y;
00073
00074 public:
00075 EventDataWrapper(std::deque<double>& _x, std::deque<sint16>& _y) :
00076 _x(_x),
00077 _y(_y)
00078 { }
00079 virtual QwtData * copy () const { return new EventDataWrapper(*this); }
00080 virtual size_t size () const { return _x.size(); }
00081 virtual double x (size_t i) const { return _x[i]; }
00082 virtual double y (size_t i) const { return (double)_y[i]; }
00083 };
00084 #endif
00085
00086 EventViewer::EventViewer(unsigned eventId, const QString& eventName, unsigned eventVariablesCount, MainWindow::EventViewers* eventsViewers) :
00087 eventId(eventId),
00088 eventsViewers(eventsViewers),
00089 values(eventVariablesCount),
00090 startingTime(QTime::currentTime())
00091 {
00092
00093 plot = new QwtPlot;
00094 plot->setCanvasBackground(Qt::white);
00095 plot->setAxisTitle(plot->xBottom, tr("Time (seconds)"));
00096 plot->setAxisTitle(plot->yLeft, tr("Values"));
00097
00098 QwtLegend *legend = new QwtLegend;
00099
00100 plot->insertLegend(legend, QwtPlot::BottomLegend);
00101
00102 for (size_t i = 0; i < values.size(); i++)
00103 {
00104 QwtPlotCurve *curve = new QwtPlotCurve(QString("%0").arg(i));
00105 #if QWT_VERSION >= 0x060000
00106 curve->setData(new EventDataWrapper(timeStamps, values[i]));
00107 #else
00108 curve->setData(EventDataWrapper(timeStamps, values[i]));
00109 #endif
00110 curve->attach(plot);
00111 curve->setPen(QPen(QColor::fromHsv((i * 360) / values.size(), 255, 100), 2));
00112 }
00113
00114 QVBoxLayout *layout = new QVBoxLayout(this);
00115 layout->addWidget(plot);
00116
00117
00118 QHBoxLayout *controlLayout = new QHBoxLayout;
00119
00120 status = new QLabel(tr("Recording..."));
00121 controlLayout->addWidget(status);
00122
00123 pauseRunButton = new QPushButton(QPixmap(QString(":/images/pause.png")), tr("&Pause"));
00124 connect(pauseRunButton, SIGNAL(clicked()), SLOT(pauseRunCapture()));
00125 controlLayout->addWidget(pauseRunButton);
00126
00127 QPushButton *clearButton = new QPushButton(QPixmap(QString(":/images/reset.png")), tr("&Clear"));
00128 connect(clearButton, SIGNAL(clicked()), SLOT(clearPlot()));
00129 controlLayout->addWidget(clearButton);
00130
00131 timeWindowCheckBox = new QCheckBox(tr("time &window:"));
00132 controlLayout->addWidget(timeWindowCheckBox);
00133
00134 timeWindowLength = new QDoubleSpinBox;
00135 timeWindowLength->setSuffix("s");
00136 connect(timeWindowCheckBox, SIGNAL(toggled(bool)), timeWindowLength, SLOT(setEnabled(bool)));
00137 timeWindowLength->setValue(10);
00138 timeWindowLength->setEnabled(false);
00139 controlLayout->addWidget(timeWindowLength);
00140 controlLayout->addStretch();
00141
00142 QPushButton *saveToFileButton = new QPushButton(QPixmap(QString(":/images/filesaveas.png")), tr("Save &As..."));
00143 connect(saveToFileButton, SIGNAL(clicked()), SLOT(saveToFile()));
00144 controlLayout->addWidget(saveToFileButton);
00145
00146 layout->addLayout(controlLayout);
00147
00148
00149 eventsViewers->insert(eventId, this);
00150 isCapturing = true;
00151 }
00152
00153 EventViewer::~EventViewer()
00154 {
00155 if (eventsViewers && isCapturing)
00156 eventsViewers->remove(eventId, this);
00157 }
00158
00159 void EventViewer::addData(const VariablesDataVector& data)
00160 {
00161 const double elapsedTime = (double)startingTime.msecsTo(QTime::currentTime()) / 1000.;
00162 if (timeWindowCheckBox->isChecked())
00163 {
00164
00165 while (
00166 (!timeStamps.empty()) &&
00167 (elapsedTime - timeStamps[0] > timeWindowLength->value())
00168 )
00169 {
00170 timeStamps.pop_front();
00171 for (size_t i = 0; i < values.size(); i++)
00172 values[i].pop_front();
00173 }
00174 }
00175
00176
00177 timeStamps.push_back(elapsedTime);
00178 for (size_t i = 0; i < values.size(); i++)
00179 {
00180 if (i < data.size())
00181 {
00182 values[i].push_back(data[i]);
00183 }
00184 else
00185 {
00186 values[i].push_back(0);
00187 }
00188 }
00189 plot->replot();
00190 }
00191
00192 void EventViewer::pauseRunCapture()
00193 {
00194 if (isCapturing)
00195 {
00196 if (eventsViewers)
00197 eventsViewers->remove(eventId, this);
00198 isCapturing = false;
00199 status->setText(tr("Paused..."));
00200 pauseRunButton->setIcon(QPixmap(QString(":/images/mix_record.png")));
00201 pauseRunButton->setText(tr("&Record"));
00202 }
00203 else
00204 {
00205 if (eventsViewers)
00206 eventsViewers->insert(eventId, this);
00207 isCapturing = true;
00208 status->setText(tr("Recording..."));
00209 pauseRunButton->setIcon(QPixmap(QString(":/images/pause.png")));
00210 pauseRunButton->setText(tr("&Pause"));
00211 }
00212 }
00213
00214 void EventViewer::clearPlot()
00215 {
00216 for (size_t i = 0; i < values.size(); i++)
00217 values[i].clear();
00218 timeStamps.clear();
00219 plot->replot();
00220 }
00221
00222 void EventViewer::saveToFile()
00223 {
00224 QSettings settings;
00225 QString lastFileName(settings.value("EventViewer/exportFileName", "").toString());
00226 QString fileName = QFileDialog::getSaveFileName(this, tr("Save plot data to file"), lastFileName, "All Files (*);;CSV files (*.csv);;Text files (*.txt)");
00227
00228 QFile file(fileName);
00229 if (!file.open(QFile::WriteOnly | QFile::Truncate))
00230 return;
00231
00232 settings.setValue("EventViewer/exportFileName", fileName);
00233
00234 QTextStream out(&file);
00235 for (size_t i = 0; i < timeStamps.size(); ++i)
00236 {
00237 out << timeStamps[i] << " ";
00238 for (size_t j = 0; j < values.size(); ++j)
00239 {
00240 out << values[j][i];
00241 if (j + 1 < values.size())
00242 out << " ";
00243 }
00244 out << "\n";
00245 }
00246 }
00247
00249 };
00250
00251 #endif // HAVE_QWT