From 40d0f1c41f51d0c226519ae1c926b7faf440275c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Micha=C3=ABl=20Celerier?= Date: Sun, 12 Jan 2025 19:38:33 -0500 Subject: [PATCH] local tree: allow copy-paste of local tree address of inlets and objects --- .../LocalTree/ProcessComponent.hpp | 1 + .../score-lib-process/Process/Process.cpp | 16 ++++++- .../score-lib-process/Process/Process.hpp | 3 ++ .../Dataflow/PortItem.cpp | 28 +++++++++--- .../LocalTree/EventComponent.hpp | 1 + .../LocalTree/IntervalComponent.hpp | 1 + .../LocalTree/LTIntervalComponent.cpp | 28 +++++++----- .../LocalTree/StateComponent.hpp | 1 + .../LocalTree/TimeSyncComponent.hpp | 1 + .../Inspector/ObjectTree/ObjectItemModel.cpp | 44 +++++++++++++++++-- 10 files changed, 103 insertions(+), 21 deletions(-) diff --git a/src/plugins/score-lib-process/LocalTree/ProcessComponent.hpp b/src/plugins/score-lib-process/LocalTree/ProcessComponent.hpp index 1fc72ada12..795006403e 100644 --- a/src/plugins/score-lib-process/LocalTree/ProcessComponent.hpp +++ b/src/plugins/score-lib-process/LocalTree/ProcessComponent.hpp @@ -16,6 +16,7 @@ class SCORE_LIB_PROCESS_EXPORT ProcessComponent ABSTRACT_COMPONENT_METADATA( LocalTree::ProcessComponent, "0732ab51-a052-4e2e-a1f7-9bf2926c199c") public: + static constexpr bool is_unique = true; ProcessComponent( ossia::net::node_base& node, Process::ProcessModel& proc, const score::DocumentContext& doc, const QString& name, QObject* parent); diff --git a/src/plugins/score-lib-process/Process/Process.cpp b/src/plugins/score-lib-process/Process/Process.cpp index c61dbfa9b9..cadee11092 100644 --- a/src/plugins/score-lib-process/Process/Process.cpp +++ b/src/plugins/score-lib-process/Process/Process.cpp @@ -7,6 +7,9 @@ #include #include +#include + +#include #include #include #include @@ -16,12 +19,13 @@ #include #include +#include +#include #include #include -#include W_OBJECT_IMPL(Process::ProcessModel) #if !defined(SCORE_ALL_UNITY) @@ -362,4 +366,14 @@ const ProcessModel* parentProcess(const QObject* obj) noexcept return static_cast(obj); return nullptr; } + +QString processLocalTreeAddress(const ProcessModel& proc) +{ + if(auto lt = findComponent(proc.components())) + { + return QString::fromStdString( + lt->node().get_device().get_name() + ":" + lt->node().osc_address()); + } + return {}; +} } diff --git a/src/plugins/score-lib-process/Process/Process.hpp b/src/plugins/score-lib-process/Process/Process.hpp index 99ab07db34..5a496b74ed 100644 --- a/src/plugins/score-lib-process/Process/Process.hpp +++ b/src/plugins/score-lib-process/Process/Process.hpp @@ -234,6 +234,9 @@ SCORE_LIB_PROCESS_EXPORT ProcessModel* parentProcess(QObject* obj) noexcept; SCORE_LIB_PROCESS_EXPORT const ProcessModel* parentProcess(const QObject* obj) noexcept; + +SCORE_LIB_PROCESS_EXPORT +QString processLocalTreeAddress(const Process::ProcessModel& proc); } DEFAULT_MODEL_METADATA(Process::ProcessModel, "Process") diff --git a/src/plugins/score-plugin-dataflow/Dataflow/PortItem.cpp b/src/plugins/score-plugin-dataflow/Dataflow/PortItem.cpp index 1a28025272..5bd9cd346c 100644 --- a/src/plugins/score-plugin-dataflow/Dataflow/PortItem.cpp +++ b/src/plugins/score-plugin-dataflow/Dataflow/PortItem.cpp @@ -24,6 +24,7 @@ #include #include +#include #include #include #include @@ -31,7 +32,7 @@ namespace Dataflow { template -bool intersection_empty(const Vec& v1, const Vec& v2) +static bool intersection_empty(const Vec& v1, const Vec& v2) { for(const auto& e1 : v1) { @@ -105,10 +106,27 @@ void AutomatablePortItem::setupMenu(QMenu& menu, const score::DocumentContext& c return; if(this->port().type() != Process::PortType::Message) return; - auto act = menu.addAction(QObject::tr("Create automation")); - QObject::connect( - act, &QAction::triggered, this, [this, &ctx] { on_createAutomation(ctx); }, - Qt::QueuedConnection); + { + auto act = menu.addAction(QObject::tr("Create automation")); + QObject::connect(act, &QAction::triggered, this, [this, &ctx] { + on_createAutomation(ctx); + }, Qt::QueuedConnection); + } + + if(auto proc = qobject_cast(this->port().parent())) + { + if(auto addr = Process::processLocalTreeAddress(*proc); !addr.isEmpty()) + { + addr += "/"; + addr += this->port().exposed(); + addr += "/value"; + auto act = menu.addAction(QObject::tr("Copy address")); + QObject::connect(act, &QAction::triggered, &port(), [addr] { + auto& cb = *qApp->clipboard(); + cb.setText(addr); + }, Qt::QueuedConnection); + } + } } void AutomatablePortItem::on_createAutomation(const score::DocumentContext& ctx) diff --git a/src/plugins/score-plugin-scenario/LocalTree/EventComponent.hpp b/src/plugins/score-plugin-scenario/LocalTree/EventComponent.hpp index 12962e74bb..ba4914ffbb 100644 --- a/src/plugins/score-plugin-scenario/LocalTree/EventComponent.hpp +++ b/src/plugins/score-plugin-scenario/LocalTree/EventComponent.hpp @@ -9,6 +9,7 @@ class SCORE_PLUGIN_SCENARIO_EXPORT Event final : public CommonComponent { COMMON_COMPONENT_METADATA("918b757d-d304-4362-bbd3-120f84e229fe") public: + static constexpr bool is_unique = true; Event( ossia::net::node_base& parent, Scenario::EventModel& event, const score::DocumentContext& doc, QObject* parent_comp); diff --git a/src/plugins/score-plugin-scenario/LocalTree/IntervalComponent.hpp b/src/plugins/score-plugin-scenario/LocalTree/IntervalComponent.hpp index 36f08295d9..a132291286 100644 --- a/src/plugins/score-plugin-scenario/LocalTree/IntervalComponent.hpp +++ b/src/plugins/score-plugin-scenario/LocalTree/IntervalComponent.hpp @@ -13,6 +13,7 @@ class SCORE_PLUGIN_SCENARIO_EXPORT IntervalBase { COMMON_COMPONENT_METADATA("11d928b5-eaeb-471c-b3b7-dc453180b10f") public: + static constexpr bool is_unique = true; using parent_t = Component>; using model_t = Process::ProcessModel; diff --git a/src/plugins/score-plugin-scenario/LocalTree/LTIntervalComponent.cpp b/src/plugins/score-plugin-scenario/LocalTree/LTIntervalComponent.cpp index 8eb090c90f..79b5c3f0e3 100644 --- a/src/plugins/score-plugin-scenario/LocalTree/LTIntervalComponent.cpp +++ b/src/plugins/score-plugin-scenario/LocalTree/LTIntervalComponent.cpp @@ -81,20 +81,20 @@ auto add_value_property( } class DefaultProcessComponent final : public ProcessComponent { - COMMON_COMPONENT_METADATA("0b801b8f-41db-49ca-a396-c26aadf3f1b5") + COMPONENT_METADATA("0b801b8f-41db-49ca-a396-c26aadf3f1b5") public: DefaultProcessComponent( ossia::net::node_base& node, Process::ProcessModel& proc, const score::DocumentContext& doc, QObject* parent) : ProcessComponent{node, proc, doc, "ProcessComponent", parent} { - try + for(Process::Inlet* inlet : proc.inlets()) { - for(Process::Inlet* inlet : proc.inlets()) + if(auto control = qobject_cast(inlet)) { - if(auto control = qobject_cast(inlet)) + if(!inlet->exposed().isEmpty()) { - if(!inlet->exposed().isEmpty()) + try { m_properties.push_back(add_property( this->node(), *inlet, inlet->exposed().toStdString(), this)); @@ -105,14 +105,20 @@ class DefaultProcessComponent final : public ProcessComponent p.set_domain(control->domain()); m_properties.push_back(std::move(prop)); } + catch(...) + { + } } } + } - for(auto& outlet : proc.outlets()) + for(auto& outlet : proc.outlets()) + { + if(auto control = qobject_cast(outlet)) { - if(auto control = qobject_cast(outlet)) + if(!outlet->exposed().isEmpty()) { - if(!outlet->exposed().isEmpty()) + try { m_properties.push_back(add_property( this->node(), *outlet, outlet->exposed().toStdString(), this)); @@ -123,12 +129,12 @@ class DefaultProcessComponent final : public ProcessComponent p.set_domain(control->domain()); m_properties.push_back(std::move(prop)); } + catch(...) + { + } } } } - catch(...) - { - } } }; diff --git a/src/plugins/score-plugin-scenario/LocalTree/StateComponent.hpp b/src/plugins/score-plugin-scenario/LocalTree/StateComponent.hpp index 2c593a582d..29cb809b04 100644 --- a/src/plugins/score-plugin-scenario/LocalTree/StateComponent.hpp +++ b/src/plugins/score-plugin-scenario/LocalTree/StateComponent.hpp @@ -9,6 +9,7 @@ class SCORE_PLUGIN_SCENARIO_EXPORT State final : public CommonComponent { COMMON_COMPONENT_METADATA("2e5fefa2-3442-4c08-9f3e-564ab65f7b22") public: + static constexpr bool is_unique = true; State( ossia::net::node_base& parent, Scenario::StateModel& event, const score::DocumentContext& doc, QObject* parent_comp); diff --git a/src/plugins/score-plugin-scenario/LocalTree/TimeSyncComponent.hpp b/src/plugins/score-plugin-scenario/LocalTree/TimeSyncComponent.hpp index e0a274d488..847ca981a8 100644 --- a/src/plugins/score-plugin-scenario/LocalTree/TimeSyncComponent.hpp +++ b/src/plugins/score-plugin-scenario/LocalTree/TimeSyncComponent.hpp @@ -9,6 +9,7 @@ class SCORE_PLUGIN_SCENARIO_EXPORT TimeSync final : public CommonComponent { COMMON_COMPONENT_METADATA("104e4446-b09f-4bf6-92ef-0fe360397066") public: + static constexpr bool is_unique = true; TimeSync( ossia::net::node_base& parent, Scenario::TimeSyncModel& event, const score::DocumentContext& doc, QObject* parent_comp); diff --git a/src/plugins/score-plugin-scenario/Scenario/Inspector/ObjectTree/ObjectItemModel.cpp b/src/plugins/score-plugin-scenario/Scenario/Inspector/ObjectTree/ObjectItemModel.cpp index 38ddba5422..d0495fb434 100644 --- a/src/plugins/score-plugin-scenario/Scenario/Inspector/ObjectTree/ObjectItemModel.cpp +++ b/src/plugins/score-plugin-scenario/Scenario/Inspector/ObjectTree/ObjectItemModel.cpp @@ -27,16 +27,25 @@ #include #include +#include +#include +#include +#include +#include #include #include #include +#include #include #include #include #include #include +#include +#include + #include #include #include @@ -1141,10 +1150,37 @@ void ObjectWidget::contextMenuEvent(QContextMenuEvent* ev) QMenu* m = new QMenu{this}; m->addAction(tr("Copy remote control path"), [ptr] { - auto path = score::IDocument::unsafe_path(*ptr); - - auto& cb = *qApp->clipboard(); - cb.setText(path.toString()); + std::string path; + if(auto cst = qobject_cast(ptr)) + { + if(auto lt = findComponent(cst->components())) + path = lt->node().get_device().get_name() + ":" + lt->node().osc_address(); + } + else if(auto ev = qobject_cast(ptr)) + { + if(auto lt = findComponent(ev->components())) + path = lt->node().get_device().get_name() + ":" + lt->node().osc_address(); + } + else if(auto tn = qobject_cast(ptr)) + { + if(auto lt = findComponent(tn->components())) + path = lt->node().get_device().get_name() + ":" + lt->node().osc_address(); + } + else if(auto st = qobject_cast(ptr)) + { + if(auto lt = findComponent(st->components())) + path = lt->node().get_device().get_name() + ":" + lt->node().osc_address(); + } + else if(auto p = qobject_cast(ptr)) + { + if(auto lt = findComponent(p->components())) + path = lt->node().get_device().get_name() + ":" + lt->node().osc_address(); + } + if(!path.empty()) + { + auto& cb = *qApp->clipboard(); + cb.setText(QString::fromStdString(path)); + } }); if(auto cst = qobject_cast(ptr))