function_editor.cpp
Go to the documentation of this file.
1 #include "function_editor.h"
2 #include "custom_function.h"
3 #include "plotwidget.h"
4 #include <QDebug>
5 #include <QMessageBox>
6 #include <QFont>
7 #include <QDomDocument>
8 #include <QDomElement>
9 #include <QFontDatabase>
10 #include <QFile>
11 #include <QMenu>
12 #include <QAction>
13 #include <QDir>
14 #include <QToolTip>
15 #include <QFileDialog>
16 #include <QFileInfo>
17 #include <QSettings>
18 #include <QByteArray>
19 #include <QInputDialog>
20 #include <QDragEnterEvent>
21 #include <QMouseEvent>
22 #include <QEnterEvent>
23 #include <QMimeData>
24 #include <QTableWidgetItem>
25 #include <QTimer>
26 #include <QSyntaxHighlighter>
27 
28 #include "lua_custom_function.h"
29 #include "svg_util.h"
30 
31 //class Highlighter : public QSyntaxHighlighter
32 //{
33 // Q_OBJECT
34 
35 //public:
36 // Highlighter(QTextDocument *parent = nullptr);
37 
38 //protected:
39 // void highlightBlock(const QString &text) override;
40 
41 //private:
42 // struct HighlightingRule
43 // {
44 // QRegularExpression pattern;
45 // QTextCharFormat format;
46 // };
47 // QVector<HighlightingRule> highlightingRules;
48 
49 // QRegularExpression commentStartExpression;
50 // QRegularExpression commentEndExpression;
51 
52 // QTextCharFormat keywordFormat;
53 // QTextCharFormat classFormat;
54 // QTextCharFormat singleLineCommentFormat;
55 // QTextCharFormat multiLineCommentFormat;
56 // QTextCharFormat quotationFormat;
57 // QTextCharFormat functionFormat;
58 //};
59 
60 
62 {
63  ui->pushButtonDeleteCurves->setIcon(LoadSvgIcon(":/resources/svg/remove_red.svg", theme));
64  ui->buttonLoadFunctions->setIcon(LoadSvgIcon(":/resources/svg/import.svg", theme));
65  ui->buttonSaveFunctions->setIcon(LoadSvgIcon(":/resources/svg/export.svg", theme));
66  ui->buttonSaveCurrent->setIcon(LoadSvgIcon(":/resources/svg/save.svg", theme));
67 }
68 
70  const CustomPlotMap& mapped_custom_plots,
71  QWidget* parent)
72  : QWidget(parent)
73  , _plot_map_data(plotMapData)
74  , _custom_plots(mapped_custom_plots)
75  , ui(new Ui::FunctionEditor)
76  , _v_count(1)
78 {
79  ui->setupUi(this);
80 
81  QSettings settings;
82 
83  this->setWindowTitle("Create a custom timeseries");
84 
85  QFont fixedFont = QFontDatabase::systemFont(QFontDatabase::FixedFont);
86  fixedFont.setPointSize(10);
87 
88  ui->globalVarsTextField->setFont(fixedFont);
89  ui->mathEquation->setFont(fixedFont);
90  ui->snippetPreview->setFont(fixedFont);
91 
92  auto theme = settings.value("StyleSheet:theme", "ligth").toString();
93  on_stylesheetChanged(theme);
94 
95  QPalette palette = ui->listAdditionalSources->palette();
96  palette.setBrush(QPalette::Highlight, palette.brush(QPalette::Base));
97  palette.setBrush(QPalette::HighlightedText, palette.brush(QPalette::Text));
98  ui->listAdditionalSources->setPalette(palette);
99 
100  QStringList numericPlotNames;
101  for (const auto& p : _plot_map_data.numeric)
102  {
103  QString name = QString::fromStdString(p.first);
104  numericPlotNames.push_back(name);
105  }
106  numericPlotNames.sort(Qt::CaseInsensitive);
107 
108  QByteArray saved_xml = settings.value("AddCustomPlotDialog.recentSnippetsXML", QByteArray()).toByteArray();
109  restoreGeometry(settings.value("AddCustomPlotDialog.geometry").toByteArray());
110 
111  if (saved_xml.isEmpty())
112  {
113  QFile file("://resources/default.snippets.xml");
114  if (!file.open(QIODevice::ReadOnly))
115  {
116  throw std::runtime_error("problem with default.snippets.xml");
117  }
118  saved_xml = file.readAll();
119  }
120 
121  importSnippets(saved_xml);
122 
123  ui->snippetsListSaved->setContextMenuPolicy(Qt::CustomContextMenu);
124 
125  connect(ui->snippetsListSaved, &QListWidget::customContextMenuRequested, this,
127 
128  ui->globalVarsTextField->setPlainText(settings.value("AddCustomPlotDialog.previousGlobals", "").toString());
129 
130  ui->mathEquation->setPlainText(settings.value("AddCustomPlotDialog.previousFunction", "return value").toString());
131 
132  ui->lineEditSource->installEventFilter(this);
133  ui->listAdditionalSources->installEventFilter(this);
134 
135  auto preview_layout = new QHBoxLayout( ui->framePlotPreview);
136  preview_layout->setMargin(6);
137  preview_layout->addWidget(_preview_widget);
138 
140 
141  _update_preview_timer.setSingleShot(true);
142 
143  connect(&_update_preview_timer, &QTimer::timeout,
145 
146  updatePreview();
147 }
148 
150 {
151  QSettings settings;
152  settings.setValue("AddCustomPlotDialog.recentSnippetsXML", exportSnippets());
153  settings.setValue("AddCustomPlotDialog.geometry", saveGeometry());
154  settings.setValue("AddCustomPlotDialog.previousGlobals", ui->globalVarsTextField->toPlainText());
155  settings.setValue("AddCustomPlotDialog.previousFunction", ui->mathEquation->toPlainText());
156 
157  delete ui;
158 }
159 
160 void FunctionEditorWidget::setLinkedPlotName(const QString& linkedPlotName)
161 {
162  ui->lineEditSource->setText(linkedPlotName);
163 }
164 
166 {
167  ui->lineEditSource->setText("");
168  ui->nameLineEdit->setText("");
169  ui->listAdditionalSources->setRowCount(0);
170 }
171 
172 
174 {
175  return ui->lineEditSource->text();
176 }
177 
179 {
180  return ui->globalVarsTextField->toPlainText();
181 }
182 
184 {
185  return ui->mathEquation->toPlainText();
186 }
187 
189 {
190  return ui->nameLineEdit->text();
191 }
192 
194 {
195  ui->nameLineEdit->setEnabled(true);
196  ui->lineEditSource->setEnabled(true);
198 }
199 
200 
202 {
203  ui->globalVarsTextField->setPlainText(data->snippet().globalVars);
204  ui->mathEquation->setPlainText(data->snippet().function);
205  setLinkedPlotName(QString::fromStdString(data->linkedPlotName()));
206  ui->nameLineEdit->setText(QString::fromStdString(data->name()));
207  ui->nameLineEdit->setEnabled(false);
208 
210 
211  auto list_widget = ui->listAdditionalSources;
212  list_widget->setRowCount(0);
213 
214  for (QString curve_name: data->snippet().additionalSources) {
215  if( list_widget->findItems(curve_name, Qt::MatchExactly).isEmpty() &&
216  curve_name != ui->lineEditSource->text() )
217  {
218  int row = list_widget->rowCount();
219  list_widget->setRowCount(row+1);
220  list_widget->setItem(row,0, new QTableWidgetItem( QString("v%1").arg(row+1)));
221  list_widget->setItem(row,1, new QTableWidgetItem(curve_name));
222  }
223  }
225 }
226 
227 //CustomPlotPtr FunctionEditorWidget::getCustomPlotData() const
228 //{
229 // return _plot;
230 //}
231 
232 bool FunctionEditorWidget::eventFilter(QObject *obj, QEvent *ev)
233 {
234  if( ev->type() == QEvent::DragEnter )
235  {
236  auto event = static_cast<QDragEnterEvent*>(ev);
237  const QMimeData* mimeData = event->mimeData();
238  QStringList mimeFormats = mimeData->formats();
239 
240  for(const QString& format : mimeFormats)
241  {
242  QByteArray encoded = mimeData->data(format);
243  QDataStream stream(&encoded, QIODevice::ReadOnly);
244 
245  if (format != "curveslist/add_curve")
246  {
247  return false;
248  }
249 
250  _dragging_curves.clear();
251 
252  while (!stream.atEnd())
253  {
254  QString curve_name;
255  stream >> curve_name;
256  if (!curve_name.isEmpty())
257  {
258  _dragging_curves.push_back(curve_name);
259  }
260  }
261  if( (obj == ui->lineEditSource && _dragging_curves.size() == 1)
262  || (obj == ui->listAdditionalSources && _dragging_curves.size() > 0) )
263  {
264  event->acceptProposedAction();
265  return true;
266  }
267  }
268  }
269  else if ( ev->type() == QEvent::Drop ) {
270  if( obj == ui->lineEditSource )
271  {
272  ui->lineEditSource->setText( _dragging_curves.front() );
273  }
274  else if ( obj == ui->listAdditionalSources )
275  {
276  auto list_widget = ui->listAdditionalSources;
277  for (QString curve_name: _dragging_curves) {
278  if( list_widget->findItems(curve_name, Qt::MatchExactly).isEmpty() &&
279  curve_name != ui->lineEditSource->text() )
280  {
281  int row = list_widget->rowCount();
282  list_widget->setRowCount(row+1);
283  list_widget->setItem(row,0, new QTableWidgetItem( QString("v%1").arg(row+1)));
284  list_widget->setItem(row,1, new QTableWidgetItem(curve_name));
285  }
286  }
288  }
289  }
290 
291  return false;
292 }
293 
294 void FunctionEditorWidget::importSnippets(const QByteArray& xml_text)
295 {
296  ui->snippetsListSaved->clear();
297 
299 
300  for (const auto& it : _snipped_saved)
301  {
302  ui->snippetsListSaved->addItem(it.first);
303  }
304 
305  for (const auto& custom_it : _custom_plots)
306  {
307  const auto& math_plot = custom_it.second;
308  SnippetData snippet;
309  snippet.name = QString::fromStdString(math_plot->name());
310 
311  if (_snipped_saved.count(snippet.name) > 0)
312  {
313  continue;
314  }
315 
316  snippet.globalVars = math_plot->snippet().globalVars;
317  snippet.function = math_plot->snippet().function;
318  }
319  ui->snippetsListSaved->sortItems();
320 }
321 
323 {
324  QDomDocument doc;
325  auto root = ExportSnippets(_snipped_saved, doc);
326  doc.appendChild(root);
327  return doc.toByteArray(2);
328 }
329 
331 {
332  if (current_row < 0)
333  {
334  ui->snippetPreview->setPlainText("");
335  return;
336  }
337  const auto& name = ui->snippetsListSaved->currentItem()->text();
338  const SnippetData& snippet = _snipped_saved.at(name);
339 
340  QString preview;
341 
342  if( !snippet.globalVars.isEmpty() )
343  {
344  preview += snippet.globalVars + "\n\n";
345  }
346  preview += "function calc(time, value";
347 
348  for (int i=1; i<= snippet.additionalSources.size(); i++)
349  {
350  preview += QString(", v%1").arg(i);
351  }
352 
353  preview += ")\n";
354  auto function_lines = snippet.function.split("\n");
355  for (const auto& line: function_lines)
356  {
357  preview += " " + line + "\n";
358  }
359  preview += "end";
360  ui->snippetPreview->setPlainText(preview);
361 }
362 
364 {
365  const auto& name = ui->snippetsListSaved->item(index.row())->text();
366  const SnippetData& snippet = _snipped_saved.at(name);
367 
368  ui->globalVarsTextField->setPlainText(snippet.globalVars);
369  ui->mathEquation->setPlainText(snippet.function);
370 }
371 
373 {
374  auto list_saved = ui->snippetsListSaved;
375 
376  if (list_saved->selectedItems().size() != 1)
377  {
378  return;
379  }
380 
381  QMenu menu;
382 
383  QAction* rename_item = new QAction("Rename...", this);
384  menu.addAction(rename_item);
385 
386  connect(rename_item, &QAction::triggered, this, &FunctionEditorWidget::onRenameSaved);
387 
388  QAction* remove_item = new QAction("Remove", this);
389  menu.addAction(remove_item);
390 
391  connect(remove_item, &QAction::triggered, this, [list_saved, this]() {
392  const auto& item = list_saved->selectedItems().first();
393  _snipped_saved.erase(item->text());
394  delete list_saved->takeItem(list_saved->row(item));
395  });
396 
397  menu.exec(list_saved->mapToGlobal(pos));
398 }
399 
401 {
402  if (_plot_map_data.numeric.count(name.toStdString()) == 0)
403  {
404  ui->pushButtonCreate->setText("Create New Timeseries");
405  }
406  else
407  {
408  ui->pushButtonCreate->setText("Modify Timeseries");
409  }
410  updatePreview();
411 }
412 
414 {
415  QSettings settings;
416  QString directory_path = settings.value("AddCustomPlotDialog.loadDirectory", QDir::currentPath()).toString();
417 
418  QString fileName =
419  QFileDialog::getOpenFileName(this, tr("Open Snippet Library"),
420  directory_path,
421  tr("Snippets (*.snippets.xml)"));
422  if (fileName.isEmpty())
423  {
424  return;
425  }
426 
427  QFile file(fileName);
428 
429  if (!file.open(QIODevice::ReadOnly))
430  {
431  QMessageBox::critical(this, "Error", QString("Failed to open the file [%1]").arg(fileName));
432  return;
433  }
434 
435  directory_path = QFileInfo(fileName).absolutePath();
436  settings.setValue("AddCustomPlotDialog.loadDirectory", directory_path);
437 
438  importSnippets(file.readAll());
439 }
440 
442 {
443  QSettings settings;
444  QString directory_path = settings.value("AddCustomPlotDialog.loadDirectory",
445  QDir::currentPath()).toString();
446 
447  QString fileName =
448  QFileDialog::getSaveFileName(this, tr("Open Snippet Library"),
449  directory_path,
450  tr("Snippets (*.snippets.xml)"));
451 
452  if (fileName.isEmpty())
453  {
454  return;
455  }
456  if (!fileName.endsWith(".snippets.xml"))
457  {
458  fileName.append(".snippets.xml");
459  }
460 
461  QFile file(fileName);
462  if (!file.open(QIODevice::WriteOnly))
463  {
464  QMessageBox::critical(this, "Error", QString("Failed to open the file [%1]").arg(fileName));
465  return;
466  }
467  auto data = exportSnippets();
468 
469  file.write(data);
470  file.close();
471 }
472 
474 {
475  QString name;
476 
477  auto selected_snippets = ui->snippetsListSaved->selectedItems();
478  if( selected_snippets.size() >= 1 )
479  {
480  name = selected_snippets.front()->text();
481  }
482  bool ok = false;
483  name = QInputDialog::getText(this, tr("Name of the Function"),
484  tr("Name:"), QLineEdit::Normal,
485  name, &ok);
486 
487  if (!ok || name.isEmpty()) {
488  return;
489  }
490 
491  SnippetData snippet;
492  snippet.name = name;
493  snippet.globalVars = ui->globalVarsTextField->toPlainText();
494  snippet.function = ui->mathEquation->toPlainText();
495 
496  addToSaved(name, snippet);
497 
498  on_snippetsListSaved_currentRowChanged(ui->snippetsListSaved->currentRow());
499 }
500 
501 bool FunctionEditorWidget::addToSaved(const QString& name, const SnippetData& snippet)
502 {
503  if (_snipped_saved.count(name))
504  {
505  QMessageBox msgBox(this);
506  msgBox.setWindowTitle("Warning");
507  msgBox.setText(tr("A function with the same name exists already in the list of saved functions.\n"));
508  msgBox.addButton(QMessageBox::Cancel);
509  QPushButton* button = msgBox.addButton(tr("Overwrite"), QMessageBox::YesRole);
510  msgBox.setDefaultButton(button);
511 
512  int res = msgBox.exec();
513 
514  if (res < 0 || res == QMessageBox::Cancel)
515  {
516  return false;
517  }
518  }
519  else
520  {
521  ui->snippetsListSaved->addItem(name);
522  ui->snippetsListSaved->sortItems();
523  }
524  _snipped_saved[name] = snippet;
525  return true;
526 }
527 
529 {
530  auto list_saved = ui->snippetsListSaved;
531  auto item = list_saved->selectedItems().first();
532  const auto& name = item->text();
533 
534  bool ok;
535  QString new_name =
536  QInputDialog::getText(this, tr("Change the name of the function"), tr("New name:"), QLineEdit::Normal, name, &ok);
537 
538  if (!ok || new_name.isEmpty() || new_name == name)
539  {
540  return;
541  }
542 
543  SnippetData snippet = _snipped_saved[name];
544  _snipped_saved.erase(name);
545  snippet.name = new_name;
546 
547  _snipped_saved.insert({ new_name, snippet });
548  item->setText(new_name);
549  ui->snippetsListSaved->sortItems();
550 }
551 
553 {
554  try
555  {
556  std::string new_plot_name = getName().toStdString();
557 
558  if (_editor_mode == CREATE && _custom_plots.count(new_plot_name) != 0)
559  {
560  QMessageBox msgBox(this);
561  msgBox.setWindowTitle("Warning");
562  msgBox.setText(tr("A custom time series with the same name exists already.\n"
563  " Do you want to overwrite it?\n"));
564  msgBox.addButton(QMessageBox::Cancel);
565  QPushButton* button = msgBox.addButton(tr("Overwrite"), QMessageBox::YesRole);
566  msgBox.setDefaultButton(button);
567 
568  int res = msgBox.exec();
569 
570  if (res < 0 || res == QMessageBox::Cancel)
571  {
572  return;
573  }
574  }
575 
576  SnippetData snippet;
577  snippet.function = getEquation();
578  snippet.globalVars = getGlobalVars();
579  snippet.name = getName();
580  snippet.linkedSource = getLinkedData();
581  for(int row = 0; row < ui->listAdditionalSources->rowCount(); row++)
582  {
583  snippet.additionalSources.push_back( ui->listAdditionalSources->item(row,1)->text());
584  }
585 
586  CustomPlotPtr plot = std::make_unique<LuaCustomFunction>(snippet);
587  accept(plot);
588  }
589  catch (const std::runtime_error& e)
590  {
591  QMessageBox::critical(this, "Error", "Failed to create math plot : " + QString::fromStdString(e.what()));
592  }
593 }
594 
595 
597 {
598  if( _editor_mode == MODIFY )
599  {
600  clear();
601  }
602  closed();
603 }
604 
605 
607 {
608  QString function_text("function( time, value");
609  for(int row = 0; row < ui->listAdditionalSources->rowCount(); row++)
610  {
611  function_text += ", ";
612  function_text += ui->listAdditionalSources->item(row,0)->text();
613  }
614  function_text += " )";
615  ui->labelFunction->setText(function_text);
616 
617  updatePreview();
618 }
619 
621 {
622  bool any_selected = !ui->listAdditionalSources->selectedItems().isEmpty();
623  ui->pushButtonDeleteCurves->setEnabled(any_selected);
624 }
625 
627 {
628  auto list_sources = ui->listAdditionalSources;
629  QModelIndexList selected = list_sources->selectionModel()->selectedRows();
630  while( selected.size() > 0 )
631  {
632  list_sources->removeRow( selected.first().row() );
633  selected = list_sources->selectionModel()->selectedRows();
634  }
635  for( int row = 0; row < list_sources->rowCount(); row++ )
636  {
637  list_sources->item(row,0)->setText( QString("v%1").arg(row+1) );
638  }
639 
642 }
643 
645 {
646  updatePreview();
647 }
648 
650 {
651  updatePreview();
652 }
653 
655 {
656  _update_preview_timer.start(250);
657 }
658 
660 {
661  QString errors;
662  std::string new_plot_name = ui->nameLineEdit->text().toStdString();
663 
664  if ( _custom_plots.count(new_plot_name) != 0 )
665  {
666  if( ui->lineEditSource->text().toStdString() == new_plot_name ||
667  ui->listAdditionalSources->findItems(getName(), Qt::MatchExactly).isEmpty() == false )
668  {
669  errors += "- The name of the new timeseries is the same of one of its dependencies.\n";
670  }
671  }
672 
673  if( new_plot_name.empty() ) {
674  errors+= "- Missing name of the new time series.\n";
675  }
676  else{
677  // check if name is unique (except if is custom_plot)
678  if (_plot_map_data.numeric.count(new_plot_name) != 0 && _custom_plots.count(new_plot_name) == 0)
679  {
680  errors+= "- Plot name already exists and can't be modified.\n";
681  }
682  }
683 
684  if( ui->lineEditSource->text().isEmpty() )
685  {
686  errors+= "- Missing source time series.\n";
687  }
688 
689  SnippetData snippet;
690  snippet.function = getEquation();
691  snippet.globalVars = getGlobalVars();
692  snippet.name = getName();
693  snippet.linkedSource = getLinkedData();
694  for(int row = 0; row < ui->listAdditionalSources->rowCount(); row++)
695  {
696  snippet.additionalSources.push_back( ui->listAdditionalSources->item(row,1)->text());
697  }
698 
699  CustomPlotPtr plot;
700  try {
701  plot = std::make_unique<LuaCustomFunction>(snippet);
702  ui->buttonSaveCurrent->setEnabled(true);
703  } catch (...)
704  {
705  errors+= "- The Lua function is not valid.\n";
706  ui->buttonSaveCurrent->setEnabled(false);
707  }
708 
709  if( plot )
710  {
711  try {
712  std::string name = new_plot_name.empty() ? "no_name" : new_plot_name;
713  PlotData& out_data = _local_plot_data.addNumeric(name)->second;
714  out_data.clear();
715  plot->calculate(_plot_map_data, &out_data);
716 
718  _preview_widget->addCurve(name, Qt::blue);
719  _preview_widget->zoomOut(false);
720  } catch (...) {
721  errors+= "- The Lua function can not compute the result.\n";
722  }
723  }
724  //----------------------------------
725 
726  QFile file(":/resources/svg/red_circle.svg");
727 
728  if( errors.isEmpty() )
729  {
730  errors = "Everything is fine :)";
731  file.setFileName(":/resources/svg/green_circle.svg");
732  ui->pushButtonCreate->setEnabled(true);
733  }
734  else{
735  errors = errors.left( errors.size()-1 );
736  ui->pushButtonCreate->setEnabled(false);
737  }
738 
739  ui->labelSemaphore->setToolTip(errors);
740  ui->labelSemaphore->setToolTipDuration(5000);
741 
742  file.open(QFile::ReadOnly | QFile::Text);
743  auto svg_data = file.readAll();
744  file.close();
745  QByteArray content(svg_data);
746  QSvgRenderer rr( content );
747  QImage image(26, 26, QImage::Format_ARGB32);
748  QPainter painter(&image);
749  image.fill(Qt::transparent);
750  rr.render(&painter);
751  ui->labelSemaphore->setPixmap( QPixmap::fromImage(image) );
752 }
753 
755 {
756  updatePreview();
757 }
const CustomPlotMap & _custom_plots
QString getEquation() const
errors
Definition: MQTTPacket.h:37
FunctionEditorWidget(PlotDataMapRef &plotMapData, const CustomPlotMap &mapped_custom_plots, QWidget *parent)
void setLinkedPlotName(const QString &linkedPlotName)
void removeAllCurves()
Definition: plotwidget.cpp:743
FMT_INLINE std::basic_string< Char > format(const S &format_str, Args &&...args)
Definition: core.h:2081
QString getLinkedData() const
void importSnippets(const QByteArray &xml_text)
void on_stylesheetChanged(QString theme)
QString globalVars
QIcon LoadSvgIcon(QString filename, QString style_name="light")
Definition: svg_util.h:17
QString getName() const
void on_nameLineEdit_textChanged(const QString &arg1)
std::unordered_map< std::string, PlotData > numeric
Definition: plotdata.h:495
void on_lineEditSource_textChanged(const QString &text)
void savedContextMenu(const QPoint &pos)
virtual ~FunctionEditorWidget() override
QString linkedSource
QStringList _dragging_curves
QDomElement ExportSnippets(const SnippetsMap &snippets, QDomDocument &doc)
void editExistingPlot(CustomPlotPtr data)
void on_globalVarsTextField_textChanged()
QString function
void zoomOut(bool emit_signal)
Ui::FunctionEditor * ui
bool addToSaved(const QString &name, const SnippetData &snippet)
std::shared_ptr< CustomFunction > CustomPlotPtr
PlotDataMapRef _local_plot_data
void on_snippetsListSaved_currentRowChanged(int currentRow)
SnippetsMap GetSnippetsFromXML(const QString &xml_text)
CurveInfo * addCurve(const std::string &name, QColor color=Qt::transparent)
Definition: plotwidget.cpp:369
PlotWidget * _preview_widget
QString getGlobalVars() const
void on_snippetsListSaved_doubleClicked(const QModelIndex &index)
const char * name
detail::named_arg< Char, T > arg(const Char *name, const T &arg)
Definition: core.h:1656
std::unordered_map< std::string, CustomPlotPtr > CustomPlotMap
bool eventFilter(QObject *obj, QEvent *event) override
SnippetsMap _snipped_saved
void setContextMenuEnabled(bool enabled)
Definition: plotwidget.cpp:227
void accept(CustomPlotPtr plot)
PlotDataMapRef & _plot_map_data
std::unordered_map< std::string, PlotData >::iterator addNumeric(const std::string &name)
Definition: plotdata.h:498
QByteArray exportSnippets() const
QStringList additionalSources
dictionary data
Definition: mqtt_test.py:22
void on_listAdditionalSources_itemSelectionChanged()
void on_pushButtonDeleteCurves_clicked()


plotjuggler
Author(s): Davide Faconti
autogenerated on Sun Dec 6 2020 03:47:34