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]()
39 bool has_name = ui->lineEditFunctionName->text().isEmpty() == false;
40 ui->pushButtonSave->setEnabled( has_name );
43 connect(
ui->buttonBox, &QDialogButtonBox::rejected,
this, &ToolboxPlugin::closed);
49 connect(
ui->listWidgetFunctions, &QListWidget::itemSelectionChanged,
this,
51 auto selected = ui->listWidgetFunctions->selectedItems();
52 ui->pushButtonDelete->setEnabled(selected.size()>0);
59 connect(
ui->textLibrary, &QTextEdit::textChanged,
61 _delay_library_check.triggerSignal(250); }
64 connect(
ui->pushButtonDefaultLibrary, &QPushButton::clicked,
65 [=]() { ui->textLibrary->setPlainText( library_default_code ); } );
67 connect(
ui->pushButtonApplyLibrary, &QPushButton::clicked,
82 auto previous_functions = settings.value(
"ToolboxLuaEditor/recent_functions",
"").toString();
83 if( previous_functions.isEmpty() ==
false)
86 if(xml_doc.setContent(previous_functions))
88 auto root = xml_doc.firstChild();
89 for(
auto elem = root.firstChildElement(
"function"); !elem.isNull();
90 elem = elem.nextSiblingElement(
"function") )
92 auto name = elem.attribute(
"name");
93 auto item =
new QListWidgetItem(
name);
94 setItemData(item,
name, elem.attribute(
"global"), elem.attribute(
"function"));
95 ui->listWidgetRecent->addItem(item);
100 if( settings.contains(
"ToolboxLuaEditor/library"))
102 QString code = settings.value(
"ToolboxLuaEditor/library").toString();
103 ui->textLibrary->setPlainText(code);
118 return "Reactive Script Editor";
129 std::pair<QWidget *, ToolboxPlugin::WidgetType>
137 if(
ui->listWidgetFunctions->count() > 0 )
139 QString
msg =
"Do you want to save the current active scripts?\n\n";
141 for(
int row = 0; row <
ui->listWidgetFunctions->count(); row++)
143 auto item =
ui->listWidgetFunctions->item(row);
144 msg += QString(
" - %1\n").arg(item->text());
147 auto ret = QMessageBox::question(
nullptr, this->
name(), msg);
148 if(
ret == QMessageBox::No )
154 auto library_elem = doc.createElement(
"library");
155 library_elem.setAttribute(
"code",
ui->textLibrary->toPlainText());
156 parent_element.appendChild(library_elem);
158 auto scripts_elem = doc.createElement(
"scripts");
160 for(
int row = 0; row <
ui->listWidgetFunctions->count(); row++)
162 auto item =
ui->listWidgetFunctions->item(row);
164 auto elem = doc.createElement(
"script");
165 elem.setAttribute(
"name", fields.name);
166 elem.setAttribute(
"function", fields.function_code);
167 elem.setAttribute(
"global", fields.global_code);
168 scripts_elem.appendChild(elem);
170 parent_element.appendChild(scripts_elem);
177 auto library_elem = parent_element.firstChildElement(
"library");
178 if(!library_elem.isNull())
180 ui->textLibrary->setPlainText( library_elem.attribute(
"code") );
183 auto scripts_elem = parent_element.firstChildElement(
"scripts");
184 if(!scripts_elem.isNull())
186 for (
auto elem = scripts_elem.firstChildElement(
"script");
187 elem.isNull() ==
false; elem = elem.nextSiblingElement(
"script"))
189 ui->listWidgetFunctions->clear();
190 QString
name = elem.attribute(
"name");
191 QString
function = elem.attribute(
"function");
192 QString global = elem.attribute(
"global");
193 auto item =
new QListWidgetItem(name);
195 ui->listWidgetFunctions->addItem(item);
197 auto lua_function = std::make_shared<ReactiveLuaFunction>(
198 _plot_data, global,
function,
ui->textLibrary->toPlainText() );
200 (*_transforms)[name.toStdString()] = lua_function;
202 ui->listWidgetFunctions->sortItems();
210 ui->listWidgetFunctions->clear();
215 if(
auto lua_function = std::dynamic_pointer_cast<ReactiveLuaFunction>( it.second ))
217 QString
name = QString::fromStdString(it.first);
218 auto item =
new QListWidgetItem(name);
219 setItemData(item, name, lua_function->getGlobalCode(), lua_function->getFunctionCode());
220 ui->listWidgetFunctions->addItem(item);
222 ui->listWidgetFunctions->sortItems();
226 QString theme = settings.value(
"StyleSheet::theme",
"light").toString();
228 ui->pushButtonDelete->setIcon(
LoadSvg(
":/resources/svg/clear.svg", theme));
230 _font_size = settings.value(
"ToolboxLuaEditor/fonts_size", 12).toInt();
232 QFont fixedFont = QFontDatabase::systemFont(QFontDatabase::FixedFont);
235 ui->textGlobal->setFont( fixedFont );
236 ui->textFunction->setFont( fixedFont );
237 ui->textLibrary->setFont( fixedFont );
239 auto style_path = (theme ==
"light" ) ?
":/resources/lua_style_light.xml" :
240 ":/resources/lua_style_dark.xml";
242 QFile fl(style_path);
243 if (fl.open(QIODevice::ReadOnly))
246 if (style->load(fl.readAll()))
248 ui->textGlobal->setSyntaxStyle( style );
249 ui->textFunction->setSyntaxStyle( style );
250 ui->textLibrary->setSyntaxStyle( style );
259 auto name =
ui->lineEditFunctionName->text();
260 if(
ui->listWidgetFunctions->findItems(
name, Qt::MatchExactly).size()>0)
263 msgBox.setWindowTitle(
"Warning");
264 msgBox.setText(tr(
"A dfunction with the same name exists already.\n" 265 " Do you want to overwrite it?\n"));
266 msgBox.addButton(QMessageBox::Cancel);
267 QPushButton* button = msgBox.addButton(tr(
"Overwrite"), QMessageBox::YesRole);
268 msgBox.setDefaultButton(button);
270 int res = msgBox.exec();
271 if (res < 0 || res == QMessageBox::Cancel)
278 auto lua_function = std::make_shared<ReactiveLuaFunction>(
280 ui->textGlobal->toPlainText(),
281 ui->textFunction->toPlainText(),
282 ui->textLibrary->toPlainText() );
284 (*_transforms)[
name.toStdString()] = lua_function;
286 if(
ui->listWidgetFunctions->findItems(
name, Qt::MatchExactly).empty() )
288 ui->listWidgetFunctions->addItem(
name);
289 ui->listWidgetFunctions->sortItems();
292 auto item =
ui->listWidgetFunctions->findItems(
name, Qt::MatchExactly).first();
295 for(
auto& new_name: lua_function->createdCurves() )
300 catch(std::runtime_error& err)
302 QMessageBox::warning(
nullptr,
"Error in Lua code", QString(err.what()), QMessageBox::Cancel);
305 auto prev_items =
ui->listWidgetRecent->findItems(
name, Qt::MatchExactly);
307 if( prev_items.empty() )
309 while(
ui->listWidgetRecent->count() >= 10 )
311 delete ui->listWidgetRecent->takeItem(0);
316 auto row =
ui->listWidgetRecent->row( prev_items.first() );
317 delete ui->listWidgetRecent->takeItem(row);
321 auto new_item =
new QListWidgetItem(
name);
322 setItemData(new_item,
name,
ui->textGlobal->toPlainText(),
ui->textFunction->toPlainText());
323 ui->listWidgetRecent->addItem(new_item);
325 QDomDocument xml_doc;
326 auto root = xml_doc.createElement(
"functions");
328 for(
int row = 0; row <
ui->listWidgetRecent->count(); row++)
330 auto item =
ui->listWidgetRecent->item(row);
333 auto elem = xml_doc.createElement(
"function");
334 elem.setAttribute(
"name", fields.name);
335 elem.setAttribute(
"global", fields.global_code);
336 elem.setAttribute(
"function", fields.function_code);
337 root.appendChild(elem);
339 xml_doc.appendChild(root);
342 settings.setValue(
"ToolboxLuaEditor/recent_functions", xml_doc.toString());
347 for(
auto item:
ui->listWidgetFunctions->selectedItems())
351 int row =
ui->listWidgetFunctions->row(item);
352 delete ui->listWidgetFunctions->takeItem(row);
358 auto item =
ui->listWidgetRecent->item(index.row());
360 ui->lineEditFunctionName->setText(fields.name);
361 ui->textGlobal->setPlainText(fields.global_code);
362 ui->textFunction->setPlainText(fields.function_code);
367 auto item =
ui->listWidgetFunctions->item(index.row());
369 ui->lineEditFunctionName->setText(fields.name);
370 ui->textGlobal->setPlainText(fields.global_code);
371 ui->textFunction->setPlainText(fields.function_code);
378 ui->pushButtonApplyLibrary->setEnabled(
false);
382 QString svg_name =
":/resources/svg/green_circle.svg";
385 ui->labelSemaphore->setToolTip(
"Everything is fine :)");
386 int active_series =
ui->listWidgetFunctions->count();
387 ui->pushButtonApplyLibrary->setEnabled( active_series > 0 );
391 settings.setValue(
"ToolboxLuaEditor/library",
ui->textLibrary->toPlainText());
393 catch(std::runtime_error& ex)
395 QString error_msg = ex.what();
396 ui->labelSemaphore->setToolTip(error_msg);
397 svg_name =
":/resources/svg/red_circle.svg";
398 ui->pushButtonApplyLibrary->setEnabled(
false);
401 QFile file(svg_name);
402 file.open(QFile::ReadOnly | QFile::Text);
403 QByteArray content(file.readAll());
404 QSvgRenderer rr(content);
405 QImage image(
ui->labelSemaphore->width(),
ui->labelSemaphore->height(), QImage::Format_ARGB32);
406 QPainter painter(&image);
407 image.fill(Qt::transparent);
409 ui->labelSemaphore->setPixmap( QPixmap::fromImage(image) );
414 for(
int row = 0; row <
ui->listWidgetFunctions->count(); row++)
416 auto item =
ui->listWidgetFunctions->item(row);
417 auto name = item->text();
420 auto lua_function = std::make_shared<ReactiveLuaFunction>(
421 _plot_data, fields.global_code, fields.function_code,
ui->textLibrary->toPlainText() );
423 (*_transforms)[fields.name.toStdString()] = lua_function;
425 catch(std::runtime_error& err)
427 QMessageBox::warning(
nullptr,
"Error in Lua code", QString(err.what()), QMessageBox::Cancel);
430 ui->pushButtonApplyLibrary->setEnabled(
false);
435 if(obj !=
ui->textGlobal && obj !=
ui->textFunction && obj !=
ui->textLibrary )
440 if (ev->type() == QEvent::DragEnter)
443 auto event =
static_cast<QDragEnterEvent*
>(ev);
444 const QMimeData* mimeData =
event->mimeData();
445 QStringList mimeFormats = mimeData->formats();
446 for (
const QString&
format : mimeFormats)
448 QByteArray encoded = mimeData->data(
format);
449 QDataStream stream(&encoded, QIODevice::ReadOnly);
451 if (
format !=
"curveslist/add_curve")
456 while (!stream.atEnd())
459 stream >> curve_name;
460 if (!curve_name.isEmpty())
467 event->acceptProposedAction();
472 else if (ev->type() == QEvent::Drop)
474 auto text_edit = qobject_cast<QPlainTextEdit*>(obj);
477 text_edit->insertPlainText(QString(
"\"%1\"\n").
arg(
name));
479 _dragging_curves.clear();
482 else if (ev->type() == QEvent::Wheel)
484 QWheelEvent* wheel_event =
dynamic_cast<QWheelEvent*
>(ev);
485 bool ctrl_modifier_pressed =
486 (QGuiApplication::keyboardModifiers() == Qt::ControlModifier);
488 if (ctrl_modifier_pressed)
491 if (wheel_event->delta() < 0)
495 else if (wheel_event->delta() > 0)
501 auto font =
ui->textGlobal->font();
503 ui->textGlobal->setFont( font );
504 ui->textFunction->setFont( font );
505 ui->textLibrary->setFont( font );
508 settings.setValue(
"ToolboxLuaEditor/fonts_size",
_font_size);
518 auto fields = item->data(Qt::UserRole).toStringList();
520 data.
name = fields[0];
529 QString function_code)
531 QStringList save_fields;
532 save_fields.push_back(name);
533 save_fields.push_back(global_code);
534 save_fields.push_back(function_code);
535 item->setData(Qt::UserRole, save_fields);
std::unordered_map< std::string, std::shared_ptr< TransformFunction > > TransformsMap
auto arg(const Char *name, const T &arg) -> detail::named_arg< Char, T >
Class, that describes completer with glsl specific types and functions.
const QPixmap & LoadSvg(QString filename, QString style_name="light")
Class, that describes Qt style parser for QCodeEditor.
Class, that describes C++ code highlighter.
void connectCallback(Function callback)
std::basic_string< Char > format(const text_style &ts, const S &format_str, const Args &... args)