• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

ossia / score / 32671464175

23 Aug 2026 10:43PM UTC coverage: 23.21% (+1.6%) from 21.606%
32671464175

push

github

jcelerier
scenario: export NodalIntervalView

test_integration_nodal_viewport and test_integration_cable_drag_view_scroll
call into the class from outside the plug-in, so a shared-plugin build could
not link either of them: the library held 136 NodalIntervalView symbols and
exported none. A static-plugin build never sees it, which is why CI does not.

51875 of 223502 relevant lines covered (23.21%)

63063.32 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

59.0
/src/plugins/score-plugin-js/JS/ApplicationPlugin.cpp
1
#include "ApplicationPlugin.hpp"
2

3
#include <JS/DocumentPlugin.hpp>
4
#include <JS/Qml/DeviceContext.hpp>
5
#include <JS/Qml/EditContext.hpp>
6
#include <JS/Qml/Utils.hpp>
7
#include <JS/Qml/ViewContext.hpp>
8
#include <Library/LibrarySettings.hpp>
9
#include <LocalTree/LocalTreeDocumentPlugin.hpp>
10

11
#include <core/application/ApplicationInterface.hpp>
12
#include <core/document/Document.hpp>
13
#include <core/presenter/DocumentManager.hpp>
14

15
#include <ossia/detail/thread.hpp>
16

17
#include <ossia-qt/invoke.hpp>
18
#include <ossia-qt/qml_protocols.hpp>
19

20
#include <QCommandLineParser>
21

22
#if __has_include(<QQuickWindow>)
23
#include <QGuiApplication>
24
#include <QQuickItem>
25
#include <QQuickWindow>
26
#endif
27

28
#if SCORE_HAS_GPU_JS
29
#include <Gfx/Settings/Model.hpp>
30
#endif
31

32
#include <ossia/network/context.hpp>
33

34
namespace JS
35
{
36
ApplicationPlugin::ApplicationPlugin(const score::GUIApplicationContext& ctx)
244✔
37
    : score::GUIApplicationPlugin{ctx}
244✔
38
{
244✔
39
#if __has_include(<QQuickWindow>)
40
  // Crisp text in every QML UI: distance-field rendering looks blurry at the small
41
  // font sizes our panels use, native glyph rendering matches the rest of score.
42
  QQuickWindow::setTextRenderType(QQuickWindow::NativeTextRendering);
244✔
43
#endif
44

45
  // For the console
46
  m_consoleEngine.globalObject().setProperty("Score", m_consoleEngine.newQObject(new EditJsContext));
244✔
47
  m_consoleEngine.globalObject().setProperty("Util", m_consoleEngine.newQObject(new JsUtils));
244✔
48
  m_consoleEngine.globalObject().setProperty(
488✔
49
      "System", m_consoleEngine.newQObject(new JsSystem));
244✔
50
  m_consoleEngine.globalObject().setProperty(
488✔
51
      "Library", m_consoleEngine.newQObject(new JsLibrary));
244✔
52
  m_consoleEngine.globalObject().setProperty("Device", m_consoleEngine.newQObject(new DeviceContext{m_consoleEngine}));
244✔
53
  m_consoleEngine.globalObject().setProperty("View", m_consoleEngine.newQObject(new JsViewContext));
244✔
54
  connect(&m_consoleEngine, &QQmlEngine::exit, this, [&] {
244✔
55
    for(auto& doc : score::GUIAppContext().docManager.documents())
×
56
      doc->commandStack().markCurrentIndexAsSaved();
×
57
    qApp->quit();
×
58
    QTimer::singleShot(
×
59
        500, [] { score::GUIApplicationInterface::instance().forceExit(); });
×
60
  });
×
61
  m_asioContext = std::make_shared<ossia::net::network_context>();
244✔
62
  m_processMessages = true;
244✔
63
  m_consoleEngine.globalObject().setProperty(
488✔
64
      "Protocols",
244✔
65
      m_consoleEngine.newQObject(new ossia::qt::qml_protocols{m_asioContext, this}));
244✔
66
  m_asioThread = std::thread{[this] {
488✔
67
    ossia::set_thread_name("ossia app asio");
244✔
68
    while(m_processMessages)
488✔
69
    {
70
      m_asioContext->run();
244✔
71
    }
72
  }};
244✔
73

74
  // For scripts of processes that run in the ui thread:
75
  m_scriptProcessUIEngine.globalObject().setProperty(
488✔
76
      "Util", m_scriptProcessUIEngine.newQObject(new JsUtils));
244✔
77
  m_scriptProcessUIEngine.globalObject().setProperty(
488✔
78
      "System", m_scriptProcessUIEngine.newQObject(new JsSystem));
244✔
79
  m_scriptProcessUIEngine.globalObject().setProperty(
488✔
80
      "Library", m_scriptProcessUIEngine.newQObject(new JsLibrary));
244✔
81
  m_scriptProcessUIEngine.globalObject().setProperty(
488✔
82
      "View", m_scriptProcessUIEngine.newQObject(new JsViewContext));
244✔
83

84
  // Command-line option parsing
85
  QCommandLineParser parser;
244✔
86

87
  QCommandLineOption script_opt(
244✔
88
      "script", QCoreApplication::translate("js", "script"), "Script", "");
244✔
89
  parser.addOption(script_opt);
244✔
90

91
  parser.parse(ctx.applicationSettings.arguments);
244✔
92
  this->m_start_script = parser.value(script_opt);
244✔
93
}
×
94

95
void ApplicationPlugin::on_newDocument(score::Document& doc)
130✔
96
{
97
  score::addDocumentPlugin<DocumentPlugin>(doc);
130✔
98
}
130✔
99

100
ApplicationPlugin::~ApplicationPlugin()
486✔
101
{
243✔
102
  m_processMessages = false;
243✔
103
  m_asioContext->context.stop();
243✔
104
  m_asioThread.join();
243✔
105
}
486✔
106

107
void ApplicationPlugin::on_createdDocument(score::Document& doc)
139✔
108
{
109
  // Local Tree
110
  LocalTree::DocumentPlugin* lt = doc.context().findPlugin<LocalTree::DocumentPlugin>();
139✔
111
  if(lt)
139✔
112
  {
113
    auto& root = lt->device().get_root_node();
139✔
114

115
    auto node = root.create_child("script");
139✔
116
    auto address = node->create_parameter(ossia::val_type::STRING);
139✔
117
    address->set_value(std::string{});
139✔
118
    address->set_access(ossia::access_mode::SET);
139✔
119
    address->add_callback([&](const ossia::value& v) {
139✔
120
      ossia::qt::run_async(
×
121
          this, [this, str = QString::fromStdString(ossia::convert<std::string>(v))] {
×
122
        auto res = m_consoleEngine.evaluate(str);
×
123
        if(res.isError())
×
124
        {
125
          qDebug() << res.toString();
×
126
        }
×
127
      });
×
128
    });
×
129
  }
139✔
130

131
  // Custom data
132
  if(auto customData = doc.context().findPlugin<DocumentPlugin>(); !customData)
139✔
133
    score::addDocumentPlugin<DocumentPlugin>(doc);
×
134

135
  if(!m_start_script.isEmpty())
139✔
136
  {
137
    QTimer::singleShot(100, this, [this] { m_consoleEngine.evaluate(m_start_script); });
×
138
  }
×
139
}
139✔
140
void ApplicationPlugin::afterStartup()
×
141
{
142
  // Dummy engine setup for JS processes
143
  // eng.importModule(
144
  //     "/home/jcelerier/Documents/ossia/score/packages/default/Scripts/include/"
145
  //     "tonal.mjs");
146
  for(auto& p : this->context.settings<Library::Settings::Model>().getIncludePaths())
×
147
  {
148
    m_scriptProcessUIEngine.addImportPath(p);
×
149
  }
150

151
#if __has_include(<QQuickWindow>)
152
  if(QFileInfo f{context.applicationSettings.ui}; f.isFile())
×
153
  {
154
    m_comp = new QQmlComponent{&m_consoleEngine, f.absoluteFilePath(), this};
×
155

156
    if(auto obj = m_comp->create())
×
157
    {
158
      if(auto item = qobject_cast<QQuickItem*>(obj))
×
159
      {
160
        m_window = new QQuickWindow{};
×
161
  // QWidget gets these from QWidgetPrivate::adjustFlags; a bare QQuickWindow
162
  // does not, and on platforms where Qt draws the chrome itself (wasm) that
163
  // leaves the window with no title bar, close or minimise button.
164
  m_window->setFlags(
×
165
      m_window->flags() | Qt::Window | Qt::WindowTitleHint | Qt::WindowSystemMenuHint
×
166
      | Qt::WindowCloseButtonHint | Qt::WindowMinimizeButtonHint
×
167
      | Qt::WindowMaximizeButtonHint);
×
168
#if defined(__EMSCRIPTEN__)
169
  // Qt for wasm reports ShowIsFullScreen unconditionally, so QWindow::show()
170
  // turns into showFullScreen() for every top level: the requested size is
171
  // discarded and the full-screen state suppresses the frame. Only Qt::Dialog
172
  // and Qt::Popup opt out (QWasmIntegration::defaultWindowState).
173
  m_window->setFlags(m_window->flags() | Qt::Dialog);
174
#endif
175
        m_window->setWidth(640);
×
176
        m_window->setHeight(480);
×
177
        item->setParentItem(m_window->contentItem());
×
178
#if defined(__EMSCRIPTEN__)
179
        m_window->showNormal();
180
#else
181
        m_window->show();
×
182
#endif
183
        return;
×
184
      }
185
    }
×
186
    else
187
    {
188
      qDebug() << m_comp->errorString();
×
189
      qGuiApp->exit(1);
×
190
    }
191
    delete m_comp;
×
192
  }
×
193
#endif
194
}
×
195
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc