implemented node groups

This commit is contained in:
itsmattkc
2021-11-24 17:58:48 -08:00
parent a94c7169f2
commit 495b07fc55
29 changed files with 947 additions and 203 deletions
+1
View File
@@ -23,6 +23,7 @@ add_subdirectory(diskcache)
add_subdirectory(export)
add_subdirectory(footagerelink)
add_subdirectory(keyframeproperties)
add_subdirectory(nodegroup)
add_subdirectory(nodeproperties)
add_subdirectory(preferences)
add_subdirectory(progress)
+22
View File
@@ -0,0 +1,22 @@
# 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 <http://www.gnu.org/licenses/>.
set(OLIVE_SOURCES
${OLIVE_SOURCES}
dialog/nodegroup/nodegroupdialog.cpp
dialog/nodegroup/nodegroupdialog.h
PARENT_SCOPE
)
+99
View File
@@ -0,0 +1,99 @@
/***
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 <http://www.gnu.org/licenses/>.
***/
#include "nodegroupdialog.h"
#include <QDialogButtonBox>
#include <QGridLayout>
#include <QLabel>
#include <QSplitter>
#include "widget/nodeparamview/nodeparamview.h"
#include "widget/nodeview/nodeview.h"
namespace olive {
#define super QDialog
NodeGroupDialog::NodeGroupDialog(NodeGroup *group, QWidget *parent) :
super(parent),
group_(group),
parent_undo_(nullptr)
{
QGridLayout *layout = new QGridLayout(this);
int row = 0;
layout->addWidget(new QLabel(tr("Name:")), row, 0);
name_edit_ = new QLineEdit();
layout->addWidget(name_edit_, row, 1);
row++;
QSplitter *splitter = new QSplitter(Qt::Horizontal);
layout->addWidget(splitter, row, 0, 1, 2);
NodeParamView *param_view = new NodeParamView(false);
param_view->SetCreateCheckBoxes(kCheckBoxesOnNonConnected);
splitter->addWidget(param_view);
NodeView *node_view = new NodeView();
node_view->SetContexts({group});
QMetaObject::invokeMethod(node_view, &NodeView::CenterOnItemsBoundingRect, Qt::QueuedConnection);
splitter->addWidget(node_view);
for (auto it=group->GetInputPassthroughs().cbegin(); it!=group->GetInputPassthroughs().cend(); it++) {
param_view->SetInputChecked(it.value(), true);
}
connect(node_view, &NodeView::NodesSelected, param_view, &NodeParamView::SelectNodes);
connect(node_view, &NodeView::NodesDeselected, param_view, &NodeParamView::DeselectNodes);
node_view->SelectAll();
row++;
QDialogButtonBox *btns = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
btns->setCenterButtons(true);
connect(btns, &QDialogButtonBox::accepted, this, &NodeGroupDialog::accept);
connect(btns, &QDialogButtonBox::rejected, this, &NodeGroupDialog::reject);
layout->addWidget(btns, row, 0, 1, 2);
setWindowTitle(tr("Group Editor"));
}
void NodeGroupDialog::accept()
{
MultiUndoCommand *command = new MultiUndoCommand();
if (name_edit_->text() != group_->GetCustomName()) {
command->add_child(new NodeGroupSetCustomNameCommand(group_, name_edit_->text()));
}
if (parent_undo_) {
parent_undo_->add_child(command);
} else {
Core::instance()->undo_stack()->push(command);
}
super::accept();
}
}
@@ -18,26 +18,41 @@
***/
#ifndef NODEGROUP_H
#define NODEGROUP_H
#ifndef NODEGROUPDIALOG_H
#define NODEGROUPDIALOG_H
#include "node.h"
#include <QDialog>
#include <QLineEdit>
#include "node/group/group.h"
namespace olive {
class NodeGroup : public Node
class NodeGroupDialog : public QDialog
{
Q_OBJECT
public:
NodeGroup();
explicit NodeGroupDialog(NodeGroup *group, QWidget *parent = nullptr);
void SetNodes(Node *nodes);
void SetParentUndoCommand(MultiUndoCommand *c)
{
parent_undo_ = c;
}
public slots:
virtual void accept() override;
signals:
private:
QVector<Node*> nodes_;
NodeGroup *group_;
QLineEdit *name_edit_;
MultiUndoCommand *parent_undo_;
};
}
#endif // NODEGROUP_H
#endif // NODEGROUPDIALOG_H
@@ -46,7 +46,7 @@ NodePropertiesDialog::NodePropertiesDialog(Node *node, const rational &timebase,
label_edit_->setText(node->GetLabel());
label_layout->addWidget(label_edit_);
NodeParamViewItem *item = new NodeParamViewItem(node);
NodeParamViewItem *item = new NodeParamViewItem(node, kNoCheckBoxes);
item->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
item->SetTimebase(timebase);
item->setTitleBarWidget(new QWidget());
+1 -2
View File
@@ -20,6 +20,7 @@ add_subdirectory(color)
add_subdirectory(distort)
add_subdirectory(filter)
add_subdirectory(generator)
add_subdirectory(group)
add_subdirectory(input)
add_subdirectory(math)
add_subdirectory(output)
@@ -34,8 +35,6 @@ set(OLIVE_SOURCES
node/globals.h
node/graph.cpp
node/graph.h
node/group.cpp
node/group.h
node/hashtraverser.cpp
node/hashtraverser.h
node/inputdragger.cpp
-30
View File
@@ -1,30 +0,0 @@
/***
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 <http://www.gnu.org/licenses/>.
***/
#include "group.h"
namespace olive {
NodeGroup::NodeGroup()
{
}
}
+22
View File
@@ -0,0 +1,22 @@
# 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 <http://www.gnu.org/licenses/>.
set(OLIVE_SOURCES
${OLIVE_SOURCES}
node/group/group.cpp
node/group/group.h
PARENT_SCOPE
)
+177
View File
@@ -0,0 +1,177 @@
/***
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 <http://www.gnu.org/licenses/>.
***/
#include "group.h"
#include "node/graph.h"
namespace olive {
NodeGroup::NodeGroup() :
output_passthrough_(nullptr)
{
graph_ = new NodeGraph();
graph_->setParent(this);
}
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<Node::CategoryID> 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, graph_->nodes()) {
n->Retranslate();
}
}
void NodeGroup::AddNode(Node *node)
{
node->setParent(graph_);
}
void NodeGroup::RemoveNode(Node *node, QObject *new_parent)
{
if (node->parent() == graph_) {
node->setParent(new_parent);
}
}
void NodeGroup::AddInputPassthrough(const NodeInput &input)
{
Q_ASSERT(graph_->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);
}
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);
break;
}
}
}
void NodeGroup::SetOutputPassthrough(Node *node)
{
Q_ASSERT(graph_->nodes().contains(node));
output_passthrough_ = node;
}
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;
}
void NodeAddToGroupCommand::redo()
{
previous_parent_ = node_->parent();
group_->AddNode(node_);
}
void NodeAddToGroupCommand::undo()
{
group_->RemoveNode(node_, previous_parent_);
}
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_);
}
}
}
+176
View File
@@ -0,0 +1,176 @@
/***
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 <http://www.gnu.org/licenses/>.
***/
#ifndef NODEGROUP_H
#define NODEGROUP_H
#include "node/node.h"
namespace olive {
class NodeGroup : public Node
{
Q_OBJECT
public:
NodeGroup();
NODE_DEFAULT_DESTRUCTOR(NodeGroup)
NODE_COPY_FUNCTION(NodeGroup)
virtual QString Name() const override;
virtual QString id() const override;
virtual QVector<CategoryID> Category() const override;
virtual QString Description() const override;
virtual void Retranslate() override;
void AddNode(Node *node);
void RemoveNode(Node *node, QObject *new_parent = nullptr);
void AddInputPassthrough(const NodeInput &input);
void RemoveInputPassthrough(const NodeInput &input);
void SetOutputPassthrough(Node *node);
const QString &GetCustomName() const
{
return custom_name_;
}
void SetCustomName(const QString &name)
{
custom_name_ = name;
// NOTE: Not technically the right signal, but should achieve the right goal
emit LabelChanged(custom_name_);
}
void ClearCustomName()
{
custom_name_.clear();
}
static QString GetGroupInputIDFromInput(const NodeInput &input);
const QHash<QString, NodeInput> &GetInputPassthroughs() const
{
return input_passthroughs_;
}
bool ContainsInputPassthrough(const NodeInput &input) const;
private:
NodeGraph *graph_;
QHash<QString, NodeInput> input_passthroughs_;
Node *output_passthrough_;
QString custom_name_;
};
class NodeAddToGroupCommand : public UndoCommand
{
public:
NodeAddToGroupCommand(Node *node, NodeGroup *group) :
node_(node),
group_(group)
{}
virtual Project * GetRelevantProject() const override
{
return node_->project();
}
protected:
virtual void redo() override;
virtual void undo() override;
private:
Node *node_;
NodeGroup *group_;
QObject *previous_parent_;
};
class NodeGroupSetCustomNameCommand : public UndoCommand
{
public:
NodeGroupSetCustomNameCommand(NodeGroup *group, const QString &name) :
group_(group),
new_name_(name)
{}
virtual Project * GetRelevantProject() const override
{
return group_->project();
}
protected:
virtual void redo() override;
virtual void undo() override;
private:
NodeGroup *group_;
QString old_name_;
QString new_name_;
};
class NodeGroupAddInputPassthrough : public UndoCommand
{
public:
NodeGroupAddInputPassthrough(NodeGroup *group, const NodeInput &input) :
group_(group),
input_(input),
actually_added_(false)
{}
virtual Project * GetRelevantProject() const override
{
return group_->project();
}
protected:
virtual void redo() override;
virtual void undo() override;
private:
NodeGroup *group_;
NodeInput input_;
bool actually_added_;
};
}
#endif // NODEGROUP_H
+16 -3
View File
@@ -49,6 +49,7 @@ Node::Node() :
operation_stack_(0),
cache_result_(false)
{
uuid_ = QUuid::createUuid();
}
Node::~Node()
@@ -88,6 +89,8 @@ void Node::Load(QXmlStreamReader *reader, XMLNodeData& xml_node_data, uint versi
xml_node_data.node_ptrs.insert(reader->readElementText().toULongLong(), this);
} else if (reader->name() == QStringLiteral("label")) {
SetLabel(reader->readElementText());
} else if (reader->name() == QStringLiteral("uuid")) {
SetUUID(QUuid::fromString(reader->readElementText()));
} else if (reader->name() == QStringLiteral("color")) {
override_color_ = reader->readElementText().toInt();
} else if (reader->name() == QStringLiteral("links")) {
@@ -169,6 +172,7 @@ void Node::Save(QXmlStreamWriter *writer) const
{
writer->writeTextElement(QStringLiteral("ptr"), QString::number(reinterpret_cast<quintptr>(this)));
writer->writeTextElement(QStringLiteral("uuid"), uuid_.toString());
writer->writeTextElement(QStringLiteral("label"), GetLabel());
writer->writeTextElement(QStringLiteral("color"), QString::number(override_color_));
@@ -219,7 +223,16 @@ void Node::Save(QXmlStreamWriter *writer) const
Project* Node::project() const
{
return dynamic_cast<Project*>(parent());
QObject *t = this->parent();
while (t) {
if (Project *p = dynamic_cast<Project*>(t)) {
return p;
}
t = t->parent();
}
return nullptr;
}
QString Node::ShortName() const
@@ -1089,7 +1102,7 @@ NodeInputImmediate *Node::GetImmediate(const QString &input, int element) const
return nullptr;
}
Node::InputFlags Node::GetInputFlags(const QString &input) const
InputFlags Node::GetInputFlags(const QString &input) const
{
const Input* i = GetInternalInputData(input);
@@ -1343,7 +1356,7 @@ void Node::HashAddNodeSignature(QCryptographicHash &hash) const
hash.addData(id().toUtf8());
}
void Node::InsertInput(const QString &id, NodeValue::Type type, const QVariant &default_value, Node::InputFlags flags, int index)
void Node::InsertInput(const QString &id, NodeValue::Type type, const QVariant &default_value, InputFlags flags, int index)
{
if (id.isEmpty()) {
qWarning() << "Rejected adding input with an empty ID on node" << this->id();
+8 -33
View File
@@ -27,6 +27,7 @@
#include <QObject>
#include <QPainter>
#include <QPointF>
#include <QUuid>
#include <QXmlStreamWriter>
#include "codec/frame.h"
@@ -112,6 +113,9 @@ public:
Project* project() const;
const QUuid &GetUUID() const {return uuid_;}
void SetUUID(const QUuid &uuid) {uuid_ = uuid;}
/**
* @brief Clear current node variables and replace them with
*/
@@ -935,38 +939,9 @@ public:
};
InputFlags GetInputFlags(const QString& input) const;
protected:
enum InputFlag {
/// By default, inputs are keyframable, connectable, and NOT arrays
kInputFlagNormal = 0x0,
kInputFlagArray = 0x1,
kInputFlagNotKeyframable = 0x2,
kInputFlagNotConnectable = 0x4,
kInputFlagHidden = 0x8
};
class InputFlags {
public:
explicit InputFlags()
{
f_ = kInputFlagNormal;
}
explicit InputFlags(uint64_t flags)
{
f_ = flags;
}
bool operator&(const InputFlag& f) const
{
return f_ & f;
}
private:
uint64_t f_;
};
virtual void Hash(QCryptographicHash& hash, const NodeGlobals &globals, const VideoParams& video_params) const;
void HashAddNodeSignature(QCryptographicHash &hash) const;
@@ -1216,8 +1191,6 @@ private:
return input_ids_.indexOf(input);
}
InputFlags GetInputFlags(const QString& input) const;
Input* GetInternalInputData(const QString& input)
{
int i = GetInternalInputIndex(input);
@@ -1336,6 +1309,8 @@ private:
PositionMap context_positions_;
QUuid uuid_;
private slots:
/**
* @brief Slot when a keyframe's time changes to keep the keyframes correctly sorted by time
-2
View File
@@ -254,8 +254,6 @@ private:
AudioPlaybackCache audio_playback_cache_;
int operation_stack_;
VideoParams cached_video_params_;
AudioParams cached_audio_params_;
+18
View File
@@ -69,6 +69,15 @@ bool NodeInput::IsArray() const
}
}
InputFlags NodeInput::GetFlags() const
{
if (IsValid()) {
return node_->GetInputFlags(input_);
} else {
return InputFlags(kInputFlagNormal);
}
}
Node *NodeInput::GetConnectedOutput() const
{
if (IsValid()) {
@@ -87,6 +96,15 @@ NodeValue::Type NodeInput::GetDataType() const
}
}
QVariant NodeInput::GetDefaultValue() const
{
if (IsValid()) {
return node_->GetDefaultValue(input_);
} else {
return QVariant();
}
}
QStringList NodeInput::GetComboBoxStrings() const
{
if (IsValid()) {
+36 -1
View File
@@ -31,6 +31,37 @@ namespace olive {
class Node;
class NodeKeyframe;
enum InputFlag {
/// By default, inputs are keyframable, connectable, and NOT arrays
kInputFlagNormal = 0x0,
kInputFlagArray = 0x1,
kInputFlagNotKeyframable = 0x2,
kInputFlagNotConnectable = 0x4,
kInputFlagHidden = 0x8
};
class InputFlags {
public:
explicit InputFlags()
{
f_ = kInputFlagNormal;
}
explicit InputFlags(uint64_t flags)
{
f_ = flags;
}
bool operator&(const InputFlag& f) const
{
return f_ & f;
}
private:
uint64_t f_;
};
struct NodeInputPair {
bool operator==(const NodeInputPair& rhs) const
{
@@ -98,7 +129,7 @@ public:
return input_;
}
int element() const
const int &element() const
{
return element_;
}
@@ -123,10 +154,14 @@ public:
bool IsArray() const;
InputFlags GetFlags() const;
Node *GetConnectedOutput() const;
NodeValue::Type GetDataType() const;
QVariant GetDefaultValue() const;
QStringList GetComboBoxStrings() const;
QVariant GetProperty(const QString& key) const;
+3
View File
@@ -373,6 +373,9 @@ void PreviewAutoCacher::AddNode(Node *node)
// Add to project
copy->setParent(&copied_project_);
// Copy UUID
copy->SetUUID(node->GetUUID());
// Insert into map
InsertIntoCopyMap(node, copy);
+3 -1
View File
@@ -24,8 +24,9 @@
#include <QtConcurrent/QtConcurrent>
#include "config/config.h"
#include "node/graph.h"
#include "node/color/colormanager/colormanager.h"
#include "node/graph.h"
#include "node/group/group.h"
#include "node/node.h"
#include "node/output/viewer/viewer.h"
#include "node/project/project.h"
@@ -172,6 +173,7 @@ private:
QVector<QueuedJob> graph_update_queue_;
QHash<Node*, Node*> copy_map_;
QHash<NodeGraph*, NodeGraph*> graph_map_;
ViewerOutput* copied_viewer_node_;
ColorManager* copied_color_manager_;
QVector<Node*> created_nodes_;
+68 -18
View File
@@ -32,10 +32,12 @@ namespace olive {
#define super TimeBasedWidget
NodeParamView::NodeParamView(QWidget *parent) :
NodeParamView::NodeParamView(bool create_keyframe_view, QWidget *parent) :
super(true, false, parent),
last_scroll_val_(0),
focused_node_(nullptr)
focused_node_(nullptr),
create_checkboxes_(kNoCheckBoxes),
time_target_(nullptr)
{
// Create horizontal layout to place scroll area in (and keyframe editing eventually)
QHBoxLayout* layout = new QHBoxLayout(this);
@@ -46,16 +48,16 @@ NodeParamView::NodeParamView(QWidget *parent) :
layout->addWidget(splitter);
// Set up scroll area for params
QScrollArea* scroll_area = new QScrollArea();
scroll_area->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
scroll_area->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
scroll_area->setWidgetResizable(true);
splitter->addWidget(scroll_area);
param_scroll_area_ = new QScrollArea();
param_scroll_area_->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
param_scroll_area_->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
param_scroll_area_->setWidgetResizable(true);
splitter->addWidget(param_scroll_area_);
// Param widget
param_widget_container_ = new NodeParamViewParamContainer();
connect(param_widget_container_, &NodeParamViewParamContainer::Resized, this, &NodeParamView::UpdateGlobalScrollBar);
scroll_area->setWidget(param_widget_container_);
param_scroll_area_->setWidget(param_widget_container_);
param_widget_area_ = new NodeParamViewDockArea();
@@ -74,6 +76,10 @@ NodeParamView::NodeParamView(QWidget *parent) :
param_widget_container_layout->addStretch(INT_MAX);
// Disable collapsing param view (but collapsing keyframe view is permitted)
splitter->setCollapsible(0, false);
if (create_keyframe_view) {
// Set up keyframe view
QWidget* keyframe_area = new QWidget();
QVBoxLayout* keyframe_area_layout = new QVBoxLayout(keyframe_area);
@@ -102,9 +108,9 @@ NodeParamView::NodeParamView(QWidget *parent) :
// Set both widgets to 50/50
splitter->setSizes({INT_MAX, INT_MAX});
// Disable collapsing param view (but collapsing keyframe view is permitted)
splitter->setCollapsible(0, false);
} else {
keyframe_view_ = nullptr;
}
// Create global vertical scrollbar on the right
vertical_scrollbar_ = new QScrollBar();
@@ -112,11 +118,13 @@ NodeParamView::NodeParamView(QWidget *parent) :
layout->addWidget(vertical_scrollbar_);
// Connect scrollbars together
connect(param_scroll_area_->verticalScrollBar(), &QScrollBar::valueChanged, vertical_scrollbar_, &QScrollBar::setValue);
connect(vertical_scrollbar_, &QScrollBar::valueChanged, param_scroll_area_->verticalScrollBar(), &QScrollBar::setValue);
if (keyframe_view_) {
connect(keyframe_view_->verticalScrollBar(), &QScrollBar::valueChanged, vertical_scrollbar_, &QScrollBar::setValue);
connect(keyframe_view_->verticalScrollBar(), &QScrollBar::valueChanged, scroll_area->verticalScrollBar(), &QScrollBar::setValue);
connect(scroll_area->verticalScrollBar(), &QScrollBar::valueChanged, vertical_scrollbar_, &QScrollBar::setValue);
connect(scroll_area->verticalScrollBar(), &QScrollBar::valueChanged, keyframe_view_->verticalScrollBar(), &QScrollBar::setValue);
connect(vertical_scrollbar_, &QScrollBar::valueChanged, scroll_area->verticalScrollBar(), &QScrollBar::setValue);
connect(keyframe_view_->verticalScrollBar(), &QScrollBar::valueChanged, param_scroll_area_->verticalScrollBar(), &QScrollBar::setValue);
connect(param_scroll_area_->verticalScrollBar(), &QScrollBar::valueChanged, keyframe_view_->verticalScrollBar(), &QScrollBar::setValue);
connect(vertical_scrollbar_, &QScrollBar::valueChanged, keyframe_view_->verticalScrollBar(), &QScrollBar::setValue);
// TimeBasedWidget's scrollbar has extra functionality that we can take advantage of
@@ -124,6 +132,7 @@ NodeParamView::NodeParamView(QWidget *parent) :
keyframe_view_->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
connect(keyframe_view_->horizontalScrollBar(), &QScrollBar::valueChanged, ruler(), &TimeRuler::SetScroll);
}
// Set a default scale - FIXME: Hardcoded
SetScale(120);
@@ -192,6 +201,14 @@ void NodeParamView::DeselectNodes(const QVector<Node *> &nodes)
}
}
void NodeParamView::SetInputChecked(const NodeInput &input, bool e)
{
input_checked_.insert(input, e);
if (NodeParamViewItem *item = items_.value(input.node())) {
item->SetInputChecked(input, e);
}
}
void NodeParamView::resizeEvent(QResizeEvent *event)
{
super::resizeEvent(event);
@@ -205,14 +222,18 @@ void NodeParamView::ScaleChangedEvent(const double &scale)
{
super::ScaleChangedEvent(scale);
if (keyframe_view_) {
keyframe_view_->SetScale(scale);
}
}
void NodeParamView::TimebaseChangedEvent(const rational &timebase)
{
super::TimebaseChangedEvent(timebase);
if (keyframe_view_) {
keyframe_view_->SetTimebase(timebase);
}
foreach (NodeParamViewItem* item, items_) {
item->SetTimebase(timebase);
@@ -225,29 +246,37 @@ void NodeParamView::TimeChangedEvent(const rational &time)
{
super::TimeChangedEvent(time);
if (keyframe_view_) {
keyframe_view_->SetTime(time);
}
UpdateItemTime(time);
}
void NodeParamView::ConnectedNodeChangeEvent(ViewerOutput *n)
{
if (keyframe_view_) {
// Set viewer as a time target
keyframe_view_->SetTimeTarget(n);
}
foreach (NodeParamViewItem* item, items_) {
item->SetTimeTarget(n);
}
time_target_ = n;
}
Node *NodeParamView::GetTimeTarget() const
{
return keyframe_view_->GetTimeTarget();
return time_target_;
}
void NodeParamView::DeleteSelected()
{
if (keyframe_view_) {
keyframe_view_->DeleteSelected();
}
}
void NodeParamView::UpdateItemTime(const rational &time)
@@ -293,14 +322,16 @@ void NodeParamView::SignalNodeOrder()
void NodeParamView::AddNode(Node *n)
{
NodeParamViewItem* item = new NodeParamViewItem(n, param_widget_area_);
NodeParamViewItem* item = new NodeParamViewItem(n, create_checkboxes_, param_widget_area_);
item->setAllowedAreas(Qt::LeftDockWidgetArea);
item->setFeatures(QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetMovable);
item->SetExpanded(node_expanded_state_.value(n, true));
if (keyframe_view_) {
connect(n, &Node::KeyframeAdded, keyframe_view_, &KeyframeView::AddKeyframe);
connect(n, &Node::KeyframeRemoved, keyframe_view_, &KeyframeView::RemoveKeyframe);
}
connect(item, &NodeParamViewItem::RequestSetTime, this, &NodeParamView::SetTimeAndSignal);
connect(item, &NodeParamViewItem::RequestSelectNode, this, &NodeParamView::RequestSelectNode);
@@ -310,6 +341,15 @@ void NodeParamView::AddNode(Node *n)
connect(item, &NodeParamViewItem::ArrayExpandedChanged, this, &NodeParamView::QueueKeyframePositionUpdate);
connect(item, &NodeParamViewItem::ExpandedChanged, this, &NodeParamView::QueueKeyframePositionUpdate);
connect(item, &NodeParamViewItem::Moved, this, &NodeParamView::QueueKeyframePositionUpdate);
connect(item, &NodeParamViewItem::InputCheckedChanged, this, &NodeParamView::SetInputChecked);
if (create_checkboxes_) {
for (auto it=input_checked_.cbegin(); it!=input_checked_.cend(); it++) {
if (it.key().node() == n) {
item->SetInputChecked(it.key(), it.value());
}
}
}
// Set time target
item->SetTimeTarget(GetTimeTarget());
@@ -327,15 +367,19 @@ void NodeParamView::AddNode(Node *n)
emit FocusedNodeChanged(focused_node_);
}
if (keyframe_view_) {
keyframe_view_->AddKeyframesOfNode(n);
}
}
void NodeParamView::RemoveNode(Node *n)
{
if (keyframe_view_) {
keyframe_view_->RemoveKeyframesOfNode(n);
disconnect(n, &Node::KeyframeAdded, keyframe_view_, &KeyframeView::AddKeyframe);
disconnect(n, &Node::KeyframeRemoved, keyframe_view_, &KeyframeView::RemoveKeyframe);
}
delete items_.take(n);
@@ -358,8 +402,10 @@ void NodeParamView::UpdateGlobalScrollBar()
{
int height_offscreen = param_widget_container_->height() - ruler()->height() + scrollbar()->height();
if (keyframe_view_) {
keyframe_view_->SetMaxScroll(height_offscreen);
vertical_scrollbar_->setRange(0, height_offscreen - keyframe_view_->height());
}
vertical_scrollbar_->setRange(0, height_offscreen - param_scroll_area_->height());
}
void NodeParamView::PinNode(bool pin)
@@ -390,6 +436,7 @@ void NodeParamView::FocusChanged(QWidget* old, QWidget* now)
item = dynamic_cast<NodeParamViewItem*>(parent);
if (item) {
if (item->parent() == param_widget_area_) {
// Found it!
if (item->GetNode() != focused_node_) {
if (focused_node_) {
@@ -403,6 +450,7 @@ void NodeParamView::FocusChanged(QWidget* old, QWidget* now)
emit FocusedNodeChanged(focused_node_);
}
}
break;
}
@@ -421,6 +469,7 @@ void NodeParamView::KeyframeViewDragged(int x, int y)
void NodeParamView::UpdateElementY()
{
if (keyframe_view_) {
for (auto it=items_.cbegin(); it!=items_.cend(); it++) {
foreach (const QString& input, it.key()->inputs()) {
int arr_sz = it.key()->InputArraySize(input);
@@ -433,6 +482,7 @@ void NodeParamView::UpdateElementY()
}
}
}
}
}
}
+26 -3
View File
@@ -58,11 +58,25 @@ class NodeParamView : public TimeBasedWidget
{
Q_OBJECT
public:
NodeParamView(QWidget* parent = nullptr);
NodeParamView(bool create_keyframe_view, QWidget* parent = nullptr);
NodeParamView(QWidget* parent = nullptr) :
NodeParamView(true, parent)
{
}
void SelectNodes(const QVector<Node *> &nodes);
void DeselectNodes(const QVector<Node*>& nodes);
void SetCreateCheckBoxes(NodeParamViewCheckBoxBehavior e)
{
create_checkboxes_ = e;
}
bool IsInputChecked(const NodeInput &input) const
{
return input_checked_.value(input);
}
const QMap<Node*, NodeParamViewItem*>& GetItemMap() const
{
return items_;
@@ -82,6 +96,9 @@ public:
keyframe_view_->DeselectAll();
}
public slots:
void SetInputChecked(const NodeInput &input, bool e);
signals:
void RequestSelectNode(const QVector<Node*>& target);
@@ -117,10 +134,10 @@ private:
int last_scroll_val_;
QScrollArea* param_scroll_area_;
NodeParamViewParamContainer* param_widget_container_;
// This may look weird, but QMainWindow is just a QWidget with a fancy layout that allows
// docking windows
NodeParamViewDockArea* param_widget_area_;
QVector<Node*> pinned_nodes_;
@@ -131,6 +148,12 @@ private:
Node* focused_node_;
NodeParamViewCheckBoxBehavior create_checkboxes_;
Node *time_target_;
QHash<NodeInput, bool> input_checked_;
private slots:
void UpdateGlobalScrollBar();
@@ -25,6 +25,8 @@
namespace olive {
// This may look weird, but QMainWindow is just a QWidget with a fancy layout that allows
// for docking QDockWidgets
class NodeParamViewDockArea : public QMainWindow
{
Q_OBJECT
+58 -10
View File
@@ -38,12 +38,14 @@ const int NodeParamViewItemBody::kArrayInsertColumn = kKeyControlColumn-1;
const int NodeParamViewItemBody::kArrayRemoveColumn = kArrayInsertColumn-1;
const int NodeParamViewItemBody::kExtraButtonColumn = kKeyControlColumn-1;
// 0 is for the array collapse button, 1 is for the main label, widgets start at 2
const int NodeParamViewItemBody::kWidgetStartColumn = 2;
const int NodeParamViewItemBody::kOptionalCheckBox = 0;
const int NodeParamViewItemBody::kArrayCollapseBtnColumn = 1;
const int NodeParamViewItemBody::kLabelColumn = 2;
const int NodeParamViewItemBody::kWidgetStartColumn = 3;
#define super QDockWidget
NodeParamViewItem::NodeParamViewItem(Node *node, QWidget *parent) :
NodeParamViewItem::NodeParamViewItem(Node *node, NodeParamViewCheckBoxBehavior create_checkboxes, QWidget *parent) :
super(parent),
node_(node),
highlighted_(false)
@@ -55,10 +57,11 @@ NodeParamViewItem::NodeParamViewItem(Node *node, QWidget *parent) :
this->setTitleBarWidget(title_bar_);
// Create and add contents widget
body_ = new NodeParamViewItemBody(node_);
body_ = new NodeParamViewItemBody(node_, create_checkboxes);
connect(body_, &NodeParamViewItemBody::RequestSelectNode, this, &NodeParamViewItem::RequestSelectNode);
connect(body_, &NodeParamViewItemBody::RequestSetTime, this, &NodeParamViewItem::RequestSetTime);
connect(body_, &NodeParamViewItemBody::ArrayExpandedChanged, this, &NodeParamViewItem::ArrayExpandedChanged);
connect(body_, &NodeParamViewItemBody::InputCheckedChanged, this, &NodeParamViewItem::InputCheckedChanged);
connect(title_bar_, &NodeParamViewItemTitleBar::ExpandedStateChanged, this, &NodeParamViewItem::SetExpanded);
connect(title_bar_, &NodeParamViewItemTitleBar::PinToggled, this, &NodeParamViewItem::PinToggled);
@@ -165,6 +168,11 @@ int NodeParamViewItem::GetElementY(const NodeInput &c) const
}
}
void NodeParamViewItem::SetInputChecked(const NodeInput &input, bool e)
{
body_->SetInputChecked(input, e);
}
void NodeParamViewItem::ToggleExpanded()
{
SetExpanded(!IsExpanded());
@@ -222,9 +230,10 @@ void NodeParamViewItemTitleBar::mouseDoubleClickEvent(QMouseEvent *event)
collapse_btn_->click();
}
NodeParamViewItemBody::NodeParamViewItemBody(Node* node, QWidget *parent) :
NodeParamViewItemBody::NodeParamViewItemBody(Node* node, NodeParamViewCheckBoxBehavior create_checkboxes, QWidget *parent) :
QWidget(parent),
node_(node)
node_(node),
create_checkboxes_(create_checkboxes)
{
QGridLayout* root_layout = new QGridLayout(this);
@@ -277,11 +286,22 @@ void NodeParamViewItemBody::CreateWidgets(QGridLayout* layout, Node *node, const
ui_objects.layout = layout;
ui_objects.row = row;
// Create optional checkbox if requested
if (create_checkboxes_) {
ui_objects.optional_checkbox = new QCheckBox();
connect(ui_objects.optional_checkbox, &QCheckBox::clicked, this, &NodeParamViewItemBody::OptionalCheckBoxClicked);
layout->addWidget(ui_objects.optional_checkbox, row, kOptionalCheckBox);
if (create_checkboxes_ == kCheckBoxesOnNonConnected && input_ref.IsConnected()) {
ui_objects.optional_checkbox->setVisible(false);
}
}
// Add descriptor label
ui_objects.main_label = new QLabel();
// Label always goes into column 1 (array collapse button goes into 0 if applicable)
layout->addWidget(ui_objects.main_label, row, 1);
// Create input label
layout->addWidget(ui_objects.main_label, row, kLabelColumn);
if (node->InputIsArray(input)) {
if (element == -1) {
@@ -292,8 +312,8 @@ void NodeParamViewItemBody::CreateWidgets(QGridLayout* layout, Node *node, const
// Default to collapsed
array_collapse_btn->setChecked(false);
// Collapse button always goes into column 0
layout->addWidget(array_collapse_btn, row, 0);
// Add collapse button to layout
layout->addWidget(array_collapse_btn, row, kArrayCollapseBtnColumn);
// Connect signal to show/hide array params when toggled
connect(array_collapse_btn, &CollapseButton::toggled, this, &NodeParamViewItemBody::ArrayCollapseBtnPressed);
@@ -448,6 +468,11 @@ void NodeParamViewItemBody::UpdateUIForEdgeConnection(const NodeInput& input)
if (ui_objects.key_control) {
ui_objects.key_control->setVisible(!input.IsConnected());
}
// Show/hide optional checkbox if requested
if (create_checkboxes_ == kCheckBoxesOnNonConnected) {
ui_objects.optional_checkbox->setVisible(!input.IsConnected());
}
}
}
@@ -575,6 +600,16 @@ void NodeParamViewItemBody::SetTimebase(const rational& timebase)
}
}
void NodeParamViewItemBody::SetInputChecked(const NodeInput &input, bool e)
{
if (input_ui_map_.contains(input)) {
QCheckBox *cb = input_ui_map_.value(input).optional_checkbox;
if (cb) {
cb->setChecked(e);
}
}
}
void NodeParamViewItemBody::ReplaceWidgets(const NodeInput &input)
{
InputUI ui = input_ui_map_.value(input);
@@ -588,12 +623,25 @@ void NodeParamViewItemBody::ShowSpeedDurationDialogForNode()
sdd.exec();
}
void NodeParamViewItemBody::OptionalCheckBoxClicked(bool e)
{
QCheckBox *cb = static_cast<QCheckBox*>(sender());
for (auto it=input_ui_map_.cbegin(); it!=input_ui_map_.cend(); it++) {
if (it.value().optional_checkbox == cb) {
emit InputCheckedChanged(it.key(), e);
break;
}
}
}
NodeParamViewItemBody::InputUI::InputUI() :
main_label(nullptr),
widget_bridge(nullptr),
connected_label(nullptr),
key_control(nullptr),
extra_btn(nullptr),
optional_checkbox(nullptr),
array_insert_btn(nullptr),
array_remove_btn(nullptr)
{
+25 -2
View File
@@ -21,6 +21,7 @@
#ifndef NODEPARAMVIEWITEM_H
#define NODEPARAMVIEWITEM_H
#include <QCheckBox>
#include <QDockWidget>
#include <QGridLayout>
#include <QLabel>
@@ -38,6 +39,12 @@
namespace olive {
enum NodeParamViewCheckBoxBehavior {
kNoCheckBoxes,
kCheckBoxesOn,
kCheckBoxesOnNonConnected
};
class NodeParamViewItemTitleBar : public QWidget
{
Q_OBJECT
@@ -75,7 +82,7 @@ private:
class NodeParamViewItemBody : public QWidget {
Q_OBJECT
public:
NodeParamViewItemBody(Node* node, QWidget* parent = nullptr);
NodeParamViewItemBody(Node* node, NodeParamViewCheckBoxBehavior create_checkboxes, QWidget* parent = nullptr);
void SetTimeTarget(Node* target);
@@ -88,6 +95,8 @@ public:
// Set the timebase of any timebased widgets contained here
void SetTimebase(const rational& timebase);
void SetInputChecked(const NodeInput &input, bool e);
signals:
void RequestSetTime(const rational& time);
@@ -95,6 +104,8 @@ signals:
void ArrayExpandedChanged(bool e);
void InputCheckedChanged(const NodeInput &input, bool e);
private:
void CreateWidgets(QGridLayout *layout, Node* node, const QString& input, int element, int row_index);
@@ -114,6 +125,7 @@ private:
QGridLayout* layout;
int row;
QPushButton *extra_btn;
QCheckBox *optional_checkbox;
NodeParamViewArrayButton* array_insert_btn;
NodeParamViewArrayButton* array_remove_btn;
@@ -135,6 +147,8 @@ private:
rational timebase_;
NodeParamViewCheckBoxBehavior create_checkboxes_;
/**
* @brief The column to place the keyframe controls in
*
@@ -147,6 +161,9 @@ private:
static const int kArrayRemoveColumn;
static const int kExtraButtonColumn;
static const int kOptionalCheckBox;
static const int kArrayCollapseBtnColumn;
static const int kLabelColumn;
static const int kWidgetStartColumn;
private slots:
@@ -168,13 +185,15 @@ private slots:
void ShowSpeedDurationDialogForNode();
void OptionalCheckBoxClicked(bool e);
};
class NodeParamViewItem : public QDockWidget
{
Q_OBJECT
public:
NodeParamViewItem(Node* node, QWidget* parent = nullptr);
NodeParamViewItem(Node* node, NodeParamViewCheckBoxBehavior create_checkboxes, QWidget* parent = nullptr);
void SetTimeTarget(Node* target);
@@ -196,6 +215,8 @@ public:
int GetElementY(const NodeInput& c) const;
void SetInputChecked(const NodeInput &input, bool e);
public slots:
void SetExpanded(bool e);
@@ -214,6 +235,8 @@ signals:
void Moved();
void InputCheckedChanged(const NodeInput &input, bool e);
protected:
virtual void changeEvent(QEvent *e) override;
+87 -9
View File
@@ -21,16 +21,18 @@
#include "nodeview.h"
#include <QInputDialog>
#include <QMessageBox>
#include <QMouseEvent>
#include <QScrollBar>
#include <QToolTip>
#include "core.h"
#include "dialog/nodegroup/nodegroupdialog.h"
#include "nodeviewundo.h"
#include "node/audio/volume/volume.h"
#include "node/distort/transform/transformdistortnode.h"
#include "node/factory.h"
#include "node/group.h"
#include "node/group/group.h"
#include "node/traverser.h"
#include "widget/menu/menushared.h"
#include "widget/timebased/timebasedview.h"
@@ -638,6 +640,7 @@ void NodeView::UpdateSelectionCache()
if (current_selection.isEmpty()) {
// All nodes that were selected have been deselected, so we'll just set them all to `deselected`
deselected = selected_nodes_;
selected_nodes_.clear();
} else {
foreach (Node* n, selected_nodes_) {
bool still_selected = false;
@@ -649,20 +652,20 @@ void NodeView::UpdateSelectionCache()
}
}
if (still_selected) {
if (!still_selected) {
deselected.append(n);
selected_nodes_.removeOne(n);
}
}
}
if (!selected.isEmpty()) {
emit NodesSelected(selected);
}
if (!deselected.isEmpty()) {
emit NodesDeselected(deselected);
}
if (!selected.isEmpty()) {
emit NodesSelected(selected);
}
}
void NodeView::ShowContextMenu(const QPoint &pos)
@@ -1082,13 +1085,88 @@ void NodeView::PositionNewEdge(const QPoint &pos)
void NodeView::GroupNodes()
{
/*NodeGroup *group = new NodeGroup();
selected_nodes_*/
// Get items
QVector<NodeViewItem*> items = scene_.GetSelectedItems();
if (items.isEmpty()) {
return;
}
// Get node context
Node *context = items.first()->GetContext();
QPointF avg_pos = items.first()->GetNodePosition();
for (int i=1; i<items.size(); i++) {
if (items.at(i)->GetContext() != context) {
QMessageBox::critical(this, tr("Failed to group nodes"), tr("Nodes can only be grouped if they're in the same context."));
return;
}
avg_pos += items.at(i)->GetNodePosition();
}
avg_pos /= items.size();
// Create group
NodeGroup *group = new NodeGroup();
// Add group to graph and context
MultiUndoCommand *command = new MultiUndoCommand();
command->add_child(new NodeAddCommand(context->parent(), group));
command->add_child(new NodeSetPositionCommand(group, context, avg_pos));
// Add nodes to group
QVector<Node*> nodes_to_group = selected_nodes_;
DeselectAll();
foreach (Node *n, nodes_to_group) {
for (auto it=n->input_connections().cbegin(); it!=n->input_connections().cend(); it++) {
Node *output = it->second;
const NodeInput &input = it->first;
if (!nodes_to_group.contains(output)) {
command->add_child(new NodeEdgeRemoveCommand(output, input));
command->add_child(new NodeEdgeAddCommand(output, NodeInput(group, input.input(), input.element())));
}
}
for (auto it=n->output_connections().cbegin(); it!=n->output_connections().cend(); it++) {
Node *output = it->first;
const NodeInput &input = it->second;
if (!nodes_to_group.contains(input.node())) {
command->add_child(new NodeEdgeRemoveCommand(output, input));
command->add_child(new NodeEdgeAddCommand(group, input));
}
}
command->add_child(new NodeRemovePositionFromContextCommand(n, context));
command->add_child(new NodeAddToGroupCommand(n, group));
command->add_child(new NodeSetPositionCommand(n, group, scene_.context_map().value(context)->GetItemFromMap(n)->GetNodePosition()));
for (auto it=n->inputs().cbegin(); it!=n->inputs().cend(); it++) {
NodeInput input(n, *it, -1);
if (!input.IsConnected() || !nodes_to_group.contains(input.GetConnectedOutput())) {
command->add_child(new NodeGroupAddInputPassthrough(group, input));
}
}
}
// Do command
command->redo_now();
NodeGroupDialog ngd(group, this);
if (ngd.exec() == QDialog::Accepted) {
// Push to stack so it can be undone (MultiUndoCommand will ignore the request to redo again)
Core::instance()->undo_stack()->push(command);
} else {
// Undo command and delete
command->undo_now();
delete command;
}
}
void NodeView::UngroupNodes()
{
//static_cast<NodeGroup*>(selected_nodes_.first());
//NodeGroup *group = static_cast<NodeGroup*>(selected_nodes_.first());
}
void NodeView::PasteNodesInternal(const QVector<Node *> &duplicate_nodes)
+1 -1
View File
@@ -45,7 +45,7 @@ class NodeView : public HandMovableView, public NodeCopyPasteService
{
Q_OBJECT
public:
NodeView(QWidget* parent);
NodeView(QWidget* parent = nullptr);
virtual ~NodeView() override;
+3 -1
View File
@@ -189,7 +189,9 @@ void NodeViewContext::DeleteSelected(NodeViewDeleteCommand *command)
void NodeViewContext::Select(const QVector<Node *> &nodes)
{
foreach (Node *n, nodes) {
item_map_.value(n)->setSelected(true);
if (NodeViewItem *item = item_map_.value(n)) {
item->setSelected(true);
}
}
}
+5
View File
@@ -36,6 +36,11 @@ public:
QPointF MapScenePosToNodePosInContext(const QPointF &pos) const;
NodeViewItem *GetItemFromMap(Node *node) const
{
return item_map_.value(node);
}
virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr) override;
public slots:
+1 -1
View File
@@ -544,7 +544,7 @@ QPointF NodeViewItem::GetInputPoint(const QString &input, int element) const
int index = node_inputs_.indexOf(input);
if (index < 0 || index >= int(input_connectors_.size())) {
return QPointF();
return pos();
}
return input_connectors_[index]->scenePos();
-10
View File
@@ -467,15 +467,6 @@ void MainWindow::TimelinePanelSelectionChanged(const QVector<Block *> &blocks)
}
}
void MainWindow::ProjectPanelSelectionChanged(const QVector<Node *> &nodes)
{
ProjectPanel *panel = static_cast<ProjectPanel *>(sender());
if (PanelManager::instance()->CurrentlyFocused(false) == panel) {
node_panel_->Select(nodes, true);
}
}
void MainWindow::ShowWelcomeDialog()
{
if (Config::Current()[QStringLiteral("ShowWelcomeDialog")].toBool()) {
@@ -572,7 +563,6 @@ ProjectPanel *MainWindow::AppendProjectPanel()
connect(panel, &PanelWidget::CloseRequested, this, &MainWindow::ProjectCloseRequested);
connect(panel, &ProjectPanel::ProjectNameChanged, this, &MainWindow::UpdateTitle);
connect(panel, &ProjectPanel::SelectionChanged, this, &MainWindow::ProjectPanelSelectionChanged);
return panel;
}
-2
View File
@@ -193,8 +193,6 @@ private slots:
void TimelinePanelSelectionChanged(const QVector<Block*> &blocks);
void ProjectPanelSelectionChanged(const QVector<Node*> &nodes);
void ShowWelcomeDialog();
};