2#include <JS/Qml/QmlObjects.hpp>
3#include <Library/LibrarySettings.hpp>
4#include <score/application/ApplicationContext.hpp>
5#include <score/application/GUIApplicationContext.hpp>
7#include <ossia/detail/logger.hpp>
8#include <ossia-qt/invoke.hpp>
9#include <ossia-qt/qml_engine_functions.hpp>
10#include <JS/ConsolePanel.hpp>
13#include <QQmlComponent>
15#include <QStandardPaths>
18#if __has_include(<boost/hash2/xxh3.hpp>)
19#include <boost/hash2/xxh3.hpp>
20#include <boost/algorithm/hex.hpp>
26static inline QString hashFileData(
const QByteArray& str)
29#if __has_include(<boost/hash2/xxh3.hpp>)
30 boost::hash2::xxh3_128 hasher;
31 hasher.update(str.constData(), str.size());
32 const auto result = hasher.result();
33 std::string hexString;
34 boost::algorithm::hex(result.begin(), result.end(), std::back_inserter(hexString));
37 hexName.push_back(
"-");
38 hexName.append(hexString.data());
43inline void loadJSObjectFromString(
const QByteArray& str, QQmlComponent& comp,
bool is_ui)
46#if __has_include(<boost/hash2/xxh3.hpp>)
47 static const auto cache_path = QStandardPaths::writableLocation(QStandardPaths::CacheLocation);
48 QFile f{cache_path +
"/Script" + hashFileData(str) + (is_ui ?
".ui.qml" :
".qml")};
49 if(f.open(QIODevice::ReadWrite))
52 if(str != f.readAll())
60 comp.loadUrl(QUrl::fromLocalFile(f.fileName()));
65 QString path = lib.getDefaultLibraryPath() + QDir::separator() +
"Scripts"
66 + QDir::separator() +
"include" + QDir::separator() +
"Script" + hashFileData(str) +
".qml";
67 comp.setData(str, QUrl::fromLocalFile(path));
71inline JS::Script* createJSObject(QQmlComponent& c, QQmlContext* context)
73 const auto& errs = c.errors();
76 ossia::logger().error(
77 "Uncaught exception at line {} : {}", errs[0].line(),
78 errs[0].toString().toStdString());
83 auto object = c.create(context);
84 auto obj = qobject_cast<JS::Script*>(
object);
92inline JS::Script* createJSObject(
const QString& val, QQmlEngine* engine, QQmlContext* context)
94 if(val.trimmed().startsWith(
"import"))
96 QQmlComponent c{engine};
97 loadJSObjectFromString(val.toUtf8(), c,
false);
98 return createJSObject(c, context);
100 else if(QFile::exists(val))
102 QQmlComponent c{engine, QUrl::fromLocalFile(val)};
103 return createJSObject(c, context);
108inline void setupExecFuncs(
auto* self, QObject* context, ossia::qt::qml_engine_functions* m_execFuncs)
111 m_execFuncs, &ossia::qt::qml_engine_functions::system, qApp,
112 [](
const QString& code) {
113 std::thread{[code] { ::system(code.toStdString().c_str()); }}.detach();
114 }, Qt::QueuedConnection);
119 m_execFuncs, &ossia::qt::qml_engine_functions::exec, js_panel,
120 &JS::PanelDelegate::evaluate, Qt::QueuedConnection);
123 m_execFuncs, &ossia::qt::qml_engine_functions::compute, m_execFuncs,
124 [self, context, m_execFuncs, js_panel](
const QString& code,
const QString& cbname) {
129 , context=QPointer{context}
130 , cur = QPointer{self->m_object}
132 , cbname] (
const QVariant& v) {
137 ossia::qt::run_async(m_execFuncs, [self, context, cur, v, cbname] {
140 if(self->m_object != cur)
143 auto mo = self->m_object->metaObject();
144 for(
int i = 0; i < mo->methodCount(); i++)
146 if(mo->method(i).name() == cbname)
148 mo->method(i).invoke(
149 self->m_object, Qt::DirectConnection, QGenericReturnArgument(),
150 QArgument<QVariant>{
"v", v});
157 ossia::qt::run_async(js_panel, [js_panel, code, cb]() {
158 js_panel->compute(code, cb);
160 }, Qt::DirectConnection);
Definition ConsolePanel.hpp:40
Definition QmlObjects.hpp:845
Definition LibrarySettings.hpp:46
T & settings() const
Access a specific Settings model instance.
Definition ApplicationContext.hpp:40