fixed arrays in nodeparamview
This commit is contained in:
+7
-5
@@ -481,6 +481,13 @@ void NodeInput::ArrayResize(int size)
|
||||
{
|
||||
if (array_size_ != size) {
|
||||
// Update array size
|
||||
if (array_size_ < size) {
|
||||
// Size is larger, create any immediates that don't exist
|
||||
for (int i=subinputs_.size(); i<size; i++) {
|
||||
subinputs_.append(CreateImmediate());
|
||||
}
|
||||
}
|
||||
|
||||
ChangeArraySizeInternal(size);
|
||||
|
||||
if (array_size_ > size) {
|
||||
@@ -493,11 +500,6 @@ void NodeInput::ArrayResize(int size)
|
||||
|
||||
// Note that we do not delete any immediates since the user might still want that data.
|
||||
// Therefore it's important to note that array_size_ does NOT necessarily equal subinputs_.size()
|
||||
} else {
|
||||
// Size is larger, create any immediates that don't exist
|
||||
for (int i=subinputs_.size(); i<size; i++) {
|
||||
subinputs_.append(CreateImmediate());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,13 +33,6 @@ NodeParamViewArrayWidget::NodeParamViewArrayWidget(NodeInput *array, QWidget* pa
|
||||
count_lbl_ = new QLabel();
|
||||
layout->addWidget(count_lbl_);
|
||||
|
||||
layout->addStretch();
|
||||
|
||||
plus_btn_ = new QPushButton(tr("+"));
|
||||
plus_btn_->setFixedWidth(plus_btn_->sizeHint().height());
|
||||
layout->addWidget(plus_btn_);
|
||||
|
||||
connect(plus_btn_, &QPushButton::clicked, this, &NodeParamViewArrayWidget::AddElement);
|
||||
connect(array_, &NodeInput::ArraySizeChanged, this, &NodeParamViewArrayWidget::UpdateCounter);
|
||||
|
||||
UpdateCounter();
|
||||
@@ -50,9 +43,32 @@ void NodeParamViewArrayWidget::UpdateCounter()
|
||||
count_lbl_->setText(tr("%1 element(s)").arg(array_->ArraySize()));
|
||||
}
|
||||
|
||||
void NodeParamViewArrayWidget::AddElement()
|
||||
NodeParamViewArrayButton::NodeParamViewArrayButton(NodeParamViewArrayButton::Type type, QWidget *parent) :
|
||||
QPushButton(parent),
|
||||
type_(type)
|
||||
{
|
||||
array_->ArrayResize(array_->ArraySize() + 1);
|
||||
Retranslate();
|
||||
|
||||
int sz = sizeHint().height() / 3 * 2;
|
||||
setFixedSize(sz, sz);
|
||||
}
|
||||
|
||||
void NodeParamViewArrayButton::changeEvent(QEvent *event)
|
||||
{
|
||||
if (event->type() == QEvent::LanguageChange) {
|
||||
Retranslate();
|
||||
}
|
||||
|
||||
QPushButton::changeEvent(event);
|
||||
}
|
||||
|
||||
void NodeParamViewArrayButton::Retranslate()
|
||||
{
|
||||
if (type_ == kAdd) {
|
||||
setText(tr("+"));
|
||||
} else {
|
||||
setText(tr("-"));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -29,6 +29,27 @@
|
||||
|
||||
namespace olive {
|
||||
|
||||
class NodeParamViewArrayButton : public QPushButton
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum Type {
|
||||
kAdd,
|
||||
kRemove
|
||||
};
|
||||
|
||||
NodeParamViewArrayButton(Type type, QWidget* parent = nullptr);
|
||||
|
||||
protected:
|
||||
virtual void changeEvent(QEvent* event) override;
|
||||
|
||||
private:
|
||||
void Retranslate();
|
||||
|
||||
Type type_;
|
||||
|
||||
};
|
||||
|
||||
class NodeParamViewArrayWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
@@ -40,13 +61,9 @@ private:
|
||||
|
||||
QLabel* count_lbl_;
|
||||
|
||||
QPushButton* plus_btn_;
|
||||
|
||||
private slots:
|
||||
void UpdateCounter();
|
||||
|
||||
void AddElement();
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -94,4 +94,9 @@ void NodeParamViewConnectedLabel::ShowLabelContextMenu()
|
||||
m.exec(QCursor::pos());
|
||||
}
|
||||
|
||||
void NodeParamViewConnectedLabel::ConnectionClicked()
|
||||
{
|
||||
emit RequestSelectNode({input_->GetConnectedNode(element_)});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -32,13 +32,15 @@ public:
|
||||
NodeParamViewConnectedLabel(NodeInput* input, int element, QWidget* parent = nullptr);
|
||||
|
||||
signals:
|
||||
void ConnectionClicked();
|
||||
void RequestSelectNode(const QVector<Node*>& node);
|
||||
|
||||
private slots:
|
||||
void UpdateConnected(Node* src, int element);
|
||||
|
||||
void ShowLabelContextMenu();
|
||||
|
||||
void ConnectionClicked();
|
||||
|
||||
private:
|
||||
ClickableLabel* connected_to_lbl_;
|
||||
|
||||
|
||||
@@ -25,12 +25,17 @@
|
||||
#include <QEvent>
|
||||
#include <QPainter>
|
||||
|
||||
#include "common/qtutils.h"
|
||||
#include "core.h"
|
||||
#include "nodeparamviewundo.h"
|
||||
#include "project/item/sequence/sequence.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
const int NodeParamViewItemBody::kKeyControlColumn = 10;
|
||||
const int NodeParamViewItemBody::kArrayInsertColumn = kKeyControlColumn-1;
|
||||
const int NodeParamViewItemBody::kArrayRemoveColumn = kArrayInsertColumn-1;
|
||||
|
||||
NodeParamViewItem::NodeParamViewItem(Node *node, QWidget *parent) :
|
||||
QDockWidget(parent),
|
||||
node_(node),
|
||||
@@ -195,11 +200,42 @@ NodeParamViewItemBody::NodeParamViewItemBody(Node* node, QWidget *parent) :
|
||||
{
|
||||
QGridLayout* root_layout = new QGridLayout(this);
|
||||
|
||||
int insert_row = 0;
|
||||
|
||||
// Create widgets all root level components
|
||||
for (int i=0; i<node->inputs().size(); i++) {
|
||||
NodeInput* input = node->inputs().at(i);
|
||||
|
||||
CreateWidgets(root_layout, input, -1, i);
|
||||
CreateWidgets(root_layout, input, -1, insert_row);
|
||||
|
||||
insert_row++;
|
||||
|
||||
if (input->IsArray()) {
|
||||
// Insert here
|
||||
QWidget* array_widget = new QWidget();
|
||||
|
||||
QGridLayout* array_layout = new QGridLayout(array_widget);
|
||||
array_layout->setContentsMargins(QtUtils::QFontMetricsWidth(fontMetrics(), QStringLiteral(" ")), 0, 0, 0);
|
||||
|
||||
root_layout->addWidget(array_widget, insert_row, 1, 1, 10);
|
||||
|
||||
for (int j=0; j<input->ArraySize(); j++) {
|
||||
CreateWidgets(array_layout, input, j, j);
|
||||
}
|
||||
|
||||
// Add one last add button for appending to the array
|
||||
NodeParamViewArrayButton* append_btn = new NodeParamViewArrayButton(NodeParamViewArrayButton::kAdd);
|
||||
connect(append_btn, &NodeParamViewArrayButton::clicked, this, &NodeParamViewItemBody::ArrayAppendClicked);
|
||||
array_layout->addWidget(append_btn, input->ArraySize(), kArrayInsertColumn);
|
||||
|
||||
array_widget->setVisible(false);
|
||||
|
||||
array_ui_.insert(input, {array_widget, input->ArraySize(), append_btn});
|
||||
|
||||
insert_row++;
|
||||
|
||||
connect(input, &NodeInput::ArraySizeChanged, this, &NodeParamViewItemBody::InputArraySizeChanged);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -213,32 +249,39 @@ void NodeParamViewItemBody::CreateWidgets(QGridLayout* layout, NodeInput *input,
|
||||
// Label always goes into column 1 (array collapse button goes into 0 if applicable)
|
||||
layout->addWidget(ui_objects.main_label, row, 1);
|
||||
|
||||
if (input->IsArray() && element == -1) {
|
||||
// Create a collapse toggle for expanding/collapsing the array
|
||||
CollapseButton* array_collapse_btn = new CollapseButton();
|
||||
if (input->IsArray()) {
|
||||
if (element == -1) {
|
||||
|
||||
// Collapse button always goes into column 0
|
||||
layout->addWidget(array_collapse_btn, row, 0);
|
||||
// Create a collapse toggle for expanding/collapsing the array
|
||||
CollapseButton* array_collapse_btn = new CollapseButton();
|
||||
|
||||
// Default to collapsed
|
||||
array_collapse_btn->setChecked(false);
|
||||
|
||||
/*
|
||||
QVector<NodeConnectable::InputConnection> subelements(conn.input->ArraySize());
|
||||
// Add data
|
||||
array_collapse_btn->setProperty("input", Node::PtrToValue(input));
|
||||
|
||||
// Collapse button always goes into column 0
|
||||
layout->addWidget(array_collapse_btn, row, 0);
|
||||
|
||||
// Connect signal to show/hide array params when toggled
|
||||
connect(array_collapse_btn, &CollapseButton::toggled, this, &NodeParamViewItemBody::ArrayCollapseBtnPressed);
|
||||
|
||||
} else {
|
||||
|
||||
NodeParamViewArrayButton* insert_element_btn = new NodeParamViewArrayButton(NodeParamViewArrayButton::kAdd);
|
||||
NodeParamViewArrayButton* remove_element_btn = new NodeParamViewArrayButton(NodeParamViewArrayButton::kRemove);
|
||||
|
||||
layout->addWidget(insert_element_btn, row, kArrayInsertColumn);
|
||||
layout->addWidget(remove_element_btn, row, kArrayRemoveColumn);
|
||||
|
||||
ui_objects.array_insert_btn = insert_element_btn;
|
||||
ui_objects.array_remove_btn = remove_element_btn;
|
||||
|
||||
connect(insert_element_btn, &NodeParamViewArrayButton::clicked, this, &NodeParamViewItemBody::ArrayInsertClicked);
|
||||
connect(remove_element_btn, &NodeParamViewArrayButton::clicked, this, &NodeParamViewItemBody::ArrayRemoveClicked);
|
||||
|
||||
for (int i=0; i<conn.input->ArraySize(); i++) {
|
||||
subelements[i] = {conn.input, i};
|
||||
}
|
||||
|
||||
NodeParamViewItemBody* sub_body = new NodeParamViewItemBody(subelements);
|
||||
sub_bodies_.append(sub_body);
|
||||
sub_body->layout()->setMargin(0);
|
||||
content_layout->addWidget(sub_body, row_count + 1, 0, 1, max_col + 1);
|
||||
|
||||
connect(array_collapse_btn, &CollapseButton::toggled, sub_body, &NodeParamViewItemBody::setVisible);
|
||||
|
||||
connect(sub_body, &NodeParamViewItemBody::KeyframeAdded, this, &NodeParamViewItemBody::KeyframeAdded);
|
||||
connect(sub_body, &NodeParamViewItemBody::KeyframeRemoved, this, &NodeParamViewItemBody::KeyframeRemoved);
|
||||
connect(sub_body, &NodeParamViewItemBody::RequestSetTime, this, &NodeParamViewItemBody::RequestSetTime);
|
||||
connect(sub_body, &NodeParamViewItemBody::RequestSelectNode, this, &NodeParamViewItemBody::RequestSelectNode);*/
|
||||
}
|
||||
|
||||
// Create a widget/input bridge for this input
|
||||
@@ -257,7 +300,7 @@ void NodeParamViewItemBody::CreateWidgets(QGridLayout* layout, NodeInput *input,
|
||||
if (input->IsConnectable()) {
|
||||
// Create clickable label used when an input is connected
|
||||
ui_objects.connected_label = new NodeParamViewConnectedLabel(input, element);
|
||||
connect(ui_objects.connected_label, &NodeParamViewConnectedLabel::ConnectionClicked, this, &NodeParamViewItemBody::ConnectionClicked);
|
||||
connect(ui_objects.connected_label, &NodeParamViewConnectedLabel::RequestSelectNode, this, &NodeParamViewItemBody::RequestSelectNode);
|
||||
layout->addWidget(ui_objects.connected_label, row, widget_start);
|
||||
|
||||
connect(input, &NodeInput::InputConnected, this, &NodeParamViewItemBody::EdgeChanged);
|
||||
@@ -266,13 +309,9 @@ void NodeParamViewItemBody::CreateWidgets(QGridLayout* layout, NodeInput *input,
|
||||
|
||||
// Add keyframe control to this layout if parameter is keyframable
|
||||
if (input->IsKeyframable()) {
|
||||
// We make an assumption here that there will never be more than 7 widgets and so the 10th
|
||||
// column will be free
|
||||
const int control_column = 10;
|
||||
|
||||
ui_objects.key_control = new NodeParamViewKeyframeControl();
|
||||
ui_objects.key_control->SetInput(input, element);
|
||||
layout->addWidget(ui_objects.key_control, row, control_column);
|
||||
layout->addWidget(ui_objects.key_control, row, kKeyControlColumn);
|
||||
connect(ui_objects.key_control, &NodeParamViewKeyframeControl::RequestSetTime, this, &NodeParamViewItemBody::RequestSetTime);
|
||||
|
||||
connect(input, &NodeInput::KeyframeEnableChanged, this, &NodeParamViewItemBody::InputKeyframeEnableChanged);
|
||||
@@ -297,10 +336,6 @@ void NodeParamViewItemBody::SetTimeTarget(Node *target)
|
||||
|
||||
ui_obj.widget_bridge->SetTimeTarget(target);
|
||||
}
|
||||
|
||||
foreach (NodeParamViewItemBody* sb, sub_bodies_) {
|
||||
sb->SetTimeTarget(target);
|
||||
}
|
||||
}
|
||||
|
||||
void NodeParamViewItemBody::SetTime(const rational &time)
|
||||
@@ -313,20 +348,20 @@ void NodeParamViewItemBody::SetTime(const rational &time)
|
||||
|
||||
ui_obj.widget_bridge->SetTime(time);
|
||||
}
|
||||
|
||||
foreach (NodeParamViewItemBody* sb, sub_bodies_) {
|
||||
sb->SetTime(time);
|
||||
}
|
||||
}
|
||||
|
||||
void NodeParamViewItemBody::Retranslate()
|
||||
{
|
||||
for (auto i=input_ui_map_.begin(); i!=input_ui_map_.end(); i++) {
|
||||
i.value().main_label->setText(tr("%1:").arg(i.key().input->name()));
|
||||
}
|
||||
const Node::InputConnection& ic = i.key();
|
||||
|
||||
foreach (NodeParamViewItemBody* sb, sub_bodies_) {
|
||||
sb->Retranslate();
|
||||
if (ic.input->IsArray() && ic.element >= 0) {
|
||||
// Make the label the array index
|
||||
i.value().main_label->setText(tr("%n:", nullptr, ic.element));
|
||||
} else {
|
||||
// Set to the input's name
|
||||
i.value().main_label->setText(tr("%1:").arg(i.key().input->name()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -341,10 +376,6 @@ void NodeParamViewItemBody::SignalAllKeyframes()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (NodeParamViewItemBody* sb, sub_bodies_) {
|
||||
sb->SignalAllKeyframes();
|
||||
}
|
||||
}
|
||||
|
||||
void NodeParamViewItemBody::EdgeChanged(Node* src, int element)
|
||||
@@ -392,21 +423,6 @@ void NodeParamViewItemBody::InputAddedKeyframe(NodeKeyframe* key)
|
||||
InputAddedKeyframeInternal(input, key);
|
||||
}
|
||||
|
||||
void NodeParamViewItemBody::ConnectionClicked()
|
||||
{
|
||||
for (auto iterator=input_ui_map_.begin(); iterator!=input_ui_map_.end(); iterator++) {
|
||||
if (iterator.value().connected_label == sender()) {
|
||||
Node* connected = iterator.key().input->parent();
|
||||
|
||||
if (connected) {
|
||||
emit RequestSelectNode({connected});
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NodeParamViewItemBody::InputAddedKeyframeInternal(NodeInput *input, NodeKeyframe* keyframe)
|
||||
{
|
||||
// Find its row in the parameters
|
||||
@@ -421,11 +437,92 @@ void NodeParamViewItemBody::InputAddedKeyframeInternal(NodeInput *input, NodeKey
|
||||
emit KeyframeAdded(keyframe, lbl_center.y());
|
||||
}
|
||||
|
||||
void NodeParamViewItemBody::ArrayCollapseBtnPressed(bool checked)
|
||||
{
|
||||
NodeInput* input = Node::ValueToPtr<NodeInput>(sender()->property("input"));
|
||||
|
||||
array_ui_.value(input).widget->setVisible(checked);
|
||||
}
|
||||
|
||||
void NodeParamViewItemBody::InputArraySizeChanged(int size)
|
||||
{
|
||||
NodeInput* input = static_cast<NodeInput*>(sender());
|
||||
|
||||
ArrayUI& array_ui = array_ui_[input];
|
||||
|
||||
if (size != array_ui.count) {
|
||||
QGridLayout* grid = static_cast<QGridLayout*>(array_ui.widget->layout());
|
||||
|
||||
if (array_ui.count < size) {
|
||||
// Our UI count is smaller than the size, create more
|
||||
grid->addWidget(array_ui.append_btn, size, kArrayInsertColumn);
|
||||
|
||||
for (int i=array_ui.count; i<size; i++) {
|
||||
CreateWidgets(grid, input, i, i);
|
||||
}
|
||||
} else {
|
||||
for (int i=array_ui.count-1; i>=size; i--) {
|
||||
// Our UI count is larger than the size, delete
|
||||
InputUI input_ui = input_ui_map_.take({input, i});
|
||||
delete input_ui.main_label;
|
||||
qDeleteAll(input_ui.widget_bridge->widgets());
|
||||
delete input_ui.widget_bridge;
|
||||
delete input_ui.connected_label;
|
||||
delete input_ui.key_control;
|
||||
delete input_ui.array_insert_btn;
|
||||
delete input_ui.array_remove_btn;
|
||||
}
|
||||
|
||||
grid->addWidget(array_ui.append_btn, size, kArrayInsertColumn);
|
||||
}
|
||||
|
||||
array_ui.count = size;
|
||||
}
|
||||
|
||||
Retranslate();
|
||||
}
|
||||
|
||||
void NodeParamViewItemBody::ArrayAppendClicked()
|
||||
{
|
||||
for (auto it=array_ui_.cbegin(); it!=array_ui_.cend(); it++) {
|
||||
if (it.value().append_btn == sender()) {
|
||||
it.key()->ArrayAppend();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NodeParamViewItemBody::ArrayInsertClicked()
|
||||
{
|
||||
for (auto it=input_ui_map_.cbegin(); it!=input_ui_map_.cend(); it++) {
|
||||
if (it.value().array_insert_btn == sender()) {
|
||||
// Found our input and element
|
||||
const Node::InputConnection& ic = it.key();
|
||||
ic.input->ArrayInsert(ic.element);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NodeParamViewItemBody::ArrayRemoveClicked()
|
||||
{
|
||||
for (auto it=input_ui_map_.cbegin(); it!=input_ui_map_.cend(); it++) {
|
||||
if (it.value().array_remove_btn == sender()) {
|
||||
// Found our input and element
|
||||
const Node::InputConnection& ic = it.key();
|
||||
ic.input->ArrayRemove(ic.element);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NodeParamViewItemBody::InputUI::InputUI() :
|
||||
main_label(nullptr),
|
||||
widget_bridge(nullptr),
|
||||
connected_label(nullptr),
|
||||
key_control(nullptr)
|
||||
key_control(nullptr),
|
||||
array_insert_btn(nullptr),
|
||||
array_remove_btn(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include <QWidget>
|
||||
|
||||
#include "node/node.h"
|
||||
#include "nodeparamviewarraywidget.h"
|
||||
#include "nodeparamviewconnectedlabel.h"
|
||||
#include "nodeparamviewkeyframecontrol.h"
|
||||
#include "nodeparamviewwidgetbridge.h"
|
||||
@@ -105,11 +106,31 @@ private:
|
||||
NodeParamViewWidgetBridge* widget_bridge;
|
||||
NodeParamViewConnectedLabel* connected_label;
|
||||
NodeParamViewKeyframeControl* key_control;
|
||||
|
||||
NodeParamViewArrayButton* array_insert_btn;
|
||||
NodeParamViewArrayButton* array_remove_btn;
|
||||
};
|
||||
|
||||
QHash<Node::InputConnection, InputUI> input_ui_map_;
|
||||
|
||||
QVector<NodeParamViewItemBody*> sub_bodies_;
|
||||
struct ArrayUI {
|
||||
QWidget* widget;
|
||||
int count;
|
||||
NodeParamViewArrayButton* append_btn;
|
||||
};
|
||||
|
||||
QHash<NodeInput*, ArrayUI> array_ui_;
|
||||
|
||||
/**
|
||||
* @brief The column to place the keyframe controls in
|
||||
*
|
||||
* Serves as an effective "maximum column" index because the keyframe button is always aligned
|
||||
* to the right edge.
|
||||
*/
|
||||
static const int kKeyControlColumn;
|
||||
|
||||
static const int kArrayInsertColumn;
|
||||
static const int kArrayRemoveColumn;
|
||||
|
||||
private slots:
|
||||
void EdgeChanged(Node *src, int element);
|
||||
@@ -118,7 +139,15 @@ private slots:
|
||||
|
||||
void InputAddedKeyframe(NodeKeyframe* key);
|
||||
|
||||
void ConnectionClicked();
|
||||
void ArrayCollapseBtnPressed(bool checked);
|
||||
|
||||
void InputArraySizeChanged(int size);
|
||||
|
||||
void ArrayAppendClicked();
|
||||
|
||||
void ArrayInsertClicked();
|
||||
|
||||
void ArrayRemoveClicked();
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ const QList<QWidget *> &NodeParamViewWidgetBridge::widgets() const
|
||||
|
||||
void NodeParamViewWidgetBridge::CreateWidgets()
|
||||
{
|
||||
if (input_->IsArray()) {
|
||||
if (input_->IsArray() && element_ == -1) {
|
||||
|
||||
NodeParamViewArrayWidget* w = new NodeParamViewArrayWidget(input_);
|
||||
widgets_.append(w);
|
||||
|
||||
@@ -79,14 +79,15 @@ void NodeView::SetGraph(NodeGraph *graph)
|
||||
disconnect(graph_, &NodeGraph::NodeRemoved, &scene_, &NodeViewScene::RemoveNode);
|
||||
disconnect(graph_, &NodeGraph::InputConnected, &scene_, &NodeViewScene::AddEdge);
|
||||
disconnect(graph_, &NodeGraph::InputDisconnected, &scene_, &NodeViewScene::RemoveEdge);
|
||||
}
|
||||
|
||||
// Clear the scene of all UI objects
|
||||
scene_.clear();
|
||||
DeselectAll();
|
||||
|
||||
// Clear the scene of all UI objects
|
||||
scene_.clear();
|
||||
}
|
||||
|
||||
// Set reference to the graph
|
||||
graph_ = graph;
|
||||
scene_.SetGraph(graph_);
|
||||
|
||||
// If the graph is valid, add UI objects for each of its Nodes
|
||||
if (graph_) {
|
||||
@@ -148,6 +149,10 @@ void NodeView::DeleteSelected()
|
||||
|
||||
void NodeView::SelectAll()
|
||||
{
|
||||
if (!graph_) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Optimization: rather than respond to every single item being selected, ignore the signal and
|
||||
// then handle them all at the end.
|
||||
DisconnectSelectionChangedSignal();
|
||||
@@ -155,24 +160,29 @@ void NodeView::SelectAll()
|
||||
scene_.SelectAll();
|
||||
|
||||
ConnectSelectionChangedSignal();
|
||||
SceneSelectionChangedSlot();
|
||||
|
||||
if (selected_nodes_.isEmpty()) {
|
||||
// No nodes were selected before so we can just emit them all
|
||||
emit NodesSelected(graph_->nodes());
|
||||
} else {
|
||||
// We have to determine the difference
|
||||
QVector<Node*> new_selection;
|
||||
foreach (Node* n, graph_->nodes()) {
|
||||
if (!selected_nodes_.contains(n)) {
|
||||
new_selection.append(n);
|
||||
}
|
||||
}
|
||||
|
||||
emit NodesSelected(new_selection);
|
||||
}
|
||||
|
||||
// Just add everything to the selected nodes list
|
||||
selected_nodes_ = graph_->nodes();
|
||||
}
|
||||
|
||||
void NodeView::DeselectAll()
|
||||
{
|
||||
// Optimization: rather than respond to every single item being selected, ignore the signal and
|
||||
// then handle them all at the end.
|
||||
DisconnectSelectionChangedSignal();
|
||||
|
||||
scene_.DeselectAll();
|
||||
|
||||
ConnectSelectionChangedSignal();
|
||||
SceneSelectionChangedSlot();
|
||||
}
|
||||
|
||||
void NodeView::Select(const QVector<Node *> &nodes)
|
||||
{
|
||||
if (!graph_) {
|
||||
if (!graph_ || selected_nodes_.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -182,14 +192,63 @@ void NodeView::Select(const QVector<Node *> &nodes)
|
||||
|
||||
scene_.DeselectAll();
|
||||
|
||||
ConnectSelectionChangedSignal();
|
||||
|
||||
// Just emit all the nodes that are currently selected as no longer selected
|
||||
emit NodesDeselected(selected_nodes_);
|
||||
selected_nodes_.clear();
|
||||
}
|
||||
|
||||
void NodeView::Select(QVector<Node *> nodes)
|
||||
{
|
||||
if (!graph_) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Optimization: rather than respond to every single item being selected, ignore the signal and
|
||||
// then handle them all at the end.
|
||||
DisconnectSelectionChangedSignal();
|
||||
|
||||
QVector<Node*> deselections_ = selected_nodes_;
|
||||
QVector<Node*> new_selections_;
|
||||
|
||||
scene_.DeselectAll();
|
||||
|
||||
// Remove any duplicates
|
||||
QVector<Node*> processed;
|
||||
|
||||
foreach (Node* n, nodes) {
|
||||
if (processed.contains(n)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
processed.append(n);
|
||||
|
||||
NodeViewItem* item = scene_.NodeToUIObject(n);
|
||||
|
||||
item->setSelected(true);
|
||||
|
||||
if (deselections_.contains(n)) {
|
||||
deselections_.removeOne(n);
|
||||
} else {
|
||||
new_selections_.append(n);
|
||||
}
|
||||
}
|
||||
|
||||
ConnectSelectionChangedSignal();
|
||||
SceneSelectionChangedSlot();
|
||||
|
||||
// Emit deselect signal for any nodes that weren't in the list
|
||||
if (!deselections_.isEmpty()) {
|
||||
emit NodesDeselected(deselections_);
|
||||
}
|
||||
|
||||
// Emit select signal for any nodes that weren't in the list
|
||||
if (!new_selections_.isEmpty()) {
|
||||
emit NodesSelected(new_selections_);
|
||||
}
|
||||
|
||||
// Update selected list to the list we received
|
||||
selected_nodes_ = nodes;
|
||||
}
|
||||
|
||||
void NodeView::SelectWithDependencies(QVector<Node *> nodes)
|
||||
@@ -325,6 +384,11 @@ void NodeView::mouseMoveEvent(QMouseEvent *event)
|
||||
// Find if the cursor is currently inside an item
|
||||
NodeViewItem* item_at_cursor = dynamic_cast<NodeViewItem*>(itemAt(event->pos()));
|
||||
|
||||
// Filter out connecting to self1
|
||||
if (item_at_cursor == create_edge_src_) {
|
||||
item_at_cursor = nullptr;
|
||||
}
|
||||
|
||||
// If the item has changed
|
||||
if (item_at_cursor != create_edge_dst_) {
|
||||
// If we had a destination active, disconnect from it since the item has changed
|
||||
@@ -505,7 +569,7 @@ void NodeView::wheelEvent(QWheelEvent *event)
|
||||
}
|
||||
}
|
||||
|
||||
void NodeView::SceneSelectionChangedSlot()
|
||||
void NodeView::UpdateSelectionCache()
|
||||
{
|
||||
QVector<Node*> current_selection = scene_.GetSelectedNodes();
|
||||
|
||||
@@ -714,12 +778,12 @@ void NodeView::MoveAttachedNodesToCursor(const QPoint& p)
|
||||
|
||||
void NodeView::ConnectSelectionChangedSignal()
|
||||
{
|
||||
connect(&scene_, &QGraphicsScene::selectionChanged, this, &NodeView::SceneSelectionChangedSlot);
|
||||
connect(&scene_, &QGraphicsScene::selectionChanged, this, &NodeView::UpdateSelectionCache);
|
||||
}
|
||||
|
||||
void NodeView::DisconnectSelectionChangedSignal()
|
||||
{
|
||||
disconnect(&scene_, &QGraphicsScene::selectionChanged, this, &NodeView::SceneSelectionChangedSlot);
|
||||
disconnect(&scene_, &QGraphicsScene::selectionChanged, this, &NodeView::UpdateSelectionCache);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ public:
|
||||
void SelectAll();
|
||||
void DeselectAll();
|
||||
|
||||
void Select(const QVector<Node*>& nodes);
|
||||
void Select(QVector<Node *> nodes);
|
||||
void SelectWithDependencies(QVector<Node *> nodes);
|
||||
|
||||
void CopySelected(bool cut);
|
||||
@@ -134,7 +134,7 @@ private slots:
|
||||
/**
|
||||
* @brief Receiver for when the scene's selected items change
|
||||
*/
|
||||
void SceneSelectionChangedSlot();
|
||||
void UpdateSelectionCache();
|
||||
|
||||
/**
|
||||
* @brief Receiver for when the user right clicks (or otherwise requests a context menu)
|
||||
|
||||
@@ -29,7 +29,6 @@ namespace olive {
|
||||
|
||||
NodeViewScene::NodeViewScene(QObject *parent) :
|
||||
QGraphicsScene(parent),
|
||||
graph_(nullptr),
|
||||
direction_(NodeViewCommon::kLeftToRight),
|
||||
curved_edges_(true)
|
||||
{
|
||||
@@ -110,11 +109,6 @@ NodeViewEdge *NodeViewScene::EdgeToUIObject(Node* output, NodeInput* input, int
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void NodeViewScene::SetGraph(NodeGraph *graph)
|
||||
{
|
||||
graph_ = graph;
|
||||
}
|
||||
|
||||
QVector<Node *> NodeViewScene::GetSelectedNodes() const
|
||||
{
|
||||
QHash<Node*, NodeViewItem*>::const_iterator iterator;
|
||||
@@ -266,11 +260,6 @@ void NodeViewScene::ReorganizeFrom(Node* n)
|
||||
}
|
||||
}
|
||||
|
||||
bool NodeViewScene::GetEdgesAreCurved() const
|
||||
{
|
||||
return curved_edges_;
|
||||
}
|
||||
|
||||
void NodeViewScene::SetEdgesAreCurved(bool curved)
|
||||
{
|
||||
if (curved_edges_ != curved) {
|
||||
|
||||
@@ -55,8 +55,6 @@ public:
|
||||
NodeViewItem* NodeToUIObject(Node* n);
|
||||
NodeViewEdge *EdgeToUIObject(Node* output, NodeInput *input, int element);
|
||||
|
||||
void SetGraph(NodeGraph* graph);
|
||||
|
||||
QVector<Node *> GetSelectedNodes() const;
|
||||
QVector<NodeViewItem*> GetSelectedItems() const;
|
||||
QVector<NodeViewEdge*> GetSelectedEdges() const;
|
||||
@@ -76,7 +74,10 @@ public:
|
||||
NodeViewCommon::FlowDirection GetFlowDirection() const;
|
||||
void SetFlowDirection(NodeViewCommon::FlowDirection direction);
|
||||
|
||||
bool GetEdgesAreCurved() const;
|
||||
bool GetEdgesAreCurved() const
|
||||
{
|
||||
return curved_edges_;
|
||||
}
|
||||
|
||||
void ReorganizeFrom(Node* n);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user