2 #include "ui_lua_editor.h"
14 #include "QSyntaxStyle"
19 ui =
new Ui::LuaEditor;
22 QString library_default_code =
ui->textLibrary->toPlainText();
24 ui->textGlobal->installEventFilter(
this);
25 ui->textFunction->installEventFilter(
this);
26 ui->textLibrary->installEventFilter(
this);
28 ui->labelSemaphore->setToolTipDuration(5000);
30 ui->textGlobal->setAcceptDrops(
true);
31 ui->textFunction->setAcceptDrops(
true);
37 connect(
ui->lineEditFunctionName, &QLineEdit::textChanged,
this, [
this]() {
38 bool has_name = ui->lineEditFunctionName->text().isEmpty() == false;
39 ui->pushButtonSave->setEnabled(has_name);
42 connect(
ui->buttonBox, &QDialogButtonBox::rejected,
this, &ToolboxPlugin::closed);
44 connect(
ui->listWidgetRecent, &QListWidget::doubleClicked,
this,
47 connect(
ui->listWidgetFunctions, &QListWidget::doubleClicked,
this,
50 connect(
ui->listWidgetFunctions, &QListWidget::itemSelectionChanged,
this, [
this]() {
51 auto selected = ui->listWidgetFunctions->selectedItems();
52 ui->pushButtonDelete->setEnabled(selected.size() > 0);
57 connect(
ui->textLibrary, &QTextEdit::textChanged,
58 [
this]() { _delay_library_check.triggerSignal(250); });
60 connect(
ui->pushButtonDefaultLibrary, &QPushButton::clicked,
61 [=]() { ui->textLibrary->setPlainText(library_default_code); });
63 connect(
ui->pushButtonApplyLibrary, &QPushButton::clicked,
this,
77 auto previous_functions =
78 settings.value(
"ToolboxLuaEditor/recent_functions",
"").toString();
79 if (previous_functions.isEmpty() ==
false)
82 if (xml_doc.setContent(previous_functions))
84 auto root = xml_doc.firstChild();
85 for (
auto elem = root.firstChildElement(
"function"); !elem.isNull();
86 elem = elem.nextSiblingElement(
"function"))
88 auto name = elem.attribute(
"name");
89 auto item =
new QListWidgetItem(
name);
90 setItemData(item,
name, elem.attribute(
"global"), elem.attribute(
"function"));
91 ui->listWidgetRecent->addItem(item);
96 if (settings.contains(
"ToolboxLuaEditor/library"))
98 QString code = settings.value(
"ToolboxLuaEditor/library").toString();
99 ui->textLibrary->setPlainText(code);
114 return "Reactive Script Editor";
130 if (
ui->listWidgetFunctions->count() > 0)
132 QString
msg =
"Do you want to save the current active scripts?\n\n";
134 for (
int row = 0; row <
ui->listWidgetFunctions->count(); row++)
136 auto item =
ui->listWidgetFunctions->item(row);
137 msg += QString(
" - %1\n").arg(item->text());
140 auto ret = QMessageBox::question(
nullptr, this->
name(), msg);
141 if (
ret == QMessageBox::No)
147 auto library_elem = doc.createElement(
"library");
148 library_elem.setAttribute(
"code",
ui->textLibrary->toPlainText());
149 parent_element.appendChild(library_elem);
151 auto scripts_elem = doc.createElement(
"scripts");
153 for (
int row = 0; row <
ui->listWidgetFunctions->count(); row++)
155 auto item =
ui->listWidgetFunctions->item(row);
157 auto elem = doc.createElement(
"script");
158 elem.setAttribute(
"name", fields.name);
159 elem.setAttribute(
"function", fields.function_code);
160 elem.setAttribute(
"global", fields.global_code);
161 scripts_elem.appendChild(elem);
163 parent_element.appendChild(scripts_elem);
170 auto library_elem = parent_element.firstChildElement(
"library");
171 if (!library_elem.isNull())
173 ui->textLibrary->setPlainText(library_elem.attribute(
"code"));
176 auto scripts_elem = parent_element.firstChildElement(
"scripts");
177 if (!scripts_elem.isNull())
179 for (
auto elem = scripts_elem.firstChildElement(
"script"); elem.isNull() ==
false;
180 elem = elem.nextSiblingElement(
"script"))
182 ui->listWidgetFunctions->clear();
183 QString
name = elem.attribute(
"name");
184 QString
function = elem.attribute(
"function");
185 QString global = elem.attribute(
"global");
186 auto item =
new QListWidgetItem(
name);
188 ui->listWidgetFunctions->addItem(item);
190 auto lua_function = std::make_shared<ReactiveLuaFunction>(
191 _plot_data, global,
function,
ui->textLibrary->toPlainText());
193 (*_transforms)[
name.toStdString()] = lua_function;
195 ui->listWidgetFunctions->sortItems();
203 ui->listWidgetFunctions->clear();
208 if (
auto lua_function = std::dynamic_pointer_cast<ReactiveLuaFunction>(it.second))
210 QString
name = QString::fromStdString(it.first);
211 auto item =
new QListWidgetItem(
name);
213 lua_function->getFunctionCode());
214 ui->listWidgetFunctions->addItem(item);
216 ui->listWidgetFunctions->sortItems();
220 QString theme = settings.value(
"StyleSheet::theme",
"light").toString();
222 ui->pushButtonDelete->setIcon(
LoadSvg(
":/resources/svg/clear.svg", theme));
224 _font_size = settings.value(
"ToolboxLuaEditor/fonts_size", 12).toInt();
226 QFont fixedFont = QFontDatabase::systemFont(QFontDatabase::FixedFont);
229 ui->textGlobal->setFont(fixedFont);
230 ui->textFunction->setFont(fixedFont);
231 ui->textLibrary->setFont(fixedFont);
233 auto style_path = (theme ==
"light") ?
":/resources/lua_style_light.xml" :
234 ":/resources/lua_style_dark.xml";
236 QFile fl(style_path);
237 if (fl.open(QIODevice::ReadOnly))
240 if (style->load(fl.readAll()))
242 ui->textGlobal->setSyntaxStyle(style);
243 ui->textFunction->setSyntaxStyle(style);
244 ui->textLibrary->setSyntaxStyle(style);
253 auto name =
ui->lineEditFunctionName->text();
254 if (
ui->listWidgetFunctions->findItems(
name, Qt::MatchExactly).size() > 0)
257 msgBox.setWindowTitle(
"Warning");
258 msgBox.setText(tr(
"A dfunction with the same name exists already.\n"
259 " Do you want to overwrite it?\n"));
260 msgBox.addButton(QMessageBox::Cancel);
261 QPushButton* button = msgBox.addButton(tr(
"Overwrite"), QMessageBox::YesRole);
262 msgBox.setDefaultButton(button);
264 int res = msgBox.exec();
265 if (res < 0 || res == QMessageBox::Cancel)
273 auto lua_function = std::make_shared<ReactiveLuaFunction>(
274 _plot_data,
ui->textGlobal->toPlainText(),
ui->textFunction->toPlainText(),
275 ui->textLibrary->toPlainText());
277 (*_transforms)[
name.toStdString()] = lua_function;
279 if (
ui->listWidgetFunctions->findItems(
name, Qt::MatchExactly).empty())
281 ui->listWidgetFunctions->addItem(
name);
282 ui->listWidgetFunctions->sortItems();
285 auto item =
ui->listWidgetFunctions->findItems(
name, Qt::MatchExactly).first();
287 ui->textFunction->toPlainText());
289 for (
auto& new_name : lua_function->createdCurves())
294 catch (std::runtime_error& err)
296 QMessageBox::warning(
nullptr,
"Error in Lua code", QString(err.what()),
297 QMessageBox::Cancel);
300 auto prev_items =
ui->listWidgetRecent->findItems(
name, Qt::MatchExactly);
302 if (prev_items.empty())
304 while (
ui->listWidgetRecent->count() >= 10)
306 delete ui->listWidgetRecent->takeItem(0);
312 auto row =
ui->listWidgetRecent->row(prev_items.first());
313 delete ui->listWidgetRecent->takeItem(row);
317 auto new_item =
new QListWidgetItem(
name);
319 ui->textFunction->toPlainText());
320 ui->listWidgetRecent->addItem(new_item);
322 QDomDocument xml_doc;
323 auto root = xml_doc.createElement(
"functions");
325 for (
int row = 0; row <
ui->listWidgetRecent->count(); row++)
327 auto item =
ui->listWidgetRecent->item(row);
330 auto elem = xml_doc.createElement(
"function");
331 elem.setAttribute(
"name", fields.name);
332 elem.setAttribute(
"global", fields.global_code);
333 elem.setAttribute(
"function", fields.function_code);
334 root.appendChild(elem);
336 xml_doc.appendChild(root);
339 settings.setValue(
"ToolboxLuaEditor/recent_functions", xml_doc.toString());
344 for (
auto item :
ui->listWidgetFunctions->selectedItems())
348 int row =
ui->listWidgetFunctions->row(item);
349 delete ui->listWidgetFunctions->takeItem(row);
355 auto item =
ui->listWidgetRecent->item(index.row());
357 ui->lineEditFunctionName->setText(fields.name);
358 ui->textGlobal->setPlainText(fields.global_code);
359 ui->textFunction->setPlainText(fields.function_code);
364 auto item =
ui->listWidgetFunctions->item(index.row());
366 ui->lineEditFunctionName->setText(fields.name);
367 ui->textGlobal->setPlainText(fields.global_code);
368 ui->textFunction->setPlainText(fields.function_code);
375 ui->pushButtonApplyLibrary->setEnabled(
false);
379 QString svg_name =
":/resources/svg/green_circle.svg";
383 ui->labelSemaphore->setToolTip(
"Everything is fine :)");
384 int active_series =
ui->listWidgetFunctions->count();
385 ui->pushButtonApplyLibrary->setEnabled(active_series > 0);
389 settings.setValue(
"ToolboxLuaEditor/library",
ui->textLibrary->toPlainText());
391 catch (std::runtime_error& ex)
393 QString error_msg = ex.what();
394 ui->labelSemaphore->setToolTip(error_msg);
395 svg_name =
":/resources/svg/red_circle.svg";
396 ui->pushButtonApplyLibrary->setEnabled(
false);
399 QFile file(svg_name);
400 file.open(QFile::ReadOnly | QFile::Text);
401 QByteArray content(file.readAll());
402 QSvgRenderer rr(content);
403 QImage image(
ui->labelSemaphore->width(),
ui->labelSemaphore->height(),
404 QImage::Format_ARGB32);
405 QPainter painter(&image);
406 image.fill(Qt::transparent);
408 ui->labelSemaphore->setPixmap(QPixmap::fromImage(image));
413 for (
int row = 0; row <
ui->listWidgetFunctions->count(); row++)
415 auto item =
ui->listWidgetFunctions->item(row);
416 auto name = item->text();
420 auto lua_function = std::make_shared<ReactiveLuaFunction>(
421 _plot_data, fields.global_code, fields.function_code,
422 ui->textLibrary->toPlainText());
424 (*_transforms)[fields.name.toStdString()] = lua_function;
426 catch (std::runtime_error& err)
428 QMessageBox::warning(
nullptr,
"Error in Lua code", QString(err.what()),
429 QMessageBox::Cancel);
432 ui->pushButtonApplyLibrary->setEnabled(
false);
437 if (obj !=
ui->textGlobal && obj !=
ui->textFunction && obj !=
ui->textLibrary)
442 if (ev->type() == QEvent::DragEnter)
445 auto event =
static_cast<QDragEnterEvent*
>(ev);
446 const QMimeData* mimeData =
event->mimeData();
447 QStringList mimeFormats = mimeData->formats();
448 for (
const QString&
format : mimeFormats)
450 QByteArray encoded = mimeData->data(
format);
451 QDataStream stream(&encoded, QIODevice::ReadOnly);
453 if (
format !=
"curveslist/add_curve")
458 while (!stream.atEnd())
461 stream >> curve_name;
462 if (!curve_name.isEmpty())
469 event->acceptProposedAction();
474 else if (ev->type() == QEvent::Drop)
476 auto text_edit = qobject_cast<QPlainTextEdit*>(obj);
479 text_edit->insertPlainText(QString(
"\"%1\"\n").
arg(
name));
484 else if (ev->type() == QEvent::Wheel)
486 QWheelEvent* wheel_event =
dynamic_cast<QWheelEvent*
>(ev);
487 bool ctrl_modifier_pressed =
488 (QGuiApplication::keyboardModifiers() == Qt::ControlModifier);
490 if (ctrl_modifier_pressed)
493 if (wheel_event->delta() < 0)
497 else if (wheel_event->delta() > 0)
503 auto font =
ui->textGlobal->font();
505 ui->textGlobal->setFont(font);
506 ui->textFunction->setFont(font);
507 ui->textLibrary->setFont(font);
510 settings.setValue(
"ToolboxLuaEditor/fonts_size",
_font_size);
521 auto fields = item->data(Qt::UserRole).toStringList();
523 data.name = fields[0];
524 data.global_code = fields[1];
525 data.function_code = fields[2];
530 QString global_code, QString function_code)
532 QStringList save_fields;
533 save_fields.push_back(
name);
534 save_fields.push_back(global_code);
535 save_fields.push_back(function_code);
536 item->setData(Qt::UserRole, save_fields);