PlotTableWidget.cpp
Go to the documentation of this file.
1 /******************************************************************************
2  * Copyright (C) 2015 by Ralf Kaestner *
3  * ralf.kaestner@gmail.com *
4  * *
5  * This program is free software; you can redistribute it and/or modify *
6  * it under the terms of the Lesser GNU General Public License as published by*
7  * the Free Software Foundation; either version 3 of the License, or *
8  * (at your option) any later version. *
9  * *
10  * This program is distributed in the hope that it will be useful, *
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13  * Lesser GNU General Public License for more details. *
14  * *
15  * You should have received a copy of the Lesser GNU General Public License *
16  * along with this program. If not, see <http://www.gnu.org/licenses/>. *
17  ******************************************************************************/
18 
19 #include <QApplication>
20 #include <QFile>
21 #include <QTextStream>
22 
25 
27 
28 namespace rqt_multiplot {
29 
30 /*****************************************************************************/
31 /* Constructors and Destructor */
32 /*****************************************************************************/
33 
35  QWidget(parent),
36  layout_(new QGridLayout(this)),
37  config_(0),
38  registry_(new MessageSubscriberRegistry(this)),
39  bagReader_(new BagReader(this)) {
40  setLayout(layout_);
41  setAutoFillBackground(true);
42 
43  layout_->setHorizontalSpacing(20);
44  layout_->setVerticalSpacing(20);
45 
46  connect(bagReader_, SIGNAL(readingStarted()), this,
47  SLOT(bagReaderReadingStarted()));
48  connect(bagReader_, SIGNAL(readingProgressChanged(double)), this,
49  SLOT(bagReaderReadingProgressChanged(double)));
50  connect(bagReader_, SIGNAL(readingFinished()), this,
51  SLOT(bagReaderReadingFinished()));
52  connect(bagReader_, SIGNAL(readingFailed(const QString&)), this,
53  SLOT(bagReaderReadingFailed(const QString&)));
54 }
55 
57 }
58 
59 /*****************************************************************************/
60 /* Accessors */
61 /*****************************************************************************/
62 
64  if (config != config_) {
65  if (config_) {
66  disconnect(config_, SIGNAL(backgroundColorChanged(const QColor&)),
67  this, SLOT(configBackgroundColorChanged(const QColor&)));
68  disconnect(config_, SIGNAL(foregroundColorChanged(const QColor&)),
69  this, SLOT(configForegroundColorChanged(const QColor&)));
70  disconnect(config_, SIGNAL(numPlotsChanged(size_t, size_t)), this,
71  SLOT(configNumPlotsChanged(size_t, size_t)));
72  disconnect(config_, SIGNAL(linkScaleChanged(bool)), this,
73  SLOT(configLinkScaleChanged(bool)));
74  disconnect(config_, SIGNAL(trackPointsChanged(bool)), this,
75  SLOT(configTrackPointsChanged(bool)));
76  }
77 
78  config_ = config;
79 
80  if (config) {
81  connect(config, SIGNAL(backgroundColorChanged(const QColor&)),
82  this, SLOT(configBackgroundColorChanged(const QColor&)));
83  connect(config, SIGNAL(foregroundColorChanged(const QColor&)),
84  this, SLOT(configForegroundColorChanged(const QColor&)));
85  connect(config, SIGNAL(numPlotsChanged(size_t, size_t)), this,
86  SLOT(configNumPlotsChanged(size_t, size_t)));
87  connect(config, SIGNAL(linkScaleChanged(bool)), this,
88  SLOT(configLinkScaleChanged(bool)));
89  connect(config, SIGNAL(trackPointsChanged(bool)), this,
90  SLOT(configTrackPointsChanged(bool)));
91 
94  configNumPlotsChanged(config->getNumRows(), config->getNumColumns());
97  }
98  }
99 }
100 
102  return config_;
103 }
104 
106  return plotWidgets_.count();
107 }
108 
110  if (!plotWidgets_.isEmpty())
111  return plotWidgets_[0].count();
112  else
113  return 0;
114 }
115 
116 PlotWidget* PlotTableWidget::getPlotWidget(size_t row, size_t column) const {
117  return plotWidgets_[row][column];
118 }
119 
121  return registry_;
122 }
123 
125  return bagReader_;
126 }
127 
128 /*****************************************************************************/
129 /* Methods */
130 /*****************************************************************************/
131 
133  for (size_t row = 0; row < plotWidgets_.count(); ++row)
134  for (size_t column = 0; column < plotWidgets_[row].count(); ++ column)
135  plotWidgets_[row][column]->run();
136 }
137 
139  for (size_t row = 0; row < plotWidgets_.count(); ++row)
140  for (size_t column = 0; column < plotWidgets_[row].count(); ++ column)
141  plotWidgets_[row][column]->pause();
142 }
143 
145  for (size_t row = 0; row < plotWidgets_.count(); ++row)
146  for (size_t column = 0; column < plotWidgets_[row].count(); ++ column)
147  plotWidgets_[row][column]->clear();
148 }
149 
151  for (size_t row = 0; row < plotWidgets_.count(); ++row)
152  for (size_t column = 0; column < plotWidgets_[row].count(); ++ column)
153  plotWidgets_[row][column]->requestReplot();
154 }
155 
157  for (size_t row = 0; row < plotWidgets_.count(); ++row)
158  for (size_t column = 0; column < plotWidgets_[row].count(); ++ column)
159  plotWidgets_[row][column]->forceReplot();
160 }
161 
162 void PlotTableWidget::renderToPixmap(QPixmap& pixmap) {
163  size_t numRows = getNumRows();
164  size_t numColumns = getNumColumns();
165 
166  if (numRows && numColumns) {
167  double plotWidth = (pixmap.width()-20.0*(numColumns-1.0))/numColumns;
168  double plotHeight = (pixmap.height()-20.0*(numRows-1.0))/numRows;
169 
170  double y = 0.0;
171  for (size_t row = 0; row < plotWidgets_.count();
172  ++row, y += plotHeight+20.0) {
173  double x = 0.0;
174 
175  for (size_t column = 0; column < plotWidgets_[row].count();
176  ++column, x += plotWidth+20.0)
177  plotWidgets_[row][column]->renderToPixmap(pixmap,
178  QRectF(x, y, plotWidth, plotHeight));
179  }
180  }
181 }
182 
184  formattedAxisTitles) {
185  formattedAxisTitles.clear();
186 
187  for (size_t row = 0; row < plotWidgets_.count(); ++row) {
188  for (size_t column = 0; column < plotWidgets_[row].count(); ++column) {
189  QStringList formattedCurveAxisTitles;
190 
191  plotWidgets_[row][column]->writeFormattedCurveAxisTitles(
192  formattedCurveAxisTitles);
193 
194  formattedAxisTitles.append(formattedCurveAxisTitles);
195  }
196  }
197 }
198 
200  formattedData) {
201  formattedData.clear();
202 
203  for (size_t row = 0; row < plotWidgets_.count(); ++row) {
204  for (size_t column = 0; column < plotWidgets_[row].count(); ++column) {
205  QList<QStringList> formattedCurveData;
206 
207  plotWidgets_[row][column]->writeFormattedCurveData(
208  formattedCurveData);
209 
210  formattedData.append(formattedCurveData);
211  }
212  }
213 }
214 
215 void PlotTableWidget::loadFromBagFile(const QString& fileName) {
216  clearPlots();
217 
218  for (size_t row = 0; row < plotWidgets_.count(); ++row)
219  for (size_t column = 0; column < plotWidgets_[row].count(); ++column)
220  plotWidgets_[row][column]->setBroker(bagReader_);
221 
222  runPlots();
223 
224  bagReader_->read(fileName);
225 }
226 
227 void PlotTableWidget::saveToImageFile(const QString& fileName) {
228  QPixmap pixmap(1280, 1024);
229 
230  pixmap.fill(Qt::transparent);
231  renderToPixmap(pixmap);
232 
233  pixmap.save(fileName, "PNG");
234 }
235 
236 void PlotTableWidget::saveToTextFile(const QString& fileName) {
237  QFile file(fileName);
238 
239  if (file.open(QIODevice::WriteOnly)) {
240  QStringList formattedAxisTitles;
241  QList<QStringList> formattedData;
242 
243  writeFormattedCurveAxisTitles(formattedAxisTitles);
244  writeFormattedCurveData(formattedData);
245 
246  QTextStream stream(&file);
247 
248  stream << "# " << formattedAxisTitles.join(", ") << "\n";
249 
250  size_t row = 0;
251 
252  while (true) {
253  QStringList dataLineParts;
254  bool finished = true;
255 
256  for (size_t column = 0; column < formattedData.count(); ++column) {
257  if (row < formattedData[column].count()) {
258  dataLineParts.append(formattedData[column][row]);
259  finished &= false;
260  }
261  else
262  dataLineParts.append(QString());
263  }
264 
265  if (!finished) {
266  stream << dataLineParts.join(", ") << "\n";
267  row++;
268  }
269  else
270  break;
271  }
272  }
273 }
274 
276  PlotWidget* excluded) {
277  BoundingRectangle validBounds = bounds;
278 
279  if (!bounds.isValid()) {
280  BoundingRectangle currentBounds;
281 
282  for (size_t row = 0; row < plotWidgets_.count(); ++row)
283  for (size_t column = 0; column < plotWidgets_[row].count(); ++column)
284  currentBounds += plotWidgets_[row][column]->getCurrentScale();
285 
286  if (bounds.getMaximum().x() <= bounds.getMinimum().x()) {
287  validBounds.getMinimum().setX(currentBounds.getMinimum().x());
288  validBounds.getMaximum().setX(currentBounds.getMaximum().x());
289  }
290 
291  if (bounds.getMaximum().y() <= bounds.getMinimum().y()) {
292  validBounds.getMinimum().setY(currentBounds.getMinimum().y());
293  validBounds.getMaximum().setY(currentBounds.getMaximum().y());
294  }
295  }
296 
297  for (size_t row = 0; row < plotWidgets_.count(); ++row) {
298  for (size_t column = 0; column < plotWidgets_[row].count(); ++column) {
299  if (excluded != plotWidgets_[row][column])
300  plotWidgets_[row][column]->setCurrentScale(validBounds);
301  }
302  }
303 }
304 
305 /*****************************************************************************/
306 /* Slots */
307 /*****************************************************************************/
308 
310  QPalette currentPalette = palette();
311 
312  currentPalette.setColor(QPalette::Window, color);
313  currentPalette.setColor(QPalette::Base, color);
314 
315  setPalette(currentPalette);
316 
317  forceReplot();
318 }
319 
321  QPalette currentPalette = palette();
322 
323  currentPalette.setColor(QPalette::WindowText, color);
324  currentPalette.setColor(QPalette::Text, color);
325 
326  setPalette(currentPalette);
327 }
328 
329 void PlotTableWidget::configNumPlotsChanged(size_t numRows, size_t
330  numColumns) {
331  size_t oldNumRows = plotWidgets_.count();
332  size_t oldNumColumns = oldNumRows ? plotWidgets_[0].count() : 0;
333 
334  if (!numRows || !numColumns) {
335  numRows = 0;
336  numColumns = 0;
337  }
338 
339  QVector<QVector<PlotWidget* > > plotWidgets(numRows);
340  QGridLayout* layout = new QGridLayout();
341 
342  layout->setHorizontalSpacing(20);
343  layout->setVerticalSpacing(20);
344 
345  for (size_t row = 0; row < numRows; ++row) {
346  plotWidgets[row].resize(numColumns);
347 
348  for (size_t column = 0; column < numColumns; ++column) {
349  if ((row < oldNumRows) && (column < oldNumColumns))
350  plotWidgets[row][column] = plotWidgets_[row][column];
351  else {
352  plotWidgets[row][column] = new PlotWidget(this);
353 
354  connect(plotWidgets[row][column], SIGNAL(preferredScaleChanged(
355  const BoundingRectangle&)), this, SLOT(plotPreferredScaleChanged(
356  const BoundingRectangle&)));
357  connect(plotWidgets[row][column], SIGNAL(currentScaleChanged(
358  const BoundingRectangle&)), this, SLOT(plotCurrentScaleChanged(
359  const BoundingRectangle&)));
360  connect(plotWidgets[row][column]->getCursor(), SIGNAL(
361  activeChanged(bool)), this, SLOT(plotCursorActiveChanged(bool)));
362  connect(plotWidgets[row][column]->getCursor(), SIGNAL(
363  currentPositionChanged(const QPointF&)), this, SLOT(
364  plotCursorCurrentPositionChanged(const QPointF&)));
365  connect(plotWidgets[row][column], SIGNAL(pausedChanged(bool)),
366  this, SLOT(plotPausedChanged(bool)));
367  connect(plotWidgets[row][column], SIGNAL(stateChanged(int)),
368  this, SLOT(plotStateChanged(int)));
369  }
370 
371  plotWidgets[row][column]->setConfig(config_->getPlotConfig(
372  row, column));
373  plotWidgets[row][column]->setBroker(registry_);
374 
375  if (config_->isScaleLinked())
376  plotWidgets[row][column]->setCurrentScale(plotWidgets[0][0]->
377  getCurrentScale());
378 
379  plotWidgets[row][column]->getCursor()->setTrackPoints(
381 
382  layout->addWidget(plotWidgets[row][column], row, column);
383  }
384  }
385 
386  if ((numRows == 1) && (numColumns == 1))
387  plotWidgets[0][0]->setCanChangeState(false);
388  else
389  plotWidgets[0][0]->setCanChangeState(true);
390 
391  for (size_t row = 0; row < oldNumRows; ++row)
392  for (size_t column = 0; column < oldNumColumns; ++column)
393  if ((row >= numRows) || (column >= numColumns))
394  delete plotWidgets_[row][column];
395 
396  plotWidgets_ = plotWidgets;
397 
398  delete layout_;
399  layout_ = layout;
400  setLayout(layout);
401 
402  emit plotPausedChanged();
403 }
404 
406  if (link) {
407  BoundingRectangle bounds;
408 
409  for (size_t row = 0; row < plotWidgets_.count(); ++row)
410  for (size_t column = 0; column < plotWidgets_[row].count(); ++ column)
411  bounds += plotWidgets_[row][column]->getPreferredScale();
412 
413  updatePlotScale(bounds);
414  }
415 }
416 
418  for (size_t row = 0; row < plotWidgets_.count(); ++row)
419  for (size_t column = 0; column < plotWidgets_[row].count(); ++ column)
420  plotWidgets_[row][column]->getCursor()->setTrackPoints(track);
421 }
422 
424  emit jobStarted("Reading bag from [file://"+
425  bagReader_->getFileName()+"]...");
426 }
427 
429  emit jobProgressChanged(progress);
430 }
431 
433  pausePlots();
434 
435  for (size_t row = 0; row < plotWidgets_.count(); ++row)
436  for (size_t column = 0; column < plotWidgets_[row].count(); ++column)
437  plotWidgets_[row][column]->setBroker(registry_);
438 
439  emit jobFinished("Read bag from [file://"+
440  bagReader_->getFileName()+"]");
441 }
442 
443 void PlotTableWidget::bagReaderReadingFailed(const QString& error) {
444  pausePlots();
445 
446  for (size_t row = 0; row < plotWidgets_.count(); ++row)
447  for (size_t column = 0; column < plotWidgets_[row].count(); ++column)
448  plotWidgets_[row][column]->setBroker(registry_);
449 
450  emit jobFailed("Failed to read bag from [file://"+
451  bagReader_->getFileName()+"]");
452 }
453 
455  bounds) {
456  if (config_) {
457  if (config_->isScaleLinked()) {
458  BoundingRectangle bounds;
459 
460  for (size_t row = 0; row < plotWidgets_.count(); ++row)
461  for (size_t column = 0; column < plotWidgets_[row].count(); ++ column)
462  bounds += plotWidgets_[row][column]->getPreferredScale();
463 
464  updatePlotScale(bounds);
465  }
466  else
467  static_cast<PlotWidget*>(sender())->setCurrentScale(bounds);
468  }
469 }
470 
472  bounds) {
473  if (config_ && config_->isScaleLinked())
474  updatePlotScale(bounds, static_cast<PlotWidget*>(sender()));
475 }
476 
478  if (config_ && config_->isCursorLinked()) {
479  for (size_t row = 0; row < plotWidgets_.count(); ++row)
480  for (size_t column = 0; column < plotWidgets_[row].count(); ++ column)
481  if (sender() != plotWidgets_[row][column])
482  plotWidgets_[row][column]->getCursor()->setActive(active);
483  }
484 }
485 
487  position) {
488  if (config_ && config_->isCursorLinked()) {
489  for (size_t row = 0; row < plotWidgets_.count(); ++row)
490  for (size_t column = 0; column < plotWidgets_[row].count(); ++ column)
491  if (sender() != plotWidgets_[row][column])
492  plotWidgets_[row][column]->getCursor()->setCurrentPosition(
493  position);
494  }
495 }
496 
498  emit plotPausedChanged();
499 }
500 
502  for (size_t row = 0; row < plotWidgets_.count(); ++row) {
503  for (size_t column = 0; column < plotWidgets_[row].count(); ++ column) {
504  if (state == PlotWidget::Maximized) {
505  if (sender() != plotWidgets_[row][column])
506  plotWidgets_[row][column]->hide();
507  }
508  else if (state == PlotWidget::Normal)
509  plotWidgets_[row][column]->show();
510  }
511  }
512 }
513 
514 }
MessageSubscriberRegistry * getRegistry() const
void read(const QString &fileName)
Definition: BagReader.cpp:77
void bagReaderReadingFailed(const QString &error)
void saveToTextFile(const QString &fileName)
void setConfig(PlotTableConfig *config)
void plotCursorCurrentPositionChanged(const QPointF &position)
void configBackgroundColorChanged(const QColor &color)
const QColor & getForegroundColor() const
void updatePlotScale(const BoundingRectangle &bounds, PlotWidget *excluded=0)
void jobProgressChanged(double progress)
PlotConfig * getPlotConfig(size_t row, size_t column) const
const QColor & getBackgroundColor() const
void configForegroundColorChanged(const QColor &color)
void plotCursorActiveChanged(bool active)
void loadFromBagFile(const QString &fileName)
void writeFormattedCurveData(QList< QStringList > &formattedData)
void jobFinished(const QString &toolTip)
PlotWidget * getPlotWidget(size_t row, size_t column) const
PlotTableWidget(QWidget *parent=0)
void jobFailed(const QString &toolTip)
void plotPreferredScaleChanged(const BoundingRectangle &bounds)
void bagReaderReadingProgressChanged(double progress)
void renderToPixmap(QPixmap &pixmap)
void configNumPlotsChanged(size_t numRows, size_t numColumns)
void jobStarted(const QString &toolTip)
void saveToImageFile(const QString &fileName)
QString getFileName() const
Definition: BagReader.cpp:61
PlotTableConfig * getConfig() const
BagReader * getBagReader() const
MessageSubscriberRegistry * registry_
void writeFormattedCurveAxisTitles(QStringList &formattedAxisTitles)
QVector< QVector< PlotWidget * > > plotWidgets_
void run(ClassLoader *loader)
void configTrackPointsChanged(bool track)
void plotCurrentScaleChanged(const BoundingRectangle &bounds)


rqt_multiplot_plugin
Author(s): Ralf Kaestner
autogenerated on Fri Jan 15 2021 03:47:53