Hacks to allow frame parser to use global variables

This commit is contained in:
Alex Spataru 2022-06-23 20:03:57 -05:00
parent 1883980ba0
commit a92b09d427
4 changed files with 68 additions and 55 deletions

View File

@ -159,17 +159,6 @@ void JSON::Generator::loadJsonMap(const QString &path)
// Save settings
writeSettings(path);
// Construct frame parsing code
m_frameParserCode = document.object().value("frameParser").toString();
if (m_frameParserCode.isEmpty())
m_frameParserCode = Project::CodeEditor::instance().defaultCode();
// Hacks to be able to evaluate the frame parser function
m_frameParserCode = "(" + m_frameParserCode + ")";
// Generate JS function handler
m_frameParserFunction = m_jsEngine.evaluate(m_frameParserCode);
// Load compacted JSON document
document.object().remove("frameParser");
m_jsonMapData = QString::fromUtf8(document.toJson(QJsonDocument::Compact));
@ -271,17 +260,9 @@ void JSON::Generator::readData(const QByteArray &data)
if (jsonMapData().isEmpty())
return;
// Construct JS parser arguments
QJSValueList args;
args << QString::fromUtf8(data) << IO::Manager::instance().separatorSequence();
// Evaluate frame parsing code (which returns a list with all the values)
auto out = m_frameParserFunction.call(args).toVariant().toList();
// Convert JS parser output to QStringList
QVector<QString> fields;
for (auto i = 0; i < out.count(); ++i)
fields.append(out.at(i).toString());
// Get fields from frame parser function
auto fields = Project::CodeEditor::instance().parse(
QString::fromUtf8(data), IO::Manager::instance().separatorSequence());
// Separate incoming data & add it to the JSON map
auto json = jsonMapData().toStdString();
@ -351,19 +332,6 @@ void JSON::Generator::readData(const QByteArray &data)
dataset.insert("value", value);
}
}
// Evaluate JS expresion (if any)
auto evaluatedValue = m_jsEngine.evaluate(value);
// Successful JS evaluation, insert evaluated value
if (evaluatedValue.errorType() == QJSValue::NoError)
{
evaluated = true;
dataset.remove("value");
dataset.insert("value", evaluatedValue.toString());
datasets.removeAt(j);
datasets.insert(j, dataset);
}
}
// Replace evaluated datasets in group

View File

@ -24,8 +24,6 @@
#include <QFile>
#include <QObject>
#include <QJSValue>
#include <QJSEngine>
#include <QSettings>
#include <QJsonArray>
#include <QJsonValue>
@ -117,13 +115,10 @@ private Q_SLOTS:
private:
QFile m_jsonMap;
QJsonObject m_json;
QJSEngine m_jsEngine;
QSettings m_settings;
QString m_jsonMapData;
OperationMode m_opMode;
QJsonParseError m_error;
QString m_frameParserCode;
QJSValue m_frameParserFunction;
QStringList m_latestValidValues;
};
}

View File

@ -119,6 +119,24 @@ QString Project::CodeEditor::defaultCode() const
return code;
}
QStringList Project::CodeEditor::parse(const QString &frame, const QString &separator)
{
// Construct function arguments
QJSValueList args;
args << frame << separator;
// Evaluate frame parsing function
auto out = m_parseFunction.call(args).toVariant().toList();
// Convert output to QStringList
QStringList list;
for (auto i = 0; i < out.count(); ++i)
list.append(out.at(i).toString());
// Return fields list
return list;
}
void Project::CodeEditor::displayWindow()
{
showNormal();
@ -182,11 +200,45 @@ void Project::CodeEditor::onHelpClicked() { }
bool Project::CodeEditor::save(const bool silent)
{
// Validate code
QJSEngine engine;
// Update text edit
if (loadScript(m_textEdit.toPlainText()))
{
m_textEdit.document()->setModified(false);
// Save code inside JSON project
QTimer::singleShot(500, this, SLOT(writeChanges()));
// Show save messagebox
if (!silent)
Misc::Utilities::showMessageBox(
tr("Frame parser code updated successfully!"),
tr("No errors have been detected in the code."));
// Everything good
return true;
}
// Something did not work quite right
return false;
}
bool Project::CodeEditor::loadScript(const QString &script)
{
// Check if there are no general JS errors
QStringList errors;
m_engine.evaluate(script, "", 1, &errors);
// Check if parse() function exists
auto fun = m_engine.globalObject().property("parse");
if (fun.isNull() || !fun.isCallable())
{
Misc::Utilities::showMessageBox(tr("Frame parser error!"),
tr("No parse() function has been declared!"));
return false;
}
// Try to run parse() function
QJSValueList args = { "", "," };
auto fun = engine.evaluate("(" + m_textEdit.toPlainText() + ")", "", 1, &errors);
auto ret = fun.call(args);
// Error on engine evaluation
@ -233,18 +285,8 @@ bool Project::CodeEditor::save(const bool silent)
return false;
}
// Update text edit
m_textEdit.document()->setModified(false);
// Save code inside JSON project
QTimer::singleShot(500, this, SLOT(writeChanges()));
// Show save messagebox
if (!silent)
Misc::Utilities::showMessageBox(tr("Frame parser code updated successfully!"),
tr("No errors have been detected in the code."));
// Everything good
// We have reached this point without any errors, set function caller
m_parseFunction = fun;
return true;
}
@ -283,6 +325,7 @@ void Project::CodeEditor::readCode()
{
m_textEdit.setPlainText(Model::instance().frameParserCode());
m_textEdit.document()->setModified(false);
loadScript(m_textEdit.toPlainText());
}
void Project::CodeEditor::writeChanges()

View File

@ -30,6 +30,9 @@
#include <QPushButton>
#include <QPlainTextEdit>
#include <QJSValue>
#include <QJSEngine>
#include <QSourceHighlite/qsourcehighliter.h>
namespace Project
@ -49,6 +52,7 @@ private:
public:
static CodeEditor &instance();
QString defaultCode() const;
QStringList parse(const QString &frame, const QString &separator);
public Q_SLOTS:
void displayWindow();
@ -62,6 +66,7 @@ private Q_SLOTS:
private:
bool checkModified();
bool save(const bool silent = false);
bool loadScript(const QString &script);
void closeEvent(QCloseEvent *event) override;
private slots:
@ -69,7 +74,9 @@ private slots:
void writeChanges();
private:
QJSEngine m_engine;
QToolBar m_toolbar;
QJSValue m_parseFunction;
QPlainTextEdit m_textEdit;
QSourceHighlite::QSourceHighliter *m_highlighter;
};