Merge pull request #2604 from alicevision/dev/NodeColoring

[ui] Graph Editor Update: Quick Node Coloring with the Color Selector Tool
This commit is contained in:
Yann Lanthony 2024-11-29 11:16:25 +01:00 committed by GitHub
commit e800cd4e31
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 173 additions and 2 deletions

View file

@ -952,6 +952,20 @@ class UIGraph(QObject):
""" Select all the nodes the depend on 'node'. """ """ Select all the nodes the depend on 'node'. """
self.selectNodes(self._graph.dfsOnDiscover(startNodes=[node], reverse=True, dependenciesOnly=True)[0]) self.selectNodes(self._graph.dfsOnDiscover(startNodes=[node], reverse=True, dependenciesOnly=True)[0])
@Slot(str)
def setSelectedNodesColor(self, color: str):
""" Sets the Provided color on the selected Nodes.
Args:
color (str): Hex code of the color to be set on the nodes.
"""
# Update the color attribute of the nodes which are currently selected
with self.groupedGraphModification("Set Nodes Color"):
# For each of the selected nodes -> Check if the node has a color -> Apply the color if it has
for node in self._selectedNodes:
if node.hasInternalAttribute("color"):
self.setAttribute(node.internalAttribute("color"), color)
@Slot(QObject, QObject) @Slot(QObject, QObject)
def boxSelect(self, selection, draggable): def boxSelect(self, selection, draggable):
""" """

View file

@ -0,0 +1,133 @@
import QtQuick
import QtQuick.Controls
import Utils 1.0
import MaterialIcons 2.2
/**
* ColorSelector is a color picker based on a set of predefined colors.
* It takes the form of a ToolButton that pops-up its palette when pressed.
*/
MaterialToolButton {
id: root
text: MaterialIcons.palette
// Internal property holding when the popup remains visible and when is it toggled off
property var isVisible: false
property var colors: [
"#E35C03",
"#FFAD7D",
"#D0AE22",
"#C9C770",
"#3D6953",
"#79C62F",
"#02627E",
"#2CB9CC",
"#1453E6",
"#507DD0",
"#4D3E5C",
"#A252BD",
"#B61518",
"#C16162",
]
// When a color gets selected/choosen
signal colorSelected(var color)
// Toggles the visibility of the popup
onPressed: toggle()
function toggle() {
/*
* Toggles the visibility of the color palette.
*/
if (!isVisible) {
palettePopup.open()
isVisible = true
}
else {
palettePopup.close()
isVisible = false
}
}
// Popup for the color palette
Popup {
id: palettePopup
// The popup will not get closed unless explicitly closed
closePolicy: Popup.NoAutoClose
// Bounds
padding: 4
width: (root.height * 4) + (padding * 4)
// center the current color
y: -height
x: -width + root.width + padding
// Layout of the Colors
Grid {
// Allow only 4 columns and all the colors can be adjusted in row multiples of 4
columns: 4
spacing: 2
anchors.centerIn: parent
// Default -- Reset Colour button
ToolButton {
id: defaultButton
padding: 0
width: root.height
height: root.height
// Emit no color so the graph sets None as the color of the Node
onClicked: {
root.colorSelected("")
}
background: Rectangle {
color: "#FFFFFF"
// display border of current/selected item
border.width: defaultButton.hovered ? 1 : 0
border.color: "#000000"
// Another Rectangle
Rectangle {
color: "#FF0000"
width: parent.width + 8
height: 2
anchors.centerIn: parent
rotation: 135 // Diagonally creating a Red line from bottom left to top right
}
}
}
// Colors palette
Repeater {
model: root.colors
// display each color as a ToolButton with a custom background
delegate: ToolButton {
padding: 0
width: root.height
height: root.height
// Emit the model data as the color to update
onClicked: {
colorSelected(modelData)
}
// Model color as the background of the button
background: Rectangle {
color: modelData
// display border of current/selected item
border.width: hovered ? 1 : 0
border.color: "#000000"
}
}
}
}
}
}

View file

@ -1,6 +1,7 @@
module Controls module Controls
ColorChart 1.0 ColorChart.qml ColorChart 1.0 ColorChart.qml
ColorSelector 1.0 ColorSelector.qml
ExpandableGroup 1.0 ExpandableGroup.qml ExpandableGroup 1.0 ExpandableGroup.qml
FloatingPane 1.0 FloatingPane.qml FloatingPane 1.0 FloatingPane.qml
Group 1.0 Group.qml Group 1.0 Group.qml

View file

@ -147,8 +147,13 @@ Item {
} else if (event.key === Qt.Key_X && event.modifiers === Qt.ControlModifier) { } else if (event.key === Qt.Key_X && event.modifiers === Qt.ControlModifier) {
copyNodes() copyNodes()
uigraph.removeNodes(uigraph.selectedNodes) uigraph.removeNodes(uigraph.selectedNodes)
} else if (event.key === Qt.Key_C && event.modifiers === Qt.ControlModifier) { } else if (event.key === Qt.Key_C) {
if (event.modifiers === Qt.ControlModifier) {
copyNodes() copyNodes()
}
else {
colorSelector.toggle()
}
} else if (event.key === Qt.Key_V && event.modifiers === Qt.ControlModifier) { } else if (event.key === Qt.Key_V && event.modifiers === Qt.ControlModifier) {
pasteNodes() pasteNodes()
} else if (event.key === Qt.Key_Tab) { } else if (event.key === Qt.Key_Tab) {
@ -1048,6 +1053,24 @@ Item {
} }
} }
} }
// Separator
Rectangle {
Layout.fillHeight: true
Layout.margins: 2
implicitWidth: 1
color: activePalette.window
}
ColorSelector {
id: colorSelector
Layout.minimumWidth: colorSelector.width
// When a Color is selected
onColorSelected: (color)=> {
uigraph.setSelectedNodesColor(color)
}
}
} }
} }