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());
47inline bool copyDirectoryRecursively(
const QString& sourcePath,
const QString& destPath)
49 QDir sourceDir(sourcePath);
50 if(!sourceDir.exists())
55 QDir destDir(destPath);
57 if(!destDir.exists() && !destDir.mkpath(
"."))
65 const QFileInfoList entries = sourceDir.entryInfoList(
66 QDir::NoDotAndDotDot | QDir::AllEntries | QDir::Hidden | QDir::System);
68 for(
const QFileInfo& entryInfo : entries)
70 QString newDestPath = destDir.absoluteFilePath(entryInfo.fileName());
75 if(!copyDirectoryRecursively(entryInfo.absoluteFilePath(), newDestPath))
83 if(QFile::exists(newDestPath))
85 QFile::remove(newDestPath);
88 if(!QFile::copy(entryInfo.absoluteFilePath(), newDestPath))
98inline bool copyParentFolderContents(
const QString& rootPath,
const QString& dst)
100 QFileInfo fileInfo(rootPath);
102 QString parentFolder = fileInfo.absolutePath();
104 return copyDirectoryRecursively(parentFolder, dst);
107inline void loadJSObjectFromString(
108 const QString& rootPath,
const QByteArray& str, QQmlComponent& comp,
bool is_ui)
110#if __has_include(<boost/hash2/xxh3.hpp>)
111 static const auto cache_path = QStandardPaths::writableLocation(QStandardPaths::CacheLocation);
112 QFile f{cache_path +
"/Script" + hashFileData(str) + (is_ui ?
".ui.qml" :
".qml")};
113 if(f.open(QIODevice::ReadWrite))
116 if(str != f.readAll())
124 copyParentFolderContents(rootPath, cache_path);
126 comp.loadUrl(QUrl::fromLocalFile(f.fileName()));
131 comp.setData(str, QUrl::fromLocalFile(rootPath));
135inline JS::Script* createJSObject(QQmlComponent& c, QQmlContext* context)
137 const auto& errs = c.errors();
140 ossia::logger().error(
141 "Uncaught exception at line {} : {}", errs[0].line(),
142 errs[0].toString().toStdString());
147 auto object = c.create(context);
148 auto obj = qobject_cast<JS::Script*>(
object);
157 const QString& rootPath,
const QString& val, QQmlEngine* engine,
158 QQmlContext* context)
160 if(val.trimmed().startsWith(
"import"))
162 QQmlComponent c{engine};
163 loadJSObjectFromString(rootPath, val.toUtf8(), c,
false);
164 return createJSObject(c, context);
166 else if(QFile::exists(val))
168 QQmlComponent c{engine, QUrl::fromLocalFile(val)};
169 return createJSObject(c, context);
174inline void setupExecFuncs(
auto* self, QObject* context, ossia::qt::qml_engine_functions* m_execFuncs)
177 m_execFuncs, &ossia::qt::qml_engine_functions::system, qApp,
178 [](
const QString& code) {
179 std::thread{[code] { ::system(code.toStdString().c_str()); }}.detach();
180 }, Qt::QueuedConnection);
185 m_execFuncs, &ossia::qt::qml_engine_functions::exec, js_panel,
186 &JS::PanelDelegate::evaluate, Qt::QueuedConnection);
189 m_execFuncs, &ossia::qt::qml_engine_functions::compute, m_execFuncs,
190 [self, context, m_execFuncs, js_panel](
const QString& code,
const QString& cbname) {
195 , context=QPointer{context}
196 , cur = QPointer{self->m_object}
198 , cbname] (
const QVariant& v) {
203 ossia::qt::run_async(m_execFuncs, [self, context, cur, v, cbname] {
206 if(self->m_object != cur)
209 auto mo = self->m_object->metaObject();
210 for(
int i = 0; i < mo->methodCount(); i++)
212 if(mo->method(i).name() == cbname)
214 mo->method(i).invoke(
215 self->m_object, Qt::DirectConnection, QGenericReturnArgument(),
216 QArgument<QVariant>{
"v", v});
223 ossia::qt::run_async(js_panel, [js_panel, code, cb]() {
224 js_panel->compute(code, cb);
226 }, Qt::DirectConnection);
Definition ConsolePanel.hpp:40
Definition QmlObjects.hpp:845