/***
Olive - Non-Linear Video Editor
Copyright (C) 2022 Olive Team
Modifications Copyright (C) 2025 mikesolar
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
***/
#include "nodeparamviewcontext.h"
#include
#include "oakengine/node.h"
#include "oakengine/undo.h"
#include "widget/menu/factorymenu.h"
namespace olive
{
#define super NodeParamViewItemBase
NodeParamViewContext::NodeParamViewContext(QWidget *parent)
: super(parent)
, type_(TrackReference::k_none)
{
QWidget *body = new QWidget();
QHBoxLayout *body_layout = new QHBoxLayout(body);
set_body(body);
dock_area_ = new NodeParamViewDockArea();
body_layout->addWidget(dock_area_);
setBackgroundRole(QPalette::Base);
retranslate();
connect(title_bar(), &NodeParamViewItemTitleBar::add_effect_button_clicked,
this, &NodeParamViewContext::add_effect_button_clicked);
}
NodeParamViewItem *NodeParamViewContext::get_item(oak::Node node, oak::Node ctx)
{
for (auto it = items_.begin(); it != items_.end(); it++) {
NodeParamViewItem *item = *it;
if (item->get_node() == node && item->get_context() == ctx) {
return item;
}
}
return nullptr;
}
void NodeParamViewContext::add_node(NodeParamViewItem *item)
{
items_.append(item);
dock_area_->add_item(item);
}
void NodeParamViewContext::remove_node(oak::Node node, oak::Node ctx)
{
for (auto it = items_.begin(); it != items_.end();) {
NodeParamViewItem *item = *it;
if (item->get_node() == node && item->get_context() == ctx) {
emit about_to_delete_item(item);
dock_area_->remove_item(item);
it = items_.erase(it);
} else {
it++;
}
}
}
void NodeParamViewContext::remove_nodes_with_context(oak::Node ctx)
{
for (auto it = items_.begin(); it != items_.end();) {
NodeParamViewItem *item = *it;
if (item->get_context() == ctx) {
emit about_to_delete_item(item);
dock_area_->remove_item(item);
it = items_.erase(it);
} else {
it++;
}
}
}
void NodeParamViewContext::set_input_checked(const oak::Input &input, bool e)
{
foreach (NodeParamViewItem *item, items_) {
if (item->get_node() == input.node()) {
item->set_input_checked(input, e);
}
}
}
void NodeParamViewContext::set_timebase(const Rational &timebase)
{
foreach (NodeParamViewItem *item, items_) {
item->set_timebase(timebase);
}
}
void NodeParamViewContext::set_time_target(OakEngineNode *n)
{
foreach (NodeParamViewItem *item, items_) {
item->set_time_target(n);
}
}
void NodeParamViewContext::set_effect_type(TrackReference::Type type)
{
type_ = type;
}
void NodeParamViewContext::retranslate()
{
}
void NodeParamViewContext::add_effect_button_clicked()
{
uint64_t flag = (type_ == TrackReference::k_video)
? oakengine_node_flag_video_effect()
: oakengine_node_flag_audio_effect();
if (flag == 0) {
return;
}
Menu *m =
create_node_menu(this, false, oak::k_category_unknown, flag);
connect(m, &Menu::triggered, this,
&NodeParamViewContext::add_effect_menu_item_triggered);
m->exec(QCursor::pos());
delete m;
}
void NodeParamViewContext::add_effect_menu_item_triggered(QAction *a)
{
// Owned handle: handed to the add-to-project undo command below
oak::Node n = create_node_from_menu_action(a);
if (!n.is_null()) {
oak::Input new_node_input = n.effect_input();
// WRAPPER-GAP: oakengine_undo_* / oakengine_node_*_command (undo
// command assembly has no oak:: wrapper)
void *command = oakengine_undo_command_create_multi();
QVector graphs_added_to;
foreach (oak::Node ctx, contexts_) {
oak::Input ctx_input = ctx.effect_input();
OakEngineProject *ctx_project = ctx.project().handle();
if (!graphs_added_to.contains(ctx_project)) {
oakengine_undo_command_multi_add_child(
command,
oakengine_node_add_to_project_command(
ctx_project, n.handle()));
graphs_added_to.append(ctx_project);
}
QPointF ctx_pos;
ctx.context_position_of(ctx, &ctx_pos);
oakengine_undo_command_multi_add_child(
command, oakengine_node_set_position_command(n.handle(), ctx.handle(), ctx_pos.x(), ctx_pos.y(), 0));
oakengine_undo_command_multi_add_child(
command, oakengine_node_set_position_command(
ctx.handle(), ctx.handle(),
ctx_pos.x() + 1,
ctx_pos.y(), 0));
if (ctx_input.is_connected()) {
oak::Node prev_output = ctx_input.connected_node();
oakengine_undo_command_multi_add_child(
command,
oakengine_node_disconnect_command(
ctx_input.node_handle(),
ctx_input.input_id().toUtf8().constData(),
ctx_input.element()));
oakengine_undo_command_multi_add_child(
command,
oakengine_node_connect_command(
prev_output.handle(),
new_node_input.node_handle(),
new_node_input.input_id().toUtf8().constData(),
new_node_input.element()));
}
oakengine_undo_command_multi_add_child(
command,
oakengine_node_connect_command(
n.handle(),
ctx_input.node_handle(),
ctx_input.input_id().toUtf8().constData(),
ctx_input.element()));
}
oakengine_undo_push(
command, tr("Added %1 to Node Chain").arg(n.name()).toUtf8().constData());
}
}
}