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 <QListWidget>
27 #include <QListWidgetItem>
28 #include <QSyntaxHighlighter>
29 
30 #include "QLuaHighlighter"
31 
32 #include "lua_custom_function.h"
33 #include "PlotJuggler/svg_util.h"
34 #include "ui_function_editor_help.h"
35 #include "stylesheet.h"
36 
38 {
39  ui->pushButtonDeleteCurves->setIcon(LoadSvg(":/resources/svg/trash.svg", theme));
40  ui->buttonLoadFunctions->setIcon(LoadSvg(":/resources/svg/import.svg", theme));
41  ui->buttonSaveFunctions->setIcon(LoadSvg(":/resources/svg/export.svg", theme));
42  ui->buttonSaveCurrent->setIcon(LoadSvg(":/resources/svg/save.svg", theme));
43 
44  auto style = GetLuaSyntaxStyle(theme);
45 
46  ui->globalVarsText->setSyntaxStyle(style);
47  ui->globalVarsTextBatch->setSyntaxStyle(style);
48 
49  ui->functionText->setSyntaxStyle(style);
50  ui->functionTextBatch->setSyntaxStyle(style);
51 }
52 
54  const TransformsMap& mapped_custom_plots,
55  QWidget* parent)
56  : QWidget(parent)
57  , _plot_map_data(plotMapData)
58  , _transform_maps(mapped_custom_plots)
59  , ui(new Ui::FunctionEditor)
60  , _v_count(1)
61  , _preview_widget(new PlotWidget(_local_plot_data, this))
62 {
63  ui->setupUi(this);
64 
65  ui->globalVarsText->setHighlighter(new QLuaHighlighter);
66  ui->globalVarsTextBatch->setHighlighter(new QLuaHighlighter);
67 
68  ui->functionText->setHighlighter(new QLuaHighlighter);
69  ui->functionTextBatch->setHighlighter(new QLuaHighlighter);
70 
71  lua_completer_ = new QLuaCompleter(this);
73 
74  ui->globalVarsText->setCompleter(lua_completer_);
75  ui->globalVarsTextBatch->setCompleter(lua_completer_);
76 
77  ui->functionText->setCompleter(lua_completer_batch_);
78  ui->functionTextBatch->setCompleter(lua_completer_batch_);
79 
80  QSettings settings;
81 
82  this->setWindowTitle("Create a custom timeseries");
83 
84  QFont fixedFont = QFontDatabase::systemFont(QFontDatabase::FixedFont);
85  fixedFont.setPointSize(10);
86 
87  ui->globalVarsText->setFont(fixedFont);
88  ui->functionText->setFont(fixedFont);
89  ui->globalVarsTextBatch->setFont(fixedFont);
90  ui->functionTextBatch->setFont(fixedFont);
91  ui->snippetPreview->setFont(fixedFont);
92 
93  auto theme = settings.value("StyleSheet::theme", "light").toString();
94  on_stylesheetChanged(theme);
95 
96  QPalette palette = ui->listAdditionalSources->palette();
97  palette.setBrush(QPalette::Highlight, palette.brush(QPalette::Base));
98  palette.setBrush(QPalette::HighlightedText, palette.brush(QPalette::Text));
99  ui->listAdditionalSources->setPalette(palette);
100 
101  QStringList numericPlotNames;
102  for (const auto& p : _plot_map_data.numeric)
103  {
104  QString name = QString::fromStdString(p.first);
105  numericPlotNames.push_back(name);
106  }
107  numericPlotNames.sort(Qt::CaseInsensitive);
108 
109  QByteArray saved_xml =
110  settings.value("FunctionEditorWidget.recentSnippetsXML", QByteArray())
111  .toByteArray();
112  restoreGeometry(settings.value("FunctionEditorWidget.geometry").toByteArray());
113 
114  if (saved_xml.isEmpty())
115  {
116  QFile file("://resources/default.snippets.xml");
117  if (!file.open(QIODevice::ReadOnly))
118  {
119  throw std::runtime_error("problem with default.snippets.xml");
120  }
121  saved_xml = file.readAll();
122  }
123 
124  importSnippets(saved_xml);
125 
126  ui->snippetsListSaved->setContextMenuPolicy(Qt::CustomContextMenu);
127 
128  connect(ui->snippetsListSaved, &QListWidget::customContextMenuRequested, this,
130 
131  ui->globalVarsText->setPlainText(
132  settings.value("FunctionEditorWidget.previousGlobals", "").toString());
133  ui->globalVarsTextBatch->setPlainText(
134  settings.value("FunctionEditorWidget.previousGlobalsBatch", "").toString());
135 
136  ui->functionText->setPlainText(
137  settings.value("FunctionEditorWidget.previousFunction", "return value").toString());
138  ui->functionTextBatch->setPlainText(
139  settings.value("FunctionEditorWidget.previousFunctionBatch", "return value")
140  .toString());
141 
142  ui->lineEditSource->installEventFilter(this);
143  ui->listAdditionalSources->installEventFilter(this);
144  ui->lineEditTab2Filter->installEventFilter(this);
145 
146  auto preview_layout = new QHBoxLayout(ui->framePlotPreview);
147  preview_layout->setMargin(6);
148  preview_layout->addWidget(_preview_widget);
149 
151 
153  onUpdatePreview();
156 
158 
159  int batch_filter_type = settings.value("FunctionEditorWidget.filterType", 2).toInt();
160  switch (batch_filter_type)
161  {
162  case 1:
163  ui->radioButtonContains->setChecked(true);
164  break;
165  case 2:
166  ui->radioButtonWildcard->setChecked(true);
167  break;
168  case 3:
169  ui->radioButtonRegExp->setChecked(true);
170  break;
171  }
172 
173  bool use_batch_prefix =
174  settings.value("FunctionEditorWidget.batchPrefix", false).toBool();
175  ui->radioButtonPrefix->setChecked(use_batch_prefix);
176 }
177 
179 {
180  QSettings settings;
181  settings.setValue("FunctionEditorWidget.recentSnippetsXML", exportSnippets());
182  settings.setValue("FunctionEditorWidget.geometry", saveGeometry());
183 
184  settings.setValue("FunctionEditorWidget.previousGlobals",
185  ui->globalVarsText->toPlainText());
186  settings.setValue("FunctionEditorWidget.previousGlobalsBatch",
187  ui->globalVarsTextBatch->toPlainText());
188 
189  settings.setValue("FunctionEditorWidget.previousFunction",
190  ui->functionText->toPlainText());
191  settings.setValue("FunctionEditorWidget.previousFunctionBatch",
192  ui->functionTextBatch->toPlainText());
193  int batch_filter_type = 0;
194  if (ui->radioButtonContains->isChecked())
195  {
196  batch_filter_type = 1;
197  }
198  else if (ui->radioButtonWildcard->isChecked())
199  {
200  batch_filter_type = 2;
201  }
202  if (ui->radioButtonRegExp->isChecked())
203  {
204  batch_filter_type = 3;
205  }
206  settings.setValue("FunctionEditorWidget.filterType", batch_filter_type);
207 
208  settings.setValue("FunctionEditorWidget.batchPrefix",
209  ui->radioButtonPrefix->isChecked());
210 }
211 
213 {
214  delete _preview_widget;
215 
216  saveSettings();
217 
218  delete ui;
219 }
220 
221 void FunctionEditorWidget::setLinkedPlotName(const QString& linkedPlotName)
222 {
223  ui->lineEditSource->setText(linkedPlotName);
224 }
225 
227 {
228  ui->lineEditSource->setText("");
229  ui->nameLineEdit->setText("");
230  ui->listAdditionalSources->setRowCount(0);
231 
232  ui->suffixLineEdit->setText("");
233  ui->listBatchSources->clear();
234  ui->lineEditTab2Filter->setText("");
235 }
236 
238 {
239  return ui->lineEditSource->text();
240 }
241 
243 {
244  ui->nameLineEdit->setEnabled(true);
245  ui->lineEditSource->setEnabled(true);
247 }
248 
250 {
251  ui->globalVarsText->setPlainText(data->snippet().global_vars);
252  ui->functionText->setPlainText(data->snippet().function);
253  setLinkedPlotName(data->snippet().linked_source);
254  ui->nameLineEdit->setText(data->aliasName());
255  ui->nameLineEdit->setEnabled(false);
256 
258 
259  auto list_widget = ui->listAdditionalSources;
260  list_widget->setRowCount(0);
261 
262  for (QString curve_name : data->snippet().additional_sources)
263  {
264  if (list_widget->findItems(curve_name, Qt::MatchExactly).isEmpty() &&
265  curve_name != ui->lineEditSource->text())
266  {
267  int row = list_widget->rowCount();
268  list_widget->setRowCount(row + 1);
269  list_widget->setItem(row, 0, new QTableWidgetItem(QString("v%1").arg(row + 1)));
270  list_widget->setItem(row, 1, new QTableWidgetItem(curve_name));
271  }
272  }
274 }
275 
276 // CustomPlotPtr FunctionEditorWidget::getCustomPlotData() const
277 //{
278 // return _plot;
279 //}
280 
281 bool FunctionEditorWidget::eventFilter(QObject* obj, QEvent* ev)
282 {
283  if (ev->type() == QEvent::DragEnter)
284  {
285  auto event = static_cast<QDragEnterEvent*>(ev);
286  const QMimeData* mimeData = event->mimeData();
287  QStringList mimeFormats = mimeData->formats();
288 
289  for (const QString& format : mimeFormats)
290  {
291  QByteArray encoded = mimeData->data(format);
292  QDataStream stream(&encoded, QIODevice::ReadOnly);
293 
294  if (format != "curveslist/add_curve")
295  {
296  return false;
297  }
298 
299  _dragging_curves.clear();
300 
301  while (!stream.atEnd())
302  {
303  QString curve_name;
304  stream >> curve_name;
305  if (!curve_name.isEmpty())
306  {
307  _dragging_curves.push_back(curve_name);
308  }
309  }
310  if ((obj == ui->lineEditSource && _dragging_curves.size() == 1) ||
311  (obj == ui->lineEditTab2Filter && _dragging_curves.size() == 1) ||
312  (obj == ui->listAdditionalSources && _dragging_curves.size() > 0))
313  {
314  event->acceptProposedAction();
315  return true;
316  }
317  }
318  }
319  else if (ev->type() == QEvent::Drop)
320  {
321  if (obj == ui->lineEditSource)
322  {
323  ui->lineEditSource->setText(_dragging_curves.front());
324  }
325  else if (obj == ui->lineEditTab2Filter)
326  {
327  ui->lineEditTab2Filter->setText(_dragging_curves.front());
328  }
329  else if (obj == ui->listAdditionalSources)
330  {
331  auto list_widget = ui->listAdditionalSources;
332  for (QString curve_name : _dragging_curves)
333  {
334  if (list_widget->findItems(curve_name, Qt::MatchExactly).isEmpty() &&
335  curve_name != ui->lineEditSource->text())
336  {
337  int row = list_widget->rowCount();
338  list_widget->setRowCount(row + 1);
339  list_widget->setItem(row, 0, new QTableWidgetItem(QString("v%1").arg(row + 1)));
340  list_widget->setItem(row, 1, new QTableWidgetItem(curve_name));
341  }
342  }
344  }
345  }
346 
347  return false;
348 }
349 
350 void FunctionEditorWidget::importSnippets(const QByteArray& xml_text)
351 {
352  ui->snippetsListSaved->clear();
353 
355 
356  for (const auto& it : _snipped_saved)
357  {
358  ui->snippetsListSaved->addItem(it.first);
359  }
360 
361  for (const auto& custom_it : _transform_maps)
362  {
363  auto math_plot = dynamic_cast<LuaCustomFunction*>(custom_it.second.get());
364  if (!math_plot)
365  {
366  continue;
367  }
368  SnippetData snippet;
369  snippet.alias_name = math_plot->aliasName();
370 
371  if (_snipped_saved.count(snippet.alias_name) > 0)
372  {
373  continue;
374  }
375 
376  snippet.global_vars = math_plot->snippet().global_vars;
377  snippet.function = math_plot->snippet().function;
378  }
379  ui->snippetsListSaved->sortItems();
380 }
381 
383 {
384  QDomDocument doc;
385  auto root = ExportSnippets(_snipped_saved, doc);
386  doc.appendChild(root);
387  return doc.toByteArray(2);
388 }
389 
391 {
392  if (current_row < 0)
393  {
394  ui->snippetPreview->setPlainText("");
395  return;
396  }
397  const auto& name = ui->snippetsListSaved->currentItem()->text();
398  const SnippetData& snippet = _snipped_saved.at(name);
399 
400  QString preview;
401 
402  if (!snippet.global_vars.isEmpty())
403  {
404  preview += snippet.global_vars + "\n\n";
405  }
406  preview += "function calc(time, value";
407 
408  for (int i = 1; i <= snippet.additional_sources.size(); i++)
409  {
410  preview += QString(", v%1").arg(i);
411  }
412 
413  preview += ")\n";
414  auto function_lines = snippet.function.split("\n");
415  for (const auto& line : function_lines)
416  {
417  preview += " " + line + "\n";
418  }
419  preview += "end";
420  ui->snippetPreview->setPlainText(preview);
421 }
422 
424 {
425  const auto& name = ui->snippetsListSaved->item(index.row())->text();
426  const SnippetData& snippet = _snipped_saved.at(name);
427 
428  ui->globalVarsText->setPlainText(snippet.global_vars);
429  ui->functionText->setPlainText(snippet.function);
430 }
431 
433 {
434  auto list_saved = ui->snippetsListSaved;
435 
436  if (list_saved->selectedItems().size() != 1)
437  {
438  return;
439  }
440 
441  QMenu menu;
442 
443  QAction* rename_item = new QAction("Rename...", this);
444  menu.addAction(rename_item);
445 
446  connect(rename_item, &QAction::triggered, this, &FunctionEditorWidget::onRenameSaved);
447 
448  QAction* remove_item = new QAction("Remove", this);
449  menu.addAction(remove_item);
450 
451  connect(remove_item, &QAction::triggered, this, [list_saved, this]() {
452  const auto& item = list_saved->selectedItems().first();
453  _snipped_saved.erase(item->text());
454  delete list_saved->takeItem(list_saved->row(item));
455  });
456 
457  menu.exec(list_saved->mapToGlobal(pos));
458 }
459 
461 {
462  if (_plot_map_data.numeric.count(name.toStdString()) == 0)
463  {
464  ui->pushButtonCreate->setText("Create New Timeseries");
465  }
466  else
467  {
468  ui->pushButtonCreate->setText("Modify Timeseries");
469  }
470  updatePreview();
471 }
472 
474 {
475  QSettings settings;
476  QString directory_path =
477  settings.value("AddCustomPlotDialog.loadDirectory", QDir::currentPath()).toString();
478 
479  QString fileName = QFileDialog::getOpenFileName(
480  this, tr("Open Snippet Library"), directory_path, tr("Snippets (*.snippets.xml)"));
481  if (fileName.isEmpty())
482  {
483  return;
484  }
485 
486  QFile file(fileName);
487 
488  if (!file.open(QIODevice::ReadOnly))
489  {
490  QMessageBox::critical(this, "Error",
491  QString("Failed to open the file [%1]").arg(fileName));
492  return;
493  }
494 
495  directory_path = QFileInfo(fileName).absolutePath();
496  settings.setValue("AddCustomPlotDialog.loadDirectory", directory_path);
497 
498  importSnippets(file.readAll());
499 }
500 
502 {
503  QSettings settings;
504  QString directory_path =
505  settings.value("AddCustomPlotDialog.loadDirectory", QDir::currentPath()).toString();
506 
507  QString fileName = QFileDialog::getSaveFileName(
508  this, tr("Open Snippet Library"), directory_path, tr("Snippets (*.snippets.xml)"));
509 
510  if (fileName.isEmpty())
511  {
512  return;
513  }
514  if (!fileName.endsWith(".snippets.xml"))
515  {
516  fileName.append(".snippets.xml");
517  }
518 
519  QFile file(fileName);
520  if (!file.open(QIODevice::WriteOnly))
521  {
522  QMessageBox::critical(this, "Error",
523  QString("Failed to open the file [%1]").arg(fileName));
524  return;
525  }
526  auto data = exportSnippets();
527 
528  file.write(data);
529  file.close();
530 
531  directory_path = QFileInfo(fileName).absolutePath();
532  settings.setValue("AddCustomPlotDialog.loadDirectory", directory_path);
533 }
534 
536 {
537  QString name;
538 
539  auto selected_snippets = ui->snippetsListSaved->selectedItems();
540  if (selected_snippets.size() >= 1)
541  {
542  name = selected_snippets.front()->text();
543  }
544  bool ok = false;
545  name = QInputDialog::getText(this, tr("Name of the Function"), tr("Name:"),
546  QLineEdit::Normal, name, &ok);
547 
548  if (!ok || name.isEmpty())
549  {
550  return;
551  }
552 
553  SnippetData snippet;
554  snippet.alias_name = name;
555  snippet.global_vars = ui->globalVarsText->toPlainText();
556  snippet.function = ui->functionText->toPlainText();
557 
558  addToSaved(name, snippet);
559 
560  on_snippetsListSaved_currentRowChanged(ui->snippetsListSaved->currentRow());
561 }
562 
563 bool FunctionEditorWidget::addToSaved(const QString& name, const SnippetData& snippet)
564 {
565  if (_snipped_saved.count(name))
566  {
567  QMessageBox msgBox(this);
568  msgBox.setWindowTitle("Warning");
569  msgBox.setText(tr("A function with the same name exists already in the list of saved "
570  "functions.\n"));
571  msgBox.addButton(QMessageBox::Cancel);
572  QPushButton* button = msgBox.addButton(tr("Overwrite"), QMessageBox::YesRole);
573  msgBox.setDefaultButton(button);
574 
575  int res = msgBox.exec();
576 
577  if (res < 0 || res == QMessageBox::Cancel)
578  {
579  return false;
580  }
581  }
582  else
583  {
584  ui->snippetsListSaved->addItem(name);
585  ui->snippetsListSaved->sortItems();
586  }
587  _snipped_saved[name] = snippet;
588  return true;
589 }
590 
592 {
593  auto list_saved = ui->snippetsListSaved;
594  auto item = list_saved->selectedItems().first();
595  const auto& name = item->text();
596 
597  bool ok;
598  QString new_name = QInputDialog::getText(this, tr("Change the name of the function"),
599  tr("New name:"), QLineEdit::Normal, name, &ok);
600 
601  if (!ok || new_name.isEmpty() || new_name == name)
602  {
603  return;
604  }
605 
606  SnippetData snippet = _snipped_saved[name];
607  _snipped_saved.erase(name);
608  snippet.alias_name = new_name;
609 
610  _snipped_saved.insert({ new_name, snippet });
611  item->setText(new_name);
612  ui->snippetsListSaved->sortItems();
613 }
614 
616 {
617  std::vector<CustomPlotPtr> created_plots;
618 
619  try
620  {
621  if (ui->tabWidget->currentIndex() == 0)
622  {
623  std::string new_plot_name = ui->nameLineEdit->text().toStdString();
624 
625  if (_editor_mode == CREATE && _transform_maps.count(new_plot_name) != 0)
626  {
627  QMessageBox msgBox(this);
628  msgBox.setWindowTitle("Warning");
629  msgBox.setText(tr("A custom time series with the same name exists already.\n"
630  " Do you want to overwrite it?\n"));
631  msgBox.addButton(QMessageBox::Cancel);
632  QPushButton* button = msgBox.addButton(tr("Overwrite"), QMessageBox::YesRole);
633  msgBox.setDefaultButton(button);
634 
635  int res = msgBox.exec();
636 
637  if (res < 0 || res == QMessageBox::Cancel)
638  {
639  return;
640  }
641  }
642 
643  SnippetData snippet;
644  snippet.function = ui->functionText->toPlainText();
645  snippet.global_vars = ui->globalVarsText->toPlainText();
646  snippet.alias_name = ui->nameLineEdit->text();
647  snippet.linked_source = getLinkedData();
648  for (int row = 0; row < ui->listAdditionalSources->rowCount(); row++)
649  {
650  snippet.additional_sources.push_back(
651  ui->listAdditionalSources->item(row, 1)->text());
652  }
653  created_plots.push_back(std::make_unique<LuaCustomFunction>(snippet));
654  }
655  else // ----------- batch ------
656  {
657  for (int row = 0; row < ui->listBatchSources->count(); row++)
658  {
659  SnippetData snippet;
660  snippet.function = ui->functionTextBatch->toPlainText();
661  snippet.global_vars = ui->globalVarsTextBatch->toPlainText();
662  snippet.linked_source = ui->listBatchSources->item(row)->text();
663  if (ui->radioButtonPrefix->isChecked())
664  {
665  snippet.alias_name = ui->suffixLineEdit->text() + snippet.linked_source;
666  }
667  else
668  {
669  snippet.alias_name = snippet.linked_source + ui->suffixLineEdit->text();
670  }
671  created_plots.push_back(std::make_unique<LuaCustomFunction>(snippet));
672  }
673  }
674 
675  accept(created_plots);
676  saveSettings();
677  }
678  catch (const std::runtime_error& e)
679  {
680  QMessageBox::critical(this, "Error",
681  "Failed to create math plot : " +
682  QString::fromStdString(e.what()));
683  }
684 }
685 
687 {
688  if (_editor_mode == MODIFY)
689  {
690  clear();
691  }
692  saveSettings();
693  closed();
694 }
695 
697 {
698  QString function_text("function( time, value");
699  for (int row = 0; row < ui->listAdditionalSources->rowCount(); row++)
700  {
701  function_text += ", ";
702  function_text += ui->listAdditionalSources->item(row, 0)->text();
703  }
704  function_text += " )";
705  ui->labelFunction->setText(function_text);
706 
707  updatePreview();
708 }
709 
711 {
712  bool any_selected = !ui->listAdditionalSources->selectedItems().isEmpty();
713  ui->pushButtonDeleteCurves->setEnabled(any_selected);
714 }
715 
717 {
718  auto list_sources = ui->listAdditionalSources;
719  QModelIndexList selected = list_sources->selectionModel()->selectedRows();
720  while (selected.size() > 0)
721  {
722  list_sources->removeRow(selected.first().row());
723  selected = list_sources->selectionModel()->selectedRows();
724  }
725  for (int row = 0; row < list_sources->rowCount(); row++)
726  {
727  list_sources->item(row, 0)->setText(QString("v%1").arg(row + 1));
728  }
729 
732 }
733 
735 {
736  updatePreview();
737 }
738 
740 {
742 }
743 
744 void FunctionEditorWidget::setSemaphore(QLabel* semaphore, QString errors)
745 {
746  QFile file(":/resources/svg/red_circle.svg");
747 
748  if (errors.isEmpty())
749  {
750  errors = "Everything is fine :)";
751  file.setFileName(":/resources/svg/green_circle.svg");
752  ui->pushButtonCreate->setEnabled(true);
753  }
754  else
755  {
756  errors = errors.left(errors.size() - 1);
757  ui->pushButtonCreate->setEnabled(false);
758  }
759 
760  semaphore->setToolTip(errors);
761  semaphore->setToolTipDuration(5000);
762 
763  file.open(QFile::ReadOnly | QFile::Text);
764  auto svg_data = file.readAll();
765  file.close();
766  QByteArray content(svg_data);
767  QSvgRenderer rr(content);
768  QImage image(26, 26, QImage::Format_ARGB32);
769  QPainter painter(&image);
770  image.fill(Qt::transparent);
771  rr.render(&painter);
772  semaphore->setPixmap(QPixmap::fromImage(image));
773 }
774 
776 {
777  QString errors;
778  std::string new_plot_name = ui->nameLineEdit->text().toStdString();
779 
780  if (_transform_maps.count(new_plot_name) != 0)
781  {
782  QString new_name = ui->nameLineEdit->text();
783  if (ui->lineEditSource->text().toStdString() == new_plot_name ||
784  !ui->listAdditionalSources->findItems(new_name, Qt::MatchExactly).isEmpty())
785  {
786  errors += "- The name of the new timeseries is the same of one of its "
787  "dependencies.\n";
788  }
789  }
790 
791  if (new_plot_name.empty())
792  {
793  errors += "- Missing name of the new time series.\n";
794  }
795  else
796  {
797  // check if name is unique (except if is custom_plot)
798  if (_plot_map_data.numeric.count(new_plot_name) != 0 &&
799  _transform_maps.count(new_plot_name) == 0)
800  {
801  errors += "- Plot name already exists and can't be modified.\n";
802  }
803  }
804 
805  if (ui->lineEditSource->text().isEmpty())
806  {
807  errors += "- Missing source time series.\n";
808  }
809 
810  SnippetData snippet;
811  snippet.function = ui->functionText->toPlainText();
812  snippet.global_vars = ui->globalVarsText->toPlainText();
813  snippet.alias_name = ui->nameLineEdit->text();
814  snippet.linked_source = getLinkedData();
815  for (int row = 0; row < ui->listAdditionalSources->rowCount(); row++)
816  {
817  snippet.additional_sources.push_back(ui->listAdditionalSources->item(row, 1)->text());
818  }
819 
820  CustomPlotPtr lua_function;
821  try
822  {
823  lua_function = std::make_unique<LuaCustomFunction>(snippet);
824  ui->buttonSaveCurrent->setEnabled(true);
825  }
826  catch (std::runtime_error& err)
827  {
828  errors += QString("- Error in Lua script: %1").arg(err.what());
829  ui->buttonSaveCurrent->setEnabled(false);
830  }
831 
832  if (lua_function)
833  {
834  try
835  {
836  std::string name = new_plot_name.empty() ? "no_name" : new_plot_name;
837  PlotData& out_data = _local_plot_data.getOrCreateNumeric(name);
838  out_data.clear();
839 
840  std::vector<PlotData*> out_vector = { &out_data };
841  lua_function->setData(&_plot_map_data, {}, out_vector);
842  lua_function->calculate();
843 
845  _preview_widget->addCurve(name, Qt::blue);
846  _preview_widget->zoomOut(false);
847  }
848  catch (std::runtime_error& err)
849  {
850  errors += QString("- Error in Lua script: %1").arg(err.what());
851  }
852  }
853 
854  setSemaphore(ui->labelSemaphore, errors);
855 }
856 
858 {
859  QString errors;
860 
861  if (ui->suffixLineEdit->text().isEmpty())
862  {
863  errors += "- Missing prefix/suffix.\n";
864  }
865 
866  if (ui->listBatchSources->count() == 0)
867  {
868  errors += "- No input series.\n";
869  }
870 
871  SnippetData snippet;
872  snippet.function = ui->functionTextBatch->toPlainText();
873  snippet.global_vars = ui->globalVarsTextBatch->toPlainText();
874 
875  try
876  {
877  auto lua_function = std::make_unique<LuaCustomFunction>(snippet);
878  }
879  catch (std::runtime_error& err)
880  {
881  errors += QString("- Error in Lua script: %1").arg(err.what());
882  }
883 
884  setSemaphore(ui->labelSemaphoreBatch, errors);
885 }
886 
888 {
889  QDialog* dialog = new QDialog(this);
890  auto ui = new Ui_FunctionEditorHelp();
891  ui->setupUi(dialog);
892 
893  dialog->setAttribute(Qt::WA_DeleteOnClose);
894  dialog->exec();
895 }
896 
898 {
899  QString filter_text = ui->lineEditTab2Filter->text();
900  ui->listBatchSources->clear();
901 
902  if (ui->radioButtonRegExp->isChecked() || ui->radioButtonWildcard->isChecked())
903  {
904  QRegExp rx(filter_text);
905  if (ui->radioButtonWildcard->isChecked())
906  {
907  rx.setPatternSyntax(QRegExp::Wildcard);
908  }
909 
910  for (const auto& [name, plotdata] : _plot_map_data.numeric)
911  {
912  auto qname = QString::fromStdString(name);
913  if (rx.exactMatch(qname))
914  {
915  ui->listBatchSources->addItem(qname);
916  }
917  }
918  }
919  else
920  {
921  QStringList spaced_items = filter_text.split(' ', PJ::SkipEmptyParts);
922  for (const auto& [name, plotdata] : _plot_map_data.numeric)
923  {
924  bool show = true;
925  auto qname = QString::fromStdString(name);
926  for (const auto& part : spaced_items)
927  {
928  if (qname.contains(part) == false)
929  {
930  show = false;
931  break;
932  }
933  }
934  if (show)
935  {
936  ui->listBatchSources->addItem(qname);
937  }
938  }
939  }
940  ui->listBatchSources->sortItems();
942 }
943 
945 {
947 }
948 
950 {
952 }
953 
955 {
957 }
958 
960 {
962 }
963 
965 {
966  if (index == 0)
967  {
968  onUpdatePreview();
969  }
970  else
971  {
973  }
974 }
975 
977 {
979 }
980 
982 {
984 }
985 
987 {
989 }
FunctionEditorWidget::on_pushButtonHelpTab2_clicked
void on_pushButtonHelpTab2_clicked()
Definition: function_editor.cpp:944
FunctionEditorWidget::on_tabWidget_currentChanged
void on_tabWidget_currentChanged(int index)
Definition: function_editor.cpp:964
detail::first
auto first(const T &value, const Tail &...) -> const T &
Definition: compile.h:60
PJ::TimeseriesBase
Definition: timeseries.h:16
FunctionEditorWidget::on_listAdditionalSources_itemSelectionChanged
void on_listAdditionalSources_itemSelectionChanged()
Definition: function_editor.cpp:710
FunctionEditorWidget::getLinkedData
QString getLinkedData() const
Definition: function_editor.cpp:237
FunctionEditorWidget::on_pushButtonCreate_clicked
void on_pushButtonCreate_clicked()
Definition: function_editor.cpp:615
FunctionEditorWidget::on_buttonSaveFunctions_clicked
void on_buttonSaveFunctions_clicked()
Definition: function_editor.cpp:501
plotwidget.h
FunctionEditorWidget::_update_preview_tab2
DelayedCallback _update_preview_tab2
Definition: function_editor.h:140
LoadSvg
const QPixmap & LoadSvg(QString filename, QString style_name="light")
Definition: svg_util.h:26
PlotWidget::removeAllCurves
void removeAllCurves() override
Definition: plotwidget.cpp:461
lua_custom_function.h
GetLuaSyntaxStyle
QSyntaxStyle * GetLuaSyntaxStyle(QString theme)
Definition: stylesheet.h:89
ExportSnippets
QDomElement ExportSnippets(const SnippetsMap &snippets, QDomDocument &doc)
Definition: custom_function.cpp:171
FunctionEditorWidget::lua_completer_batch_
QLuaCompleter * lua_completer_batch_
Definition: function_editor.h:135
FunctionEditorWidget::on_stylesheetChanged
void on_stylesheetChanged(QString theme)
Definition: function_editor.cpp:37
GetSnippetsFromXML
SnippetsMap GetSnippetsFromXML(const QString &xml_text)
Definition: custom_function.cpp:132
SnippetData::linked_source
QString linked_source
Definition: custom_function.h:24
LuaCustomFunction
Definition: lua_custom_function.h:9
FunctionEditorWidget::accept
void accept(std::vector< CustomPlotPtr > plot)
FunctionEditorWidget::_update_preview_tab1
DelayedCallback _update_preview_tab1
Definition: function_editor.h:139
arg
auto arg(const Char *name, const T &arg) -> detail::named_arg< Char, T >
Definition: core.h:1875
PlotWidget::setContextMenuEnabled
void setContextMenuEnabled(bool enabled)
Definition: plotwidget.cpp:139
FunctionEditorWidget::eventFilter
bool eventFilter(QObject *obj, QEvent *event) override
Definition: function_editor.cpp:281
FunctionEditorWidget::onLineEditTab2FilterChanged
void onLineEditTab2FilterChanged()
Definition: function_editor.cpp:897
QLuaCompleter
Class, that describes completer with glsl specific types and functions.
Definition: QLuaCompleter.hpp:10
FunctionEditorWidget::saveSettings
void saveSettings()
Definition: function_editor.cpp:178
FunctionEditorWidget::on_globalVarsTextBatch_textChanged
void on_globalVarsTextBatch_textChanged()
Definition: function_editor.cpp:976
FunctionEditorWidget::setLinkedPlotName
void setLinkedPlotName(const QString &linkedPlotName)
Definition: function_editor.cpp:221
PJ::SkipEmptyParts
const auto SkipEmptyParts
Definition: plotdatabase.h:31
FunctionEditorWidget::createNewPlot
void createNewPlot()
Definition: function_editor.cpp:242
FunctionEditorWidget::onUpdatePreviewBatch
void onUpdatePreviewBatch()
Definition: function_editor.cpp:857
PJ::TransformsMap
std::unordered_map< std::string, std::shared_ptr< TransformFunction > > TransformsMap
Definition: transform_function.h:85
FunctionEditorWidget::onRenameSaved
void onRenameSaved()
Definition: function_editor.cpp:591
FunctionEditorWidget::CREATE
@ CREATE
Definition: function_editor.h:33
ok
ROSCPP_DECL bool ok()
FunctionEditorWidget::on_suffixLineEdit_textChanged
void on_suffixLineEdit_textChanged(const QString &arg1)
Definition: function_editor.cpp:959
FunctionEditorWidget::_plot_map_data
PlotDataMapRef & _plot_map_data
Definition: function_editor.h:119
FunctionEditorWidget::on_pushButtonHelp_clicked
void on_pushButtonHelp_clicked()
Definition: function_editor.cpp:887
FunctionEditorWidget::on_functionText_textChanged
void on_functionText_textChanged()
Definition: function_editor.cpp:986
PlotWidget
Definition: plotwidget.h:38
PJ::PlotDataBase::clear
virtual void clear()
Definition: plotdatabase.h:213
PJ::PlotDataMapRef::numeric
TimeseriesMap numeric
Numerical timeseries.
Definition: plotdata.h:39
FunctionEditorWidget::on_nameLineEdit_textChanged
void on_nameLineEdit_textChanged(const QString &arg1)
Definition: function_editor.cpp:460
SnippetData::additional_sources
QStringList additional_sources
Definition: custom_function.h:25
PlotWidget::addCurve
CurveInfo * addCurve(const std::string &name, QColor color=Qt::transparent)
Definition: plotwidget.cpp:393
custom_function.h
CustomPlotPtr
std::shared_ptr< CustomFunction > CustomPlotPtr
Definition: custom_function.h:15
SnippetData::alias_name
QString alias_name
Definition: custom_function.h:21
SnippetData::function
QString function
Definition: custom_function.h:23
FunctionEditorWidget::on_listSourcesChanged
void on_listSourcesChanged()
Definition: function_editor.cpp:696
PJ::DelayedCallback::triggerSignal
void triggerSignal(int delay_ms)
Definition: delayed_callback.hpp:37
FunctionEditorWidget::on_buttonSaveCurrent_clicked
void on_buttonSaveCurrent_clicked()
Definition: function_editor.cpp:535
Ui
Definition: cheatsheet_dialog.h:6
FunctionEditorWidget::ui
Ui::FunctionEditor * ui
Definition: function_editor.h:121
FunctionEditorWidget::~FunctionEditorWidget
virtual ~FunctionEditorWidget() override
Definition: function_editor.cpp:212
FunctionEditorWidget::_preview_widget
PlotWidget * _preview_widget
Definition: function_editor.h:130
FunctionEditorWidget::on_globalVarsText_textChanged
void on_globalVarsText_textChanged()
Definition: function_editor.cpp:981
FunctionEditorWidget::on_lineEditSource_textChanged
void on_lineEditSource_textChanged(const QString &text)
Definition: function_editor.cpp:734
stylesheet.h
FunctionEditorWidget::on_pushButtonCancel_pressed
void on_pushButtonCancel_pressed()
Definition: function_editor.cpp:686
FunctionEditorWidget::on_snippetsListSaved_doubleClicked
void on_snippetsListSaved_doubleClicked(const QModelIndex &index)
Definition: function_editor.cpp:423
FunctionEditorWidget::_dragging_curves
QStringList _dragging_curves
Definition: function_editor.h:127
FunctionEditorWidget::savedContextMenu
void savedContextMenu(const QPoint &pos)
Definition: function_editor.cpp:432
FunctionEditorWidget::_transform_maps
const TransformsMap & _transform_maps
Definition: function_editor.h:120
FunctionEditorWidget::updatePreview
void updatePreview()
Definition: function_editor.cpp:739
PJ::PlotDataMapRef::getOrCreateNumeric
PlotData & getOrCreateNumeric(const std::string &name, PlotGroup::Ptr group={})
Definition: plotdata.cpp:75
format
auto format(const text_style &ts, const S &format_str, const Args &... args) -> std::basic_string< Char >
Definition: color.h:543
FunctionEditorWidget::importSnippets
void importSnippets(const QByteArray &xml_text)
Definition: function_editor.cpp:350
FunctionEditorWidget::_tab2_filter
DelayedCallback _tab2_filter
Definition: function_editor.h:137
FunctionEditorWidget::_snipped_saved
SnippetsMap _snipped_saved
Definition: function_editor.h:125
SnippetData::global_vars
QString global_vars
Definition: custom_function.h:22
FunctionEditorWidget::on_snippetsListSaved_currentRowChanged
void on_snippetsListSaved_currentRowChanged(int currentRow)
Definition: function_editor.cpp:390
FunctionEditorWidget::setSemaphore
void setSemaphore(QLabel *semaphore, QString errors)
Definition: function_editor.cpp:744
FunctionEditorWidget::onUpdatePreview
void onUpdatePreview()
Definition: function_editor.cpp:775
FunctionEditorWidget::closed
void closed()
FunctionEditorWidget::on_pushButtonDeleteCurves_clicked
void on_pushButtonDeleteCurves_clicked()
Definition: function_editor.cpp:716
FunctionEditorWidget::MODIFY
@ MODIFY
Definition: function_editor.h:34
FunctionEditorWidget::editExistingPlot
void editExistingPlot(CustomPlotPtr data)
Definition: function_editor.cpp:249
SnippetData
Definition: custom_function.h:19
FunctionEditorWidget::_editor_mode
EditorMode _editor_mode
Definition: function_editor.h:132
FunctionEditorWidget::_local_plot_data
PlotDataMapRef _local_plot_data
Definition: function_editor.h:129
FunctionEditorWidget::exportSnippets
QByteArray exportSnippets() const
Definition: function_editor.cpp:382
FunctionEditorWidget::FunctionEditorWidget
FunctionEditorWidget(PlotDataMapRef &plotMapData, const TransformsMap &mapped_custom_plots, QWidget *parent)
Definition: function_editor.cpp:53
mqtt_test.data
dictionary data
Definition: mqtt_test.py:22
FunctionEditorWidget::on_functionTextBatch_textChanged
void on_functionTextBatch_textChanged()
Definition: function_editor.cpp:954
QLuaHighlighter
Class, that describes C++ code highlighter.
Definition: QLuaHighlighter.hpp:19
function_editor.h
PJ::PlotDataMapRef
Definition: plotdata.h:34
PlotWidget::zoomOut
void zoomOut(bool emit_signal)
Definition: plotwidget.cpp:1319
PJ::DelayedCallback::connectCallback
void connectCallback(Function callback)
Definition: delayed_callback.hpp:32
FunctionEditorWidget::on_lineEditTab2Filter_textChanged
void on_lineEditTab2Filter_textChanged(const QString &arg1)
Definition: function_editor.cpp:949
FunctionEditorWidget::lua_completer_
QLuaCompleter * lua_completer_
Definition: function_editor.h:134
FunctionEditorWidget::clear
void clear()
Definition: function_editor.cpp:226
FunctionEditorWidget::addToSaved
bool addToSaved(const QString &name, const SnippetData &snippet)
Definition: function_editor.cpp:563
svg_util.h
FunctionEditorWidget::on_buttonLoadFunctions_clicked
void on_buttonLoadFunctions_clicked()
Definition: function_editor.cpp:473


plotjuggler
Author(s): Davide Faconti
autogenerated on Mon Nov 11 2024 03:23:44