/*** Olive - Non-Linear Video Editor Copyright (C) 2021 Olive Team 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 "group.h" #include "node/graph.h" namespace olive { NodeGroup::NodeGroup() : output_passthrough_(nullptr) { } QString NodeGroup::Name() const { if (custom_name_.isEmpty()) { return tr("Group"); } else { return custom_name_; } } QString NodeGroup::id() const { return QStringLiteral("org.olivevideoeditor.Olive.group"); } QVector NodeGroup::Category() const { return {kCategoryGeneral}; } QString NodeGroup::Description() const { return tr("A group of nodes that is represented as a single node."); } void NodeGroup::Retranslate() { foreach (Node *n, nodes_) { n->Retranslate(); } } void NodeGroup::AddNode(Node *node) { nodes_.append(node); emit NodeAddedToGroup(node); } void NodeGroup::RemoveNode(Node *node) { if (nodes_.removeOne(node)) { emit NodeRemovedFromGroup(node); } } void NodeGroup::AddInputPassthrough(const NodeInput &input) { Q_ASSERT(nodes_.contains(input.node())); for (auto it=input_passthroughs_.cbegin(); it!=input_passthroughs_.cend(); it++) { if (it.value() == input) { // Already passing this input through return; } } // Add input QString id = GetGroupInputIDFromInput(input); AddInput(id, input.GetDataType(), input.GetDefaultValue(), input.GetFlags()); input_passthroughs_.insert(id, input); emit InputPassthroughAdded(this, input); } void NodeGroup::RemoveInputPassthrough(const NodeInput &input) { for (auto it=input_passthroughs_.cbegin(); it!=input_passthroughs_.cend(); it++) { if (it.value() == input) { RemoveInput(it.key()); input_passthroughs_.erase(it); emit InputPassthroughRemoved(this, it.value()); break; } } } void NodeGroup::SetOutputPassthrough(Node *node) { Q_ASSERT(!node || nodes_.contains(node)); output_passthrough_ = node; emit OutputPassthroughChanged(this, output_passthrough_); } QString NodeGroup::GetGroupInputIDFromInput(const NodeInput &input) { QCryptographicHash hash(QCryptographicHash::Sha1); hash.addData(input.node()->GetUUID().toByteArray()); hash.addData(input.input().toUtf8()); hash.addData((const char*) &input.element(), sizeof(input.element())); return QString::fromLatin1(hash.result().toHex()); } bool NodeGroup::ContainsInputPassthrough(const NodeInput &input) const { for (auto it=input_passthroughs_.cbegin(); it!=input_passthroughs_.cend(); it++) { if (it.value() == input) { return true; } } return false; } QString NodeGroup::GetInputName(const QString &id) const { return input_passthroughs_.value(id).name(); } void NodeAddToGroupCommand::redo() { group_->AddNode(node_); } void NodeAddToGroupCommand::undo() { group_->RemoveNode(node_); } void NodeGroupSetCustomNameCommand::redo() { old_name_ = group_->GetCustomName(); group_->SetCustomName(new_name_); } void NodeGroupSetCustomNameCommand::undo() { group_->SetCustomName(old_name_); } void NodeGroupAddInputPassthrough::redo() { if (!group_->ContainsInputPassthrough(input_)) { group_->AddInputPassthrough(input_); actually_added_ = true; } else { actually_added_ = false; } } void NodeGroupAddInputPassthrough::undo() { if (actually_added_) { group_->RemoveInputPassthrough(input_); } } void NodeRemoveFromGroupCommand::redo() { group_->RemoveNode(node_); } void NodeRemoveFromGroupCommand::undo() { group_->AddNode(node_); } void NodeGroupSetOutputPassthrough::redo() { old_output_ = group_->GetOutputPassthrough(); group_->SetOutputPassthrough(new_output_); } void NodeGroupSetOutputPassthrough::undo() { group_->SetOutputPassthrough(old_output_); } }