nodeview: allow users to place a node on an edge to automatically connect it

between the two nodes

UI convenience. Edge highlights when the cursor is in range to perform this
action.
This commit is contained in:
itsmattkc
2020-02-16 12:40:12 +11:00
parent a987899e5c
commit ce889f68d5
6 changed files with 111 additions and 8 deletions
+71 -1
View File
@@ -29,7 +29,8 @@
NodeView::NodeView(QWidget *parent) :
QGraphicsView(parent),
graph_(nullptr),
attached_item_(nullptr)
attached_item_(nullptr),
drop_edge_(nullptr)
{
setScene(&scene_);
setDragMode(RubberBandDrag);
@@ -231,7 +232,25 @@ void NodeView::keyPressEvent(QKeyEvent *event)
void NodeView::mousePressEvent(QMouseEvent *event)
{
if (attached_item_) {
Node* dropping_node = attached_item_->node();
DetachItemFromCursor();
if (drop_edge_) {
NodeEdgePtr old_edge = drop_edge_->edge();
// We have everything we need to place the node in between
QUndoCommand* command = new QUndoCommand();
// Remove old edge
new NodeEdgeRemoveCommand(old_edge, command);
// Place new edges
new NodeEdgeAddCommand(old_edge->output(), drop_compatible_input_, command);
new NodeEdgeAddCommand(dropping_node->output(), old_edge->input(), command);
Core::instance()->undo_stack()->push(command);
}
}
QGraphicsView::mousePressEvent(event);
@@ -243,6 +262,57 @@ void NodeView::mouseMoveEvent(QMouseEvent *event)
if (attached_item_) {
attached_item_->setPos(mapToScene(event->pos()));
// See if the user clicked on an edge
QRect edge_detect_rect(event->pos(), event->pos());
// FIXME: Hardcoded numbers
edge_detect_rect.adjust(-20, -20, 20, 20);
QList<QGraphicsItem*> items = this->items(edge_detect_rect);
NodeViewEdge* new_drop_edge = nullptr;
foreach (QGraphicsItem* item, items) {
NodeViewEdge* edge = dynamic_cast<NodeViewEdge*>(item);
if (edge) {
// Try to place this node inside this edge
// See if the node we're dropping has an input of a compatible data type
NodeInput* edges_input = edge->edge()->input();
NodeParam::DataType input_type = edges_input->data_type();
NodeInput* compatible_input = nullptr;
foreach (NodeParam* drop_node_param, attached_item_->node()->parameters()) {
if (drop_node_param->type() == NodeParam::kInput
&& static_cast<NodeInput*>(drop_node_param)->data_type() & input_type) {
compatible_input = static_cast<NodeInput*>(drop_node_param);
break;
}
}
if (compatible_input) {
new_drop_edge = edge;
drop_compatible_input_ = compatible_input;
break;
}
}
}
if (drop_edge_ != new_drop_edge) {
if (drop_edge_) {
drop_edge_->SetHighlighted(false);
}
drop_edge_ = new_drop_edge;
if (drop_edge_) {
drop_edge_->SetHighlighted(true);
}
}
}
}
+3
View File
@@ -114,6 +114,9 @@ private:
NodeViewItem* attached_item_;
NodeViewEdge* drop_edge_;
NodeInput* drop_compatible_input_;
QGraphicsScene scene_;
QTimer reorganize_timer_;
+18 -7
View File
@@ -30,7 +30,8 @@
NodeViewEdge::NodeViewEdge(QGraphicsItem *parent) :
QGraphicsLineItem(parent),
edge_(nullptr),
connected_(false)
connected_(false),
highlighted_(false)
{
// Ensures this UI object is drawn behind other objects
setZValue(-1);
@@ -101,19 +102,29 @@ void NodeViewEdge::Adjust()
void NodeViewEdge::SetConnected(bool c)
{
connected_ = c;
update();
}
void NodeViewEdge::SetHighlighted(bool e)
{
highlighted_ = e;
update();
}
void NodeViewEdge::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
QPalette::ColorGroup color_mode;
QPalette::ColorGroup color_group = QPalette::Active;
QPalette::ColorRole color_role = QPalette::Text;
if (connected_) {
color_mode = QPalette::Active;
} else {
color_mode = QPalette::Disabled;
if (highlighted_) {
color_role = QPalette::Highlight;
}
setPen(QPen(widget->palette().color(color_mode, QPalette::Text), edge_width_));
if (!connected_) {
color_group = QPalette::Disabled;
}
setPen(QPen(widget->palette().color(color_group, color_role), edge_width_));
QGraphicsLineItem::paint(painter, option, widget);
}
+10
View File
@@ -68,6 +68,13 @@ public:
*/
void SetConnected(bool c);
/**
* @brief Set highlighted state
*
* Changes color of edge.
*/
void SetHighlighted(bool e);
protected:
virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr) override;
@@ -77,6 +84,9 @@ private:
int edge_width_;
bool connected_;
bool highlighted_;
};
#endif // NODEEDGEITEM_H
+8
View File
@@ -45,6 +45,14 @@ NodeEdgeRemoveCommand::NodeEdgeRemoveCommand(NodeOutput *output, NodeInput *inpu
{
}
NodeEdgeRemoveCommand::NodeEdgeRemoveCommand(NodeEdgePtr edge, QUndoCommand *parent) :
QUndoCommand(parent),
output_(edge->output()),
input_(edge->input()),
done_(false)
{
}
void NodeEdgeRemoveCommand::redo()
{
if (done_) {
+1
View File
@@ -36,6 +36,7 @@ private:
class NodeEdgeRemoveCommand : public QUndoCommand {
public:
NodeEdgeRemoveCommand(NodeOutput* output, NodeInput* input, QUndoCommand* parent = nullptr);
NodeEdgeRemoveCommand(NodeEdgePtr edge, QUndoCommand* parent = nullptr);
virtual void redo() override;
virtual void undo() override;