Skip to content

Commit 5909b36

Browse files
committed
Drag onto link to insert widget
1 parent 8989b6b commit 5909b36

File tree

2 files changed

+33
-8
lines changed

2 files changed

+33
-8
lines changed

Orange/canvas/canvas/items/linkitem.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ class LinkCurveItem(QGraphicsPathItem):
2828
"""
2929
def __init__(self, parent):
3030
super().__init__(parent)
31+
self.__parent = parent
32+
3133
self.setAcceptedMouseButtons(Qt.NoButton)
3234
self.setAcceptHoverEvents(True)
3335

@@ -91,6 +93,9 @@ def setPath(self, path):
9193
self.__shape = None
9294
super().setPath(path)
9395

96+
def parent(self):
97+
return self.__parent
98+
9499
def __update(self):
95100
shadow_enabled = self.__hover
96101
if self.shadow.isEnabled() != shadow_enabled:

Orange/canvas/document/schemeedit.py

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -879,6 +879,9 @@ def removeLink(self, link):
879879
self.__undoStack.push(command)
880880

881881
def insertNode(self, link, new_node):
882+
"""
883+
Insert a node in-between two linked nodes.
884+
"""
882885
command = commands.InsertNodeCommand(self.__scheme, link, new_node)
883886
self.__undoStack.push(command)
884887

@@ -1044,6 +1047,17 @@ def changeEvent(self, event):
10441047

10451048
QWidget.changeEvent(self, event)
10461049

1050+
def tryInsertNode(self, link, new_node_desc, pos):
1051+
source_node = link.source_node
1052+
sink_node = link.sink_node
1053+
1054+
if are_nodes_compatible(source_node.description, new_node_desc) and \
1055+
are_nodes_compatible(new_node_desc, sink_node.description):
1056+
new_node = self.newNodeHelper(new_node_desc, position=(pos.x(), pos.y()))
1057+
self.insertNode(link, new_node)
1058+
else:
1059+
self.createNewNode(new_node_desc, position=(pos.x(), pos.y()))
1060+
10471061
def eventFilter(self, obj, event):
10481062
# Filter the scene's drag/drop events.
10491063
if obj is self.scene():
@@ -1069,7 +1083,12 @@ def eventFilter(self, obj, event):
10691083
log.error("Unknown qualified name '%s'", qname)
10701084
else:
10711085
pos = event.scenePos()
1072-
self.createNewNode(desc, position=(pos.x(), pos.y()))
1086+
item = self.__scene.item_at(event.scenePos())
1087+
if item and isinstance(item, items.LinkCurveItem):
1088+
link = self.__scene.link_for_item(item.parent())
1089+
self.tryInsertNode(link, desc, pos)
1090+
else:
1091+
self.createNewNode(desc, position=(pos.x(), pos.y()))
10731092
return True
10741093

10751094
elif etype == QEvent.GraphicsSceneMousePress:
@@ -1620,16 +1639,11 @@ def __nodeInsert(self):
16201639
source_node = original_link.source_node
16211640
sink_node = original_link.sink_node
16221641

1623-
def is_compatible(source, sink):
1624-
return any(scheme.compatible_channels(output, input) \
1625-
for output in source.outputs \
1626-
for input in sink.inputs)
1627-
16281642
def filterFunc(index):
16291643
new_node_desc = index.data(QtWidgetRegistry.WIDGET_DESC_ROLE)
16301644
if isinstance(new_node_desc, WidgetDescription):
1631-
return is_compatible(source_node.description, new_node_desc) and\
1632-
is_compatible(new_node_desc, sink_node.description)
1645+
return are_nodes_compatible(source_node.description, new_node_desc) and\
1646+
are_nodes_compatible(new_node_desc, sink_node.description)
16331647
else:
16341648
return False
16351649

@@ -1997,6 +2011,12 @@ def node_properties(scheme):
19972011
return [dict(node.properties) for node in scheme.nodes]
19982012

19992013

2014+
def are_nodes_compatible(source, sink):
2015+
return any(scheme.compatible_channels(output, input) \
2016+
for output in source.outputs \
2017+
for input in sink.inputs)
2018+
2019+
20002020
def uniquify(item, names, pattern="{item}-{_}", start=0):
20012021
candidates = (pattern.format(item=item, _=i)
20022022
for i in itertools.count(start))

0 commit comments

Comments
 (0)