6 #include <QElapsedTimer> 11 snippet.
name.toStdString(),
23 int pos1 =
function.indexOf(
"$$", offset);
28 int pos2 =
function.indexOf(
"$$", pos1+2);
33 output.push_back(
function.mid(pos1+2, pos2-pos1-2) );
40 const std::string &plotName,
42 const QString &
function):
55 int pos1=replaced_equation.indexOf(
"$$");
60 int pos2 = replaced_equation.indexOf(
"$$", pos1+2);
63 throw std::runtime_error(
"syntax error : invalid use of $$ macro");
66 QString channel_name = replaced_equation.mid(pos1+2, pos2-pos1-2);
68 if(channel_name == qLinkedPlot)
71 replaced_equation.replace(QStringLiteral(
"$$%1$$").
arg(channel_name), QStringLiteral(
"value"));
75 QString jsExpression = QString(
"CHANNEL_VALUES[%1]").arg(
_used_channels.size());
76 replaced_equation.replace(QStringLiteral(
"$$%1$$").
arg(channel_name), jsExpression);
88 bool newly_added =
false;
91 if(dst_data_it == plotData.
numeric.end())
97 PlotData& dst_data = dst_data_it->second;
107 plotData.
numeric.erase( dst_data_it );
109 std::rethrow_exception( std::current_exception() );
115 _jsEngine = std::unique_ptr<QJSEngine>(
new QJSEngine() );
118 if(globalVarResult.isError())
120 throw std::runtime_error(
"JS Engine : " + globalVarResult.toString().toStdString());
122 QString calcMethodStr = QString(
"function calc(time, value, CHANNEL_VALUES){with (Math){\n%1\n}}").arg(
_function_replaced);
128 const std::vector<const PlotData*>& channels_data,
129 QJSValue& chan_values,
132 const PlotData::Point &old_point = src_data.
at(point_index);
135 for(
const PlotData* chan_data: channels_data)
138 int index = chan_data->getIndexFromX(old_point.x);
140 value = chan_data->at(index).y;
143 value = std::numeric_limits<double>::quiet_NaN();
145 chan_values.setProperty(static_cast<quint32>(chan_index++), QJSValue(value));
148 PlotData::Point new_point;
149 new_point.x = old_point.x;
151 QJSValue jsData = calcFct.call({QJSValue(old_point.x), QJSValue(old_point.y), chan_values});
154 throw std::runtime_error(
"JS Engine : " + jsData.toString().toStdString());
156 new_point.y = jsData.toNumber();
163 QJSValue calcFct =
_jsEngine->evaluate(
"calc");
165 if(calcFct.isError())
167 throw std::runtime_error(
"JS Engine : " + calcFct.toString().toStdString());
171 if(src_data_it == plotData.
numeric.end())
176 const PlotData& src_data = src_data_it->second;
181 std::vector<const PlotData*> channel_data;
186 auto it = plotData.
numeric.find(channel);
187 if(it == plotData.
numeric.end())
189 throw std::runtime_error(
"Invalid channel name");
191 const PlotData* chan_data = &(it->second);
192 channel_data.push_back(chan_data);
195 QJSValue chan_values =
_jsEngine->newArray(static_cast<quint32>(_used_channels.size()));
197 for(
size_t i=0;
i < src_data.
size(); ++
i)
204 if (dst_data->
size() != 0){
233 QDomElement snippet = doc.createElement(
"snippet");
234 snippet.setAttribute(
"name", QString::fromStdString(
_plot_name) );
236 QDomElement linked = doc.createElement(
"linkedPlot");
237 linked.appendChild( doc.createTextNode( QString::fromStdString(
_linked_plot_name)) );
238 snippet.appendChild(linked);
240 QDomElement global = doc.createElement(
"global");
242 snippet.appendChild(global);
244 QDomElement equation = doc.createElement(
"equation");
245 equation.appendChild( doc.createTextNode(
_function) );
246 snippet.appendChild(equation);
253 auto name = element.attribute(
"name").toStdString();
254 auto linkedPlot = element.firstChildElement(
"linkedPlot").text().trimmed().toStdString();
255 auto globalVars = element.firstChildElement(
"global").text().trimmed();
256 auto calcEquation = element.firstChildElement(
"equation").text().trimmed();
258 return std::make_shared<CustomFunction>(linkedPlot,
name,
globalVars, calcEquation );
263 if( xml_text.isEmpty() )
return {};
266 QString parseErrorMsg;
268 if(!doc.setContent(xml_text, &parseErrorMsg, &parseErrorLine))
270 QMessageBox::critical(
nullptr,
"Error",
271 QString(
"Failed to parse snippets (xml), error %1 at line %2")
272 .
arg(parseErrorMsg).
arg(parseErrorLine));
277 QDomElement snippets_element = doc.documentElement();
286 for (
auto elem = snippets_element.firstChildElement(
"snippet");
288 elem = elem.nextSiblingElement(
"snippet"))
291 snippet.
name = elem.attribute(
"name");
292 snippet.
globalVars = elem.firstChildElement(
"global").text().trimmed();
293 snippet.
equation = elem.firstChildElement(
"equation").text().trimmed();
294 snippets.insert( {snippet.
name, snippet } );
301 auto snippets_root = doc.createElement(
"snippets");
303 for (
const auto& it: snippets )
305 const auto& snippet = it.second;
307 auto element = doc.createElement(
"snippet");
308 element.setAttribute(
"name", it.first);
310 auto global_el = doc.createElement(
"global");
311 global_el.appendChild( doc.createTextNode( snippet.globalVars ) );
313 auto equation_el = doc.createElement(
"equation");
314 equation_el.appendChild( doc.createTextNode( snippet.equation ) );
316 element.appendChild( global_el );
317 element.appendChild( equation_el );
318 snippets_root.appendChild( element );
320 return snippets_root;
std::unordered_map< std::string, PlotData > numeric
void setMaximumRangeX(Time max_range)
const Point & at(size_t index) const
std::vector< std::string > _used_channels
PlotData::Point calculatePoint(QJSValue &calcFct, const PlotData &src_data, const std::vector< const PlotData * > &channels_data, QJSValue &chan_values, size_t point_index)
std::map< QString, SnippetData > SnippetsMap
CustomFunction(const std::string &linkedPlot, const std::string &plotName, const QString &globalVars, const QString &function)
const QString _global_vars
const std::string & name() const
std::unique_ptr< QJSEngine > _jsEngine
QDomElement ExportSnippets(const SnippetsMap &snippets, QDomDocument &doc)
const std::string & linkedPlotName() const
TFSIMD_FORCE_INLINE const tfScalar & x() const
static QStringList getChannelsFromFuntion(const QString &function)
const std::string _plot_name
void calculate(const PlotDataMapRef &plotData, PlotData *dst_data)
const QString & globalVars() const
std::shared_ptr< CustomFunction > CustomPlotPtr
double _last_updated_timestamp
SnippetsMap GetSnippetsFromXML(const QString &xml_text)
virtual size_t size() const
QString _function_replaced
static CustomPlotPtr createFromXML(QDomElement &element)
const std::string _linked_plot_name
std::unordered_map< std::string, PlotData >::iterator addNumeric(const std::string &name)
const Point & back() const
const QString & function() const
Time maximumRangeX() const
QDomElement xmlSaveState(QDomDocument &doc) const
void calculateAndAdd(PlotDataMapRef &plotData)