Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ui] add support for selecting multiple nodes at once #1227

Merged
merged 7 commits into from
May 3, 2021
Merged

[ui] add support for selecting multiple nodes at once #1227

merged 7 commits into from
May 3, 2021

Conversation

ChemicalXandco
Copy link
Contributor

Description

The ability to select multiple nodes at once improves the efficiency of using the graph editor. I have tried to make the node selection behave similar to blender. The box select widget is used by dragging with the left mouse button. The main selected node is slightly brighter than the other selected nodes and has a blue border.
Screenshot_20210115_202417
Screenshot_20210115_193313

Features list

  • select multiple nodes at once
  • use of control key modifier to select multiple nodes
  • use of box select widget to select multiple nodes
  • duplicate selected nodes
  • remove selected nodes
  • delete data of selected nodes
  • move selected nodes together

(Resolves some points on #269)

@natowi natowi added feature new feature (proposed as PR or issue planned by dev) UI labels Jan 16, 2021
@ChemicalXandco ChemicalXandco mentioned this pull request Jan 18, 2021
@fabiencastan
Copy link
Member

I often get this error when manipulating nodes in the GraphEditor:

Traceback (most recent call last):
  File "C:\dev\meshroom\meshroom\common\qt.py", line 190, in remove
    raise ValueError("QObjectListModel.remove(obj) : obj not in list")
ValueError: QObjectListModel.remove(obj) : obj not in list
[2021-01-22 23:22:10,394][WARNING] file:///C:/dev/meshroom/meshroom/ui/qml/GraphEditor/GraphEditor.qml:446: Error: QObjectListModel.remove(obj) : obj not in list

Copy link
Member

@fabiencastan fabiencastan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the really cool PR!
I have added few notes to clean the code before integration.

for node in self._selectedNodes:
position = Position(node.x + deltaX, node.y + deltaY)
self.push(commands.MoveNodeCommand(self._graph, node, position))

@Slot(Node)
def removeNode(self, node):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The check on locked makes sense, but should we really care about the notion of selection here?
The function is called removeNode and takes a node in parameter, so it should just do the action.

Comment on lines 543 to 544
if not node.locked:
self.push(commands.RemoveNodeCommand(self._graph, node))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if not node.locked:
self.push(commands.RemoveNodeCommand(self._graph, node))
self.removeNode(node)

Comment on lines 560 to 561
if not node.locked:
self.removeNode(node)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if not node.locked:
self.removeNode(node)
self.removeNode(node)

Already checked in the function.

@@ -569,19 +599,33 @@ def duplicateNode(self, srcNode, duplicateFollowingNodes=False):
Returns:
[Nodes]: the list of duplicated nodes
"""
title = "Duplicate Nodes from {}" if duplicateFollowingNodes else "Duplicate {}"
if duplicateFollowingNodes: title = "Duplicate Nodes from {}"
elif self.nodeSelection(srcNode): title = "Duplicate selected nodes"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should not have links with the notion of node selection at this level. The UI use the selection to determine the list of nodes. Then we have the list of nodes and perform actions on it. But the low-level functions should not check the notion of selection again.

The function is explicit: duplicateNode(srcNode, duplicateFollowingNodes=False). We don't expect that to check the notion of selection.

# enable updates between duplication and layout to get correct depths during layout
with self.groupedGraphModification(title.format(srcNode.name), disableUpdates=False):
# disable graph updates during duplication
with self.groupedGraphModification("Node duplication", disableUpdates=True):
duplicates = self.push(commands.DuplicateNodeCommand(self._graph, srcNode, duplicateFollowingNodes))
if self.nodeSelection(srcNode) and not duplicateFollowingNodes:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same, no notion of selection here.

# move nodes below the bounding box formed by the duplicated node(s)
bbox = self._layout.boundingBox(duplicates)
for n in duplicates:
self.moveNode(n, Position(n.x, bbox[3] + self.layout.gridSpacing + n.y))

return duplicates

@Slot(QObject)
def clearData(self, node):
if self.nodeSelection(node):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same, no notion of selection here.

def clearNodeSelection(self):
""" Clear node selection. """
self.selectedNode = None

@Slot()
def clearNodesSelections(self):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
def clearNodesSelections(self):
def clearNodesSelection(self):

for nodeName in self.duplicates:
self.graph.removeNode(nodeName)

class DuplicateNodeListCommand(_DuplicateNodes):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't need to have 2 classes to do it with one of multiple nodes and inheritance, etc.
Either we keep DuplicateNodeListCommand and always use it (even for a single node) or keep DuplicateNodeCommand and group the commands for multiple nodes.

@fabiencastan
Copy link
Member

Small behavior problem in this configuration (duplicate nodes and nodes behind):
image

It gives:
image

While the simple duplicate nodes:
image

Gives the correct result but with a strange selection:
image

@fabiencastan
Copy link
Member

It would be great the replace the "Alt+click" to select all the nodes after (instead of duplicating the nodes).
So if we want to move a node and all nodes connected behind it (a fairly common need), it would be simple.

@fabiencastan
Copy link
Member

Regarding the selection, I think we should clear the selection and select all the newly created nodes.

@fabiencastan
Copy link
Member

Really great PR, this is a life changer!
Looking forward to be able to merge it.

@ChemicalXandco
Copy link
Contributor Author

Small behavior problem in this configuration (duplicate nodes and nodes behind)

I agree that this does not behave right. Should I remove the options '_ from here' or should I rework them to include the other selected nodes? I think that removing those options and relying on alt + click to select the following nodes is more intuitive than having these options that operate on some nodes that are not selected. What do you think @fabiencastan?

@fabiencastan
Copy link
Member

Good question. I agree that's redundant and makes two ways to do the same.
But, on the other hand, I think it's still useful to have the "from here" option as it's visual and do not require to know the keyboard shortcuts.
Also alt/shift/ctrl can be problematic in remote, or on some linux alt could be used by the os to move the window, etc.

@natowi natowi mentioned this pull request Apr 16, 2021
@natowi
Copy link
Member

natowi commented Apr 20, 2021

Love it :)

demo

Only a few minor layout issues #1389 (nodes overlap and auto layout problems), but it might be too much for this PR

@fabiencastan
Copy link
Member

@ChemicalXandco Is it ready for review? Or are you still working on it?

@ChemicalXandco
Copy link
Contributor Author

It is ready

@fabiencastan fabiencastan added this to the Meshroom 2021.2.0 milestone May 3, 2021
@fabiencastan
Copy link
Member

Great work!

@fabiencastan fabiencastan merged commit 18be350 into alicevision:develop May 3, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature new feature (proposed as PR or issue planned by dev) UI
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants