[GraphEditor] Clean-up: Harmonize syntax across all files

This commit is contained in:
Candice Bentéjac 2023-10-17 15:42:14 +02:00
parent 2bdf061d2e
commit e9d80611c7
15 changed files with 341 additions and 375 deletions

View file

@ -31,7 +31,7 @@ ListView {
&& (object.isDefault && GraphEditorSettings.showDefaultAttributes || !object.isDefault && GraphEditorSettings.showModifiedAttributes) && (object.isDefault && GraphEditorSettings.showDefaultAttributes || !object.isDefault && GraphEditorSettings.showModifiedAttributes)
&& (object.isOutput && GraphEditorSettings.showOutputAttributes || !object.isOutput && GraphEditorSettings.showInputAttributes) && (object.isOutput && GraphEditorSettings.showOutputAttributes || !object.isOutput && GraphEditorSettings.showInputAttributes)
&& (object.isLinkNested && GraphEditorSettings.showLinkAttributes || !object.isLink && GraphEditorSettings.showNotLinkAttributes)) && (object.isLinkNested && GraphEditorSettings.showLinkAttributes || !object.isLink && GraphEditorSettings.showNotLinkAttributes))
) && object.matchText(filterText) ) && object.matchText(filterText)
visible: active visible: active
sourceComponent: AttributeItemDelegate { sourceComponent: AttributeItemDelegate {

View file

@ -25,8 +25,7 @@ RowLayout {
spacing: 2 spacing: 2
function updateAttributeLabel() function updateAttributeLabel() {
{
background.color = attribute.validValue ? Qt.darker(palette.window, 1.1) : Qt.darker(Colors.red, 1.5) background.color = attribute.validValue ? Qt.darker(palette.window, 1.1) : Qt.darker(Colors.red, 1.5)
if (attribute.desc) { if (attribute.desc) {
@ -40,7 +39,10 @@ RowLayout {
} }
Pane { Pane {
background: Rectangle { id: background; color: object.validValue ? Qt.darker(parent.palette.window, 1.1) : Qt.darker(Colors.red, 1.5) } background: Rectangle {
id: background
color: object.validValue ? Qt.darker(parent.palette.window, 1.1) : Qt.darker(Colors.red, 1.5)
}
padding: 0 padding: 0
Layout.preferredWidth: labelWidth || implicitWidth Layout.preferredWidth: labelWidth || implicitWidth
Layout.fillHeight: true Layout.fillHeight: true
@ -128,8 +130,7 @@ RowLayout {
onClicked: { onClicked: {
forceActiveFocus() forceActiveFocus()
if(mouse.button == Qt.RightButton) if (mouse.button == Qt.RightButton) {
{
var menu = menuComp.createObject(parameterLabel) var menu = menuComp.createObject(parameterLabel)
menu.parent = parameterLabel menu.parent = parameterLabel
menu.popup() menu.popup()
@ -147,25 +148,23 @@ RowLayout {
} }
} }
function setTextFieldAttribute(value) function setTextFieldAttribute(value) {
{
// editingFinished called even when TextField is readonly // editingFinished called even when TextField is readonly
if(!editable) if (!editable)
return return
switch(attribute.type) switch (attribute.type) {
{ case "IntParam":
case "IntParam": case "FloatParam":
case "FloatParam": _reconstruction.setAttribute(root.attribute, Number(value))
_reconstruction.setAttribute(root.attribute, Number(value)) updateAttributeLabel()
updateAttributeLabel() break
break; case "File":
case "File": _reconstruction.setAttribute(root.attribute, value)
_reconstruction.setAttribute(root.attribute, value) break
break; default:
default: _reconstruction.setAttribute(root.attribute, value.trim())
_reconstruction.setAttribute(root.attribute, value.trim()) updateAttributeLabel()
updateAttributeLabel() break
break;
} }
} }
@ -173,24 +172,28 @@ RowLayout {
Layout.fillWidth: true Layout.fillWidth: true
sourceComponent: { sourceComponent: {
switch(attribute.type) switch (attribute.type) {
{ case "ChoiceParam":
case "ChoiceParam": return attribute.desc.exclusive ? comboBox_component : multiChoice_component return attribute.desc.exclusive ? comboBox_component : multiChoice_component
case "IntParam": return slider_component case "IntParam": return slider_component
case "FloatParam": case "FloatParam":
if(attribute.desc.semantic === 'color/hue') if (attribute.desc.semantic === 'color/hue')
return color_hue_component return color_hue_component
return slider_component return slider_component
case "BoolParam": return checkbox_component case "BoolParam":
case "ListAttribute": return listAttribute_component return checkbox_component
case "GroupAttribute": return groupAttribute_component case "ListAttribute":
case "StringParam": return listAttribute_component
if (attribute.desc.semantic === 'multiline') case "GroupAttribute":
return textArea_component return groupAttribute_component
return textField_component case "StringParam":
case "ColorParam": if (attribute.desc.semantic === 'multiline')
return color_component return textArea_component
default: return textField_component return textField_component
case "ColorParam":
return color_component
default:
return textField_component
} }
} }
@ -206,16 +209,16 @@ RowLayout {
root.forceActiveFocus() root.forceActiveFocus()
} }
Component.onDestruction: { Component.onDestruction: {
if(activeFocus) if (activeFocus)
setTextFieldAttribute(text) setTextFieldAttribute(text)
} }
DropArea { DropArea {
enabled: root.editable enabled: root.editable
anchors.fill: parent anchors.fill: parent
onDropped: { onDropped: {
if(drop.hasUrls) if (drop.hasUrls)
setTextFieldAttribute(Filepath.urlToString(drop.urls[0])) setTextFieldAttribute(Filepath.urlToString(drop.urls[0]))
else if(drop.hasText && drop.text != '') else if (drop.hasText && drop.text != '')
setTextFieldAttribute(drop.text) setTextFieldAttribute(drop.text)
} }
} }
@ -282,7 +285,7 @@ RowLayout {
checked: node && node.color === "" ? false : true checked: node && node.color === "" ? false : true
text: "Custom Color" text: "Custom Color"
onClicked: { onClicked: {
if(checked) { if (checked) {
_reconstruction.setAttribute(attribute, "#0000FF") _reconstruction.setAttribute(attribute, "#0000FF")
} else { } else {
_reconstruction.setAttribute(attribute, "") _reconstruction.setAttribute(attribute, "")
@ -300,7 +303,7 @@ RowLayout {
onEditingFinished: setTextFieldAttribute(text) onEditingFinished: setTextFieldAttribute(text)
onAccepted: setTextFieldAttribute(text) onAccepted: setTextFieldAttribute(text)
Component.onDestruction: { Component.onDestruction: {
if(activeFocus) if (activeFocus)
setTextFieldAttribute(text) setTextFieldAttribute(text)
} }
} }
@ -366,8 +369,11 @@ RowLayout {
checked: attribute.value.indexOf(modelData) >= 0 checked: attribute.value.indexOf(modelData) >= 0
onToggled: { onToggled: {
var t = attribute.value var t = attribute.value
if(!checked) { t.splice(t.indexOf(modelData), 1) } // remove element if (!checked) {
else { t.push(modelData) } // add element t.splice(t.indexOf(modelData), 1) // remove element
} else {
t.push(modelData) // add element
}
_reconstruction.setAttribute(attribute, t) _reconstruction.setAttribute(attribute, t)
} }
} }
@ -397,7 +403,7 @@ RowLayout {
// When the value change keep the text align to the left to be able to read the most important part // When the value change keep the text align to the left to be able to read the most important part
// of the number. When we are editing (item is in focus), the content should follow the editing. // of the number. When we are editing (item is in focus), the content should follow the editing.
autoScroll: activeFocus autoScroll: activeFocus
validator: attribute.type == "FloatParam" ? doubleValidator : intValidator validator: attribute.type === "FloatParam" ? doubleValidator : intValidator
onEditingFinished: setTextFieldAttribute(text) onEditingFinished: setTextFieldAttribute(text)
onAccepted: { onAccepted: {
setTextFieldAttribute(text) setTextFieldAttribute(text)
@ -407,7 +413,7 @@ RowLayout {
ensureVisible(0) ensureVisible(0)
} }
Component.onDestruction: { Component.onDestruction: {
if(activeFocus) if (activeFocus)
setTextFieldAttribute(text) setTextFieldAttribute(text)
} }
Component.onCompleted: { Component.onCompleted: {
@ -482,7 +488,7 @@ RowLayout {
ListView { ListView {
id: lv id: lv
model: listAttribute_layout.expanded ? attribute.value : undefined model: listAttribute_layout.expanded ? attribute.value : undefined
visible: model != undefined && count > 0 visible: model !== undefined && count > 0
implicitHeight: Math.min(contentHeight, 300) implicitHeight: Math.min(contentHeight, 300)
Layout.fillWidth: true Layout.fillWidth: true
Layout.margins: 4 Layout.margins: 4
@ -491,7 +497,7 @@ RowLayout {
ScrollBar.vertical: ScrollBar { id: sb } ScrollBar.vertical: ScrollBar { id: sb }
delegate: Loader{ delegate: Loader {
active: !objectsHideable active: !objectsHideable
|| ((object.isDefault && GraphEditorSettings.showDefaultAttributes || !object.isDefault && GraphEditorSettings.showModifiedAttributes) || ((object.isDefault && GraphEditorSettings.showDefaultAttributes || !object.isDefault && GraphEditorSettings.showModifiedAttributes)
&& (object.isLinkNested && GraphEditorSettings.showLinkAttributes || !object.isLinkNested && GraphEditorSettings.showNotLinkAttributes)) && (object.isLinkNested && GraphEditorSettings.showLinkAttributes || !object.isLinkNested && GraphEditorSettings.showNotLinkAttributes))
@ -505,14 +511,15 @@ RowLayout {
Component.onCompleted: { Component.onCompleted: {
var cpt = Qt.createComponent("AttributeItemDelegate.qml") var cpt = Qt.createComponent("AttributeItemDelegate.qml")
var obj = cpt.createObject(item, var obj = cpt.createObject(item,
{'attribute': Qt.binding(function() { return item.childAttrib }), {
'attribute': Qt.binding(function() { return item.childAttrib }),
'readOnly': Qt.binding(function() { return !root.editable }) 'readOnly': Qt.binding(function() { return !root.editable })
}) })
obj.Layout.fillWidth = true obj.Layout.fillWidth = true
obj.label.text = index obj.label.text = index
obj.label.horizontalAlignment = Text.AlignHCenter obj.label.horizontalAlignment = Text.AlignHCenter
obj.label.verticalAlignment = Text.AlignVCenter obj.label.verticalAlignment = Text.AlignVCenter
obj.doubleClicked.connect(function(attr) {root.doubleClicked(attr)}) obj.doubleClicked.connect(function(attr) { root.doubleClicked(attr) })
} }
ToolButton { ToolButton {
enabled: root.editable enabled: root.editable
@ -537,11 +544,12 @@ RowLayout {
Component.onCompleted: { Component.onCompleted: {
var cpt = Qt.createComponent("AttributeEditor.qml"); var cpt = Qt.createComponent("AttributeEditor.qml");
var obj = cpt.createObject(groupItem, var obj = cpt.createObject(groupItem,
{'model': Qt.binding(function() { return attribute.value }), {
'readOnly': Qt.binding(function() { return root.readOnly }), 'model': Qt.binding(function() { return attribute.value }),
'labelWidth': 100, // reduce label width for children (space gain) 'readOnly': Qt.binding(function() { return root.readOnly }),
'objectsHideable': Qt.binding(function() { return root.objectsHideable }), 'labelWidth': 100, // reduce label width for children (space gain)
'filterText': Qt.binding(function() { return root.filterText }), 'objectsHideable': Qt.binding(function() { return root.objectsHideable }),
'filterText': Qt.binding(function() { return root.filterText }),
}) })
obj.Layout.fillWidth = true; obj.Layout.fillWidth = true;
obj.attributeDoubleClicked.connect(function(attr) {root.doubleClicked(attr)}) obj.attributeDoubleClicked.connect(function(attr) {root.doubleClicked(attr)})
@ -565,7 +573,7 @@ RowLayout {
onEditingFinished: setTextFieldAttribute(text) onEditingFinished: setTextFieldAttribute(text)
onAccepted: setTextFieldAttribute(text) onAccepted: setTextFieldAttribute(text)
Component.onDestruction: { Component.onDestruction: {
if(activeFocus) if (activeFocus)
setTextFieldAttribute(text) setTextFieldAttribute(text)
} }
} }
@ -575,9 +583,9 @@ RowLayout {
color: Qt.hsla(slider.pressed ? slider.formattedValue : attribute.value, 1, 0.5, 1) color: Qt.hsla(slider.pressed ? slider.formattedValue : attribute.value, 1, 0.5, 1)
} }
Slider { Slider {
id: slider
Layout.fillWidth: true Layout.fillWidth: true
id: slider
readonly property int stepDecimalCount: 2 readonly property int stepDecimalCount: 2
readonly property real formattedValue: value.toFixed(stepDecimalCount) readonly property real formattedValue: value.toFixed(stepDecimalCount)
enabled: root.editable enabled: root.editable
@ -587,7 +595,7 @@ RowLayout {
stepSize: 0.01 stepSize: 0.01
snapMode: Slider.SnapAlways snapMode: Slider.SnapAlways
onPressedChanged: { onPressedChanged: {
if(!pressed) if (!pressed)
_reconstruction.setAttribute(attribute, formattedValue) _reconstruction.setAttribute(attribute, formattedValue)
} }

View file

@ -17,11 +17,11 @@ RowLayout {
property bool displayOutputPinForInput: true property bool displayOutputPinForInput: true
// position of the anchor for attaching and edge to this attribute pin // position of the anchor for attaching and edge to this attribute pin
readonly property point inputAnchorPos: Qt.point(inputAnchor.x + inputAnchor.width/2, readonly property point inputAnchorPos: Qt.point(inputAnchor.x + inputAnchor.width / 2,
inputAnchor.y + inputAnchor.height/2) inputAnchor.y + inputAnchor.height / 2)
readonly property point outputAnchorPos: Qt.point(outputAnchor.x + outputAnchor.width/2, readonly property point outputAnchorPos: Qt.point(outputAnchor.x + outputAnchor.width / 2,
outputAnchor.y + outputAnchor.height/2) outputAnchor.y + outputAnchor.height / 2)
readonly property bool isList: attribute && attribute.type === "ListAttribute" readonly property bool isList: attribute && attribute.type === "ListAttribute"
@ -39,8 +39,8 @@ RowLayout {
Repeater { Repeater {
id: childrenRepeater id: childrenRepeater
model: isList && !attribute.isLink ? attribute.value : 0 model: isList && !attribute.isLink ? attribute.value : 0
onItemAdded: {childPinCreated(item.childAttribute, item)} onItemAdded: childPinCreated(item.childAttribute, item)
onItemRemoved: {childPinDeleted(item.childAttribute, item)} onItemRemoved: childPinDeleted(item.childAttribute, item)
delegate: Item { delegate: Item {
property var childAttribute: object property var childAttribute: object
} }
@ -52,10 +52,10 @@ RowLayout {
width: 8 width: 8
height: width height: width
radius: isList ? 0 : width/2 radius: isList ? 0 : width / 2
Layout.alignment: Qt.AlignVCenter Layout.alignment: Qt.AlignVCenter
border.color: Colors.sysPalette.mid border.color: Colors.sysPalette.mid
color: Colors.sysPalette.base color: Colors.sysPalette.base
Rectangle { Rectangle {
@ -64,7 +64,7 @@ RowLayout {
anchors.fill: parent anchors.fill: parent
anchors.margins: 2 anchors.margins: 2
color: { color: {
if(inputConnectMA.containsMouse || inputConnectMA.drag.active || (inputDropArea.containsDrag && inputDropArea.acceptableDrop)) if (inputConnectMA.containsMouse || inputConnectMA.drag.active || (inputDropArea.containsDrag && inputDropArea.acceptableDrop))
return Colors.sysPalette.highlight return Colors.sysPalette.highlight
return Colors.sysPalette.text return Colors.sysPalette.text
} }
@ -84,19 +84,17 @@ RowLayout {
keys: [inputDragTarget.objectName] keys: [inputDragTarget.objectName]
onEntered: { onEntered: {
// Check if attributes are compatible to create a valid connection // Check if attributes are compatible to create a valid connection
if( root.readOnly // cannot connect on a read-only attribute if (root.readOnly // cannot connect on a read-only attribute
|| drag.source.objectName != inputDragTarget.objectName // not an edge connector || drag.source.objectName != inputDragTarget.objectName // not an edge connector
|| drag.source.baseType !== inputDragTarget.baseType // not the same base type || drag.source.baseType !== inputDragTarget.baseType // not the same base type
|| drag.source.nodeItem === inputDragTarget.nodeItem // connection between attributes of the same node || drag.source.nodeItem === inputDragTarget.nodeItem // connection between attributes of the same node
|| (drag.source.isList && !inputDragTarget.isList) // connection between a list and a simple attribute || (drag.source.isList && !inputDragTarget.isList) // connection between a list and a simple attribute
|| (drag.source.isList && childrenRepeater.count) // source/target are lists but target already has children || (drag.source.isList && childrenRepeater.count) // source/target are lists but target already has children
|| drag.source.connectorType === "input" // refuse to connect an "input pin" on another one (input attr can be connected to input attr, but not the graphical pin) || drag.source.connectorType === "input" // refuse to connect an "input pin" on another one (input attr can be connected to input attr, but not the graphical pin)
) ) {
{
// Refuse attributes connection // Refuse attributes connection
drag.accepted = false drag.accepted = false
} } else if (inputDragTarget.attribute.isLink) { // already connected attribute
else if (inputDragTarget.attribute.isLink) { // already connected attribute
root.edgeAboutToBeRemoved(inputDragTarget.attribute) root.edgeAboutToBeRemoved(inputDragTarget.attribute)
} }
inputDropArea.acceptableDrop = drag.accepted inputDropArea.acceptableDrop = drag.accepted
@ -159,8 +157,8 @@ RowLayout {
Edge { Edge {
id: inputConnectEdge id: inputConnectEdge
visible: false visible: false
point1x: inputDragTarget.x + inputDragTarget.width/2 point1x: inputDragTarget.x + inputDragTarget.width / 2
point1y: inputDragTarget.y + inputDragTarget.height/2 point1y: inputDragTarget.y + inputDragTarget.height / 2
point2x: parent.width / 2 point2x: parent.width / 2
point2y: parent.width / 2 point2y: parent.width / 2
color: palette.highlight color: palette.highlight
@ -214,7 +212,7 @@ RowLayout {
anchors.fill: parent anchors.fill: parent
anchors.margins: 2 anchors.margins: 2
color: { color: {
if(outputConnectMA.containsMouse || outputConnectMA.drag.active || (outputDropArea.containsDrag && outputDropArea.acceptableDrop)) if (outputConnectMA.containsMouse || outputConnectMA.drag.active || (outputDropArea.containsDrag && outputDropArea.acceptableDrop))
return Colors.sysPalette.highlight return Colors.sysPalette.highlight
return Colors.sysPalette.text return Colors.sysPalette.text
} }
@ -234,18 +232,16 @@ RowLayout {
keys: [outputDragTarget.objectName] keys: [outputDragTarget.objectName]
onEntered: { onEntered: {
// Check if attributes are compatible to create a valid connection // Check if attributes are compatible to create a valid connection
if( drag.source.objectName != outputDragTarget.objectName // not an edge connector if (drag.source.objectName != outputDragTarget.objectName // not an edge connector
|| drag.source.baseType !== outputDragTarget.baseType // not the same base type || drag.source.baseType !== outputDragTarget.baseType // not the same base type
|| drag.source.nodeItem === outputDragTarget.nodeItem // connection between attributes of the same node || drag.source.nodeItem === outputDragTarget.nodeItem // connection between attributes of the same node
|| (!drag.source.isList && outputDragTarget.isList) // connection between a list and a simple attribute || (!drag.source.isList && outputDragTarget.isList) // connection between a list and a simple attribute
|| (drag.source.isList && childrenRepeater.count) // source/target are lists but target already has children || (drag.source.isList && childrenRepeater.count) // source/target are lists but target already has children
|| drag.source.connectorType === "output" // refuse to connect an output pin on another one || drag.source.connectorType === "output" // refuse to connect an output pin on another one
) ) {
{
// Refuse attributes connection // Refuse attributes connection
drag.accepted = false drag.accepted = false
} } else if (drag.source.attribute.isLink) { // already connected attribute
else if (drag.source.attribute.isLink) { // already connected attribute
root.edgeAboutToBeRemoved(drag.source.attribute) root.edgeAboutToBeRemoved(drag.source.attribute)
} }
outputDropArea.acceptableDrop = drag.accepted outputDropArea.acceptableDrop = drag.accepted
@ -277,8 +273,8 @@ RowLayout {
height: parent.height height: parent.height
Drag.keys: [outputDragTarget.objectName] Drag.keys: [outputDragTarget.objectName]
Drag.active: outputConnectMA.drag.active Drag.active: outputConnectMA.drag.active
Drag.hotSpot.x: width*0.5 Drag.hotSpot.x: width * 0.5
Drag.hotSpot.y: height*0.5 Drag.hotSpot.y: height * 0.5
} }
MouseArea { MouseArea {
@ -304,8 +300,8 @@ RowLayout {
visible: false visible: false
point1x: parent.width / 2 point1x: parent.width / 2
point1y: parent.width / 2 point1y: parent.width / 2
point2x: outputDragTarget.x + outputDragTarget.width/2 point2x: outputDragTarget.x + outputDragTarget.width / 2
point2y: outputDragTarget.y + outputDragTarget.height/2 point2y: outputDragTarget.y + outputDragTarget.height / 2
color: palette.highlight color: palette.highlight
thickness: outputDragTarget.dropAccepted ? 2 : 1 thickness: outputDragTarget.dropAccepted ? 2 : 1
} }
@ -354,8 +350,8 @@ RowLayout {
script: { script: {
// Add the right offset if the initial click is not exactly at the center of the connection circle. // Add the right offset if the initial click is not exactly at the center of the connection circle.
var pos = inputDragTarget.mapFromItem(inputConnectMA, inputConnectMA.mouseX, inputConnectMA.mouseY); var pos = inputDragTarget.mapFromItem(inputConnectMA, inputConnectMA.mouseX, inputConnectMA.mouseY);
inputDragTarget.x = pos.x - inputDragTarget.width/2; inputDragTarget.x = pos.x - inputDragTarget.width / 2;
inputDragTarget.y = pos.y - inputDragTarget.height/2; inputDragTarget.y = pos.y - inputDragTarget.height / 2;
} }
} }
}, },
@ -374,11 +370,10 @@ RowLayout {
StateChangeScript { StateChangeScript {
script: { script: {
var pos = outputDragTarget.mapFromItem(outputConnectMA, outputConnectMA.mouseX, outputConnectMA.mouseY); var pos = outputDragTarget.mapFromItem(outputConnectMA, outputConnectMA.mouseX, outputConnectMA.mouseY);
outputDragTarget.x = pos.x - outputDragTarget.width/2; outputDragTarget.x = pos.x - outputDragTarget.width / 2;
outputDragTarget.y = pos.y - outputDragTarget.height/2; outputDragTarget.y = pos.y - outputDragTarget.height / 2;
} }
} }
} }
] ]
} }

View file

@ -18,7 +18,7 @@ ColumnLayout {
onChunksChanged: { onChunksChanged: {
// When the list changes, ensure the current index is in the new range // When the list changes, ensure the current index is in the new range
if(currentIndex >= chunks.count) if (currentIndex >= chunks.count)
currentIndex = chunks.count-1 currentIndex = chunks.count-1
} }
@ -39,8 +39,7 @@ ColumnLayout {
focus: true focus: true
currentIndex: root.currentIndex currentIndex: root.currentIndex
onCurrentIndexChanged: { onCurrentIndexChanged: {
if(chunksLV.currentIndex !== root.currentIndex) if (chunksLV.currentIndex !== root.currentIndex) {
{
// When the list is resized, the currentIndex is reset to 0. // When the list is resized, the currentIndex is reset to 0.
// So here we force it to keep the binding. // So here we force it to keep the binding.
chunksLV.currentIndex = Qt.binding(function() { return root.currentIndex }) chunksLV.currentIndex = Qt.binding(function() { return root.currentIndex })
@ -67,7 +66,7 @@ ColumnLayout {
} }
highlight: Component { highlight: Component {
Rectangle { Rectangle {
visible: true // !root.chunksSummary visible: true // !root.chunksSummary
color: activePalette.highlight color: activePalette.highlight
opacity: 0.3 opacity: 0.3
z: 2 z: 2

View file

@ -23,7 +23,6 @@ Loader {
property Component iconDelegate: Component { property Component iconDelegate: Component {
Label { Label {
text: MaterialIcons.warning text: MaterialIcons.warning
font.family: MaterialIcons.fontFamily font.family: MaterialIcons.fontFamily
font.pointSize: 12 font.pointSize: 12
@ -74,6 +73,5 @@ Loader {
} }
} }
} }
} }
} }

View file

@ -20,9 +20,8 @@ MessageDialog {
// the number of CompatibilityNodes that can be upgraded // the number of CompatibilityNodes that can be upgraded
readonly property int upgradableCount: { readonly property int upgradableCount: {
var count = 0 var count = 0
for(var i=0; i<issueCount; ++i) for (var i = 0; i < issueCount; ++i) {
{ if (nodesModel.at(i).canUpgrade)
if(nodesModel.at(i).canUpgrade)
count++; count++;
} }
return count return count
@ -34,8 +33,7 @@ MessageDialog {
t += '-------------------------\n' t += '-------------------------\n'
t += "Node | Issue | Upgradable\n" t += "Node | Issue | Upgradable\n"
t += '-------------------------\n' t += '-------------------------\n'
for(var i=0; i<issueCount; ++i) for (var i = 0; i < issueCount; ++i) {
{
var n = nodesModel.at(i) var n = nodesModel.at(i)
t += n.nodeType + " | " + n.issueDetails + " | " + n.canUpgrade + "\n" t += n.nodeType + " | " + n.issueDetails + " | " + n.canUpgrade + "\n"
} }
@ -108,7 +106,6 @@ MessageDialog {
font.bold: true font.bold: true
} }
} }
} }
Label { Label {
@ -126,11 +123,9 @@ MessageDialog {
} }
onAccepted: { onAccepted: {
if(upgradableCount) if (upgradableCount) {
{
uigraph.upgradeAllNodes() uigraph.upgradeAllNodes()
upgradeDone() upgradeDone()
} }
} }
} }

View file

@ -45,7 +45,7 @@ Shape {
strokeWidth: 1 strokeWidth: 1
// final visual width of this path (never below 1) // final visual width of this path (never below 1)
readonly property real visualWidth: Math.max(strokeWidth, 1) readonly property real visualWidth: Math.max(strokeWidth, 1)
dashPattern: [6/visualWidth, 4/visualWidth] dashPattern: [6 / visualWidth, 4 / visualWidth]
capStyle: ShapePath.RoundCap capStyle: ShapePath.RoundCap
PathCubic { PathCubic {
@ -53,8 +53,10 @@ Shape {
property real ctrlPtDist: 30 property real ctrlPtDist: 30
x: root.endX x: root.endX
y: root.endY y: root.endY
relativeControl1X: ctrlPtDist; relativeControl1Y: 0 relativeControl1X: ctrlPtDist
control2X: x - ctrlPtDist; control2Y: y relativeControl1Y: 0
control2X: x - ctrlPtDist
control2Y: y
} }
} }

View file

@ -45,19 +45,16 @@ Item {
SystemPalette { id: activePalette } SystemPalette { id: activePalette }
/// Get node delegate for the given node object /// Get node delegate for the given node object
function nodeDelegate(node) function nodeDelegate(node) {
{ for(var i = 0; i < nodeRepeater.count; ++i) {
for(var i=0; i<nodeRepeater.count; ++i) if (nodeRepeater.itemAt(i).node === node)
{
if(nodeRepeater.itemAt(i).node === node)
return nodeRepeater.itemAt(i) return nodeRepeater.itemAt(i)
} }
return undefined return undefined
} }
/// Select node delegate /// Select node delegate
function selectNode(node) function selectNode(node) {
{
uigraph.selectedNode = node uigraph.selectedNode = node
if (node !== null) { if (node !== null) {
uigraph.appendSelection(node) uigraph.appendSelection(node)
@ -79,8 +76,7 @@ Item {
} }
/// Copy node content to clipboard /// Copy node content to clipboard
function copyNodes() function copyNodes() {
{
var nodeContent = uigraph.getSelectedNodesContent() var nodeContent = uigraph.getSelectedNodesContent()
if (nodeContent !== '') { if (nodeContent !== '') {
Clipboard.clear() Clipboard.clear()
@ -89,8 +85,7 @@ Item {
} }
/// Paste content of clipboard to graph editor and create new node if valid /// Paste content of clipboard to graph editor and create new node if valid
function pasteNodes() function pasteNodes() {
{
var finalPosition = undefined var finalPosition = undefined
var centerPosition = false var centerPosition = false
if (mouseArea.containsMouse) { if (mouseArea.containsMouse) {
@ -115,37 +110,30 @@ Item {
} }
/// Get the coordinates of the point at the center of the GraphEditor /// Get the coordinates of the point at the center of the GraphEditor
function getCenterPosition() function getCenterPosition() {
{
return mapToItem(draggable, mouseArea.width / 2, mouseArea.height / 2) return mapToItem(draggable, mouseArea.width / 2, mouseArea.height / 2)
} }
Keys.onPressed: { Keys.onPressed: {
if (event.key === Qt.Key_F) { if (event.key === Qt.Key_F) {
fit(); fit()
} } else if (event.key === Qt.Key_Delete) {
else if (event.key === Qt.Key_Delete) {
if (event.modifiers === Qt.AltModifier) { if (event.modifiers === Qt.AltModifier) {
uigraph.removeNodesFrom(uigraph.selectedNodes); uigraph.removeNodesFrom(uigraph.selectedNodes)
} else {
uigraph.removeNodes(uigraph.selectedNodes)
} }
else { } else if (event.key === Qt.Key_D) {
uigraph.removeNodes(uigraph.selectedNodes); duplicateNode(event.modifiers === Qt.AltModifier)
} } else if (event.key === Qt.Key_C && event.modifiers === Qt.ControlModifier) {
} copyNodes()
else if (event.key === Qt.Key_D) { } else if (event.key === Qt.Key_V && event.modifiers === Qt.ControlModifier) {
duplicateNode(event.modifiers === Qt.AltModifier); pasteNodes()
} } else if (event.key === Qt.Key_Tab) {
else if (event.key === Qt.Key_C && event.modifiers === Qt.ControlModifier) { event.accepted = true
copyNodes();
}
else if (event.key === Qt.Key_V && event.modifiers === Qt.ControlModifier) {
pasteNodes();
}
else if (event.key === Qt.Key_Tab) {
event.accepted = true;
if (mouseArea.containsMouse) { if (mouseArea.containsMouse) {
newNodeMenu.spawnPosition = mouseArea.mapToItem(draggable, mouseArea.mouseX, mouseArea.mouseY); newNodeMenu.spawnPosition = mouseArea.mapToItem(draggable, mouseArea.mouseX, mouseArea.mouseY)
newNodeMenu.popup(); newNodeMenu.popup()
} }
} }
} }
@ -164,14 +152,14 @@ Item {
cursorShape: drag.target == draggable ? Qt.ClosedHandCursor : Qt.ArrowCursor cursorShape: drag.target == draggable ? Qt.ClosedHandCursor : Qt.ArrowCursor
onWheel: { onWheel: {
var zoomFactor = wheel.angleDelta.y > 0 ? factor : 1/factor var zoomFactor = wheel.angleDelta.y > 0 ? factor : 1 / factor
var scale = draggable.scale * zoomFactor var scale = draggable.scale * zoomFactor
scale = Math.min(Math.max(minZoom, scale), maxZoom) scale = Math.min(Math.max(minZoom, scale), maxZoom)
if(draggable.scale == scale) if (draggable.scale == scale)
return return
var point = mapToItem(draggable, wheel.x, wheel.y) var point = mapToItem(draggable, wheel.x, wheel.y)
draggable.x += (1-zoomFactor) * point.x * draggable.scale draggable.x += (1 - zoomFactor) * point.x * draggable.scale
draggable.y += (1-zoomFactor) * point.y * draggable.scale draggable.y += (1 - zoomFactor) * point.y * draggable.scale
draggable.scale = scale draggable.scale = scale
workspaceMoved() workspaceMoved()
} }
@ -197,16 +185,15 @@ Item {
workspaceClicked() workspaceClicked()
} }
onPositionChanged: { onPositionChanged: {
if(drag.active) if (drag.active)
workspaceMoved() workspaceMoved()
} }
onClicked: { onClicked: {
if(mouse.button == Qt.RightButton) if (mouse.button == Qt.RightButton) {
{
// store mouse click position in 'draggable' coordinates as new node spawn position // store mouse click position in 'draggable' coordinates as new node spawn position
newNodeMenu.spawnPosition = mouseArea.mapToItem(draggable, mouse.x, mouse.y); newNodeMenu.spawnPosition = mouseArea.mapToItem(draggable, mouse.x, mouse.y)
newNodeMenu.popup(); newNodeMenu.popup()
} }
} }
@ -217,8 +204,7 @@ Item {
property point spawnPosition property point spawnPosition
property variant menuKeys: Object.keys(root.nodeTypesModel).concat(Object.values(MeshroomApp.pipelineTemplateNames)) property variant menuKeys: Object.keys(root.nodeTypesModel).concat(Object.values(MeshroomApp.pipelineTemplateNames))
function createNode(nodeType) function createNode(nodeType) {
{
uigraph.clearNodeSelection() // Ensures that only the created node / imported pipeline will be selected uigraph.clearNodeSelection() // Ensures that only the created node / imported pipeline will be selected
// "nodeType" might be a pipeline (artificially added in the "Pipelines" category) instead of a node // "nodeType" might be a pipeline (artificially added in the "Pipelines" category) instead of a node
@ -231,8 +217,7 @@ Item {
close() close()
} }
function importPipeline(pipeline) function importPipeline(pipeline) {
{
if (MeshroomApp.pipelineTemplateNames.includes(pipeline)) { if (MeshroomApp.pipelineTemplateNames.includes(pipeline)) {
var url = MeshroomApp.pipelineTemplateFiles[MeshroomApp.pipelineTemplateNames.indexOf(pipeline)]["path"] var url = MeshroomApp.pipelineTemplateFiles[MeshroomApp.pipelineTemplateNames.indexOf(pipeline)]["path"]
var nodes = uigraph.importProject(Filepath.stringToUrl(url), spawnPosition) var nodes = uigraph.importProject(Filepath.stringToUrl(url), spawnPosition)
@ -243,21 +228,20 @@ Item {
return false return false
} }
function parseCategories() function parseCategories() {
{
// Organize nodes based on their category // Organize nodes based on their category
// {"category1": ["node1", "node2"], "category2": ["node3", "node4"]} // {"category1": ["node1", "node2"], "category2": ["node3", "node4"]}
let categories = {}; let categories = {};
for (const [name, data] of Object.entries(root.nodeTypesModel)) { for (const [name, data] of Object.entries(root.nodeTypesModel)) {
let category = data["category"]; let category = data["category"];
if (categories[category] === undefined) { if (categories[category] === undefined) {
categories[category] = []; categories[category] = []
} }
categories[category].push(name) categories[category].push(name)
} }
// Add a "Pipelines" category, filled with the list of templates to create pipelines from the menu // Add a "Pipelines" category, filled with the list of templates to create pipelines from the menu
categories["Pipelines"] = MeshroomApp.pipelineTemplateNames; categories["Pipelines"] = MeshroomApp.pipelineTemplateNames
return categories return categories
} }
@ -287,27 +271,27 @@ Item {
// Hide items that does not match the filter text // Hide items that does not match the filter text
visible: modelData.toLowerCase().indexOf(searchBar.text.toLowerCase()) > -1 visible: modelData.toLowerCase().indexOf(searchBar.text.toLowerCase()) > -1
// Reset menu currentIndex if highlighted items gets filtered out // Reset menu currentIndex if highlighted items gets filtered out
onVisibleChanged: if(highlighted) newNodeMenu.currentIndex = 0 onVisibleChanged: if (highlighted) newNodeMenu.currentIndex = 0
text: modelData text: modelData
// Forward key events to the search bar to continue typing seamlessly // Forward key events to the search bar to continue typing seamlessly
// even if this delegate took the activeFocus due to mouse hovering // even if this delegate took the activeFocus due to mouse hovering
Keys.forwardTo: [searchBar.textField] Keys.forwardTo: [searchBar.textField]
Keys.onPressed: { Keys.onPressed: {
event.accepted = false; event.accepted = false;
switch(event.key) { switch (event.key) {
case Qt.Key_Return: case Qt.Key_Return:
case Qt.Key_Enter: case Qt.Key_Enter:
// create node on validation (Enter/Return keys) // create node on validation (Enter/Return keys)
newNodeMenu.createNode(modelData); newNodeMenu.createNode(modelData)
event.accepted = true; event.accepted = true
break; break
case Qt.Key_Up: case Qt.Key_Up:
case Qt.Key_Down: case Qt.Key_Down:
case Qt.Key_Left: case Qt.Key_Left:
case Qt.Key_Right: case Qt.Key_Right:
break; // ignore if arrow key was pressed to let the menu be controlled break // ignore if arrow key was pressed to let the menu be controlled
default: default:
searchBar.forceActiveFocus(); searchBar.forceActiveFocus()
} }
} }
// Create node on mouse click // Create node on mouse click
@ -339,7 +323,7 @@ Item {
// Dynamically add the menu categories // Dynamically add the menu categories
Instantiator { Instantiator {
model: !(searchBar.text !== "") ? Object.keys(newNodeMenu.parseCategories()).sort() : undefined model: !(searchBar.text !== "") ? Object.keys(newNodeMenu.parseCategories()).sort() : undefined
onObjectAdded: newNodeMenu.insertMenu(index+1, object ) // add sub-menu under the search bar onObjectAdded: newNodeMenu.insertMenu(index + 1, object ) // add sub-menu under the search bar
onObjectRemoved: newNodeMenu.removeMenu(object) onObjectRemoved: newNodeMenu.removeMenu(object)
delegate: Menu { delegate: Menu {
@ -409,12 +393,10 @@ Item {
onPressed: { onPressed: {
const canEdit = !edge.dst.node.locked const canEdit = !edge.dst.node.locked
if(event.button === Qt.RightButton) if (event.button === Qt.RightButton) {
{ if (canEdit && (event.modifiers & Qt.AltModifier)) {
if(canEdit && (event.modifiers & Qt.AltModifier)) {
uigraph.removeEdge(edge) uigraph.removeEdge(edge)
} } else {
else {
edgeMenu.currentEdge = edge edgeMenu.currentEdge = edge
edgeMenu.popup() edgeMenu.popup()
} }
@ -478,8 +460,8 @@ Item {
ToolTip.text: "Copy selection to the clipboard and immediately paste it" ToolTip.text: "Copy selection to the clipboard and immediately paste it"
ToolTip.visible: hovered ToolTip.visible: hovered
onTriggered: { onTriggered: {
copyNodes(); copyNodes()
pasteNodes(); pasteNodes()
} }
} }
MenuItem { MenuItem {
@ -489,11 +471,14 @@ Item {
MaterialToolButton { MaterialToolButton {
id: duplicateFollowingButton id: duplicateFollowingButton
height: parent.height height: parent.height
anchors { right: parent.right; rightMargin: parent.padding } anchors {
right: parent.right
rightMargin: parent.padding
}
text: MaterialIcons.fast_forward text: MaterialIcons.fast_forward
onClicked: { onClicked: {
duplicateNode(true); duplicateNode(true)
nodeMenu.close(); nodeMenu.close()
} }
} }
} }
@ -504,11 +489,14 @@ Item {
MaterialToolButton { MaterialToolButton {
id: removeFollowingButton id: removeFollowingButton
height: parent.height height: parent.height
anchors { right: parent.right; rightMargin: parent.padding } anchors {
right: parent.right
rightMargin: parent.padding
}
text: MaterialIcons.fast_forward text: MaterialIcons.fast_forward
onClicked: { onClicked: {
uigraph.removeNodesFrom(uigraph.selectedNodes); uigraph.removeNodesFrom(uigraph.selectedNodes)
nodeMenu.close(); nodeMenu.close()
} }
} }
} }
@ -516,35 +504,38 @@ Item {
MenuItem { MenuItem {
text: "Delete Data" + (deleteFollowingButton.hovered ? " From Here" : "" ) + "..." text: "Delete Data" + (deleteFollowingButton.hovered ? " From Here" : "" ) + "..."
enabled: { enabled: {
if(!nodeMenu.currentNode) if (!nodeMenu.currentNode)
return false return false
// Check if the current node is locked (needed because it does not belong to its own duplicates list) // Check if the current node is locked (needed because it does not belong to its own duplicates list)
if(nodeMenu.currentNode.locked) if (nodeMenu.currentNode.locked)
return false return false
// Check if at least one of the duplicate nodes is locked // Check if at least one of the duplicate nodes is locked
for(let i = 0; i < nodeMenu.currentNode.duplicates.count; ++i) { for (let i = 0; i < nodeMenu.currentNode.duplicates.count; ++i) {
if(nodeMenu.currentNode.duplicates.at(i).locked) if (nodeMenu.currentNode.duplicates.at(i).locked)
return false return false
} }
return true return true
} }
function showConfirmationDialog(deleteFollowing) { function showConfirmationDialog(deleteFollowing) {
uigraph.forceNodesStatusUpdate(); uigraph.forceNodesStatusUpdate()
var obj = deleteDataDialog.createObject(root, var obj = deleteDataDialog.createObject(root,
{ {
"node": nodeMenu.currentNode, "node": nodeMenu.currentNode,
"deleteFollowing": deleteFollowing "deleteFollowing": deleteFollowing
}); })
obj.open() obj.open()
nodeMenu.close(); nodeMenu.close()
} }
onTriggered: showConfirmationDialog(false) onTriggered: showConfirmationDialog(false)
MaterialToolButton { MaterialToolButton {
id: deleteFollowingButton id: deleteFollowingButton
anchors { right: parent.right; rightMargin: parent.padding } anchors {
right: parent.right
rightMargin: parent.padding
}
height: parent.height height: parent.height
text: MaterialIcons.fast_forward text: MaterialIcons.fast_forward
onClicked: parent.showConfirmationDialog(true) onClicked: parent.showConfirmationDialog(true)
@ -566,10 +557,10 @@ Item {
standardButtons: Dialog.Yes | Dialog.Cancel standardButtons: Dialog.Yes | Dialog.Cancel
onAccepted: { onAccepted: {
if(deleteFollowing) if (deleteFollowing)
uigraph.clearDataFrom(uigraph.selectedNodes); uigraph.clearDataFrom(uigraph.selectedNodes)
else else
uigraph.clearData(uigraph.selectedNodes); uigraph.clearData(uigraph.selectedNodes)
} }
onClosed: destroy() onClosed: destroy()
} }
@ -611,7 +602,7 @@ Item {
return return
} }
} else if (mouse.modifiers & Qt.AltModifier) { } else if (mouse.modifiers & Qt.AltModifier) {
if (!(mouse.modifiers & Qt.ControlModifier)){ if (!(mouse.modifiers & Qt.ControlModifier)) {
uigraph.clearNodeSelection() uigraph.clearNodeSelection()
} }
uigraph.selectFollowing(node) uigraph.selectFollowing(node)
@ -796,10 +787,10 @@ Item {
padding: 0 padding: 0
enabled: graphSearchBar.text !== "" enabled: graphSearchBar.text !== ""
onClicked: { onClicked: {
navigation.currentIndex--; navigation.currentIndex--
if (navigation.currentIndex === -1) if (navigation.currentIndex === -1)
navigation.currentIndex = filteredNodes.count - 1; navigation.currentIndex = filteredNodes.count - 1
navigation.nextItem(); navigation.nextItem()
} }
} }
@ -808,10 +799,10 @@ Item {
padding: 0 padding: 0
enabled: graphSearchBar.text !== "" enabled: graphSearchBar.text !== ""
onClicked: { onClicked: {
navigation.currentIndex++; navigation.currentIndex++
if (navigation.currentIndex === filteredNodes.count) if (navigation.currentIndex === filteredNodes.count)
navigation.currentIndex = 0; navigation.currentIndex = 0
navigation.nextItem(); navigation.nextItem()
} }
} }
@ -839,38 +830,34 @@ Item {
} }
} }
function nextItem() function nextItem() {
{
// compute bounding box // compute bounding box
var node = nodeRepeater.itemAt(filteredNodes.itemAt(navigation.currentIndex).index_) var node = nodeRepeater.itemAt(filteredNodes.itemAt(navigation.currentIndex).index_)
var bbox = Qt.rect(node.x, node.y, node.width, node.height) var bbox = Qt.rect(node.x, node.y, node.width, node.height)
// rescale to fit the bounding box in the view, zoom is limited to prevent huge text // rescale to fit the bounding box in the view, zoom is limited to prevent huge text
draggable.scale = Math.min(Math.min(root.width/bbox.width, root.height/bbox.height),maxZoom) draggable.scale = Math.min(Math.min(root.width / bbox.width, root.height / bbox.height),maxZoom)
// recenter // recenter
draggable.x = bbox.x*draggable.scale*-1 + (root.width-bbox.width*draggable.scale)*0.5 draggable.x = bbox.x*draggable.scale * -1 + (root.width - bbox.width * draggable.scale) * 0.5
draggable.y = bbox.y*draggable.scale*-1 + (root.height-bbox.height*draggable.scale)*0.5 draggable.y = bbox.y*draggable.scale * -1 + (root.height - bbox.height * draggable.scale) * 0.5
} }
} }
function registerAttributePin(attribute, pin) function registerAttributePin(attribute, pin) {
{
root._attributeToDelegate[attribute] = pin root._attributeToDelegate[attribute] = pin
} }
function unregisterAttributePin(attribute, pin) function unregisterAttributePin(attribute, pin) {
{
delete root._attributeToDelegate[attribute] delete root._attributeToDelegate[attribute]
} }
function boundingBox() function boundingBox() {
{
var first = nodeRepeater.itemAt(0) var first = nodeRepeater.itemAt(0)
var bbox = Qt.rect(first.x, first.y, first.x + first.width, first.y + first.height) var bbox = Qt.rect(first.x, first.y, first.x + first.width, first.y + first.height)
for(var i=0; i<root.graph.nodes.count; ++i) { for (var i = 0; i < root.graph.nodes.count; ++i) {
var item = nodeRepeater.itemAt(i) var item = nodeRepeater.itemAt(i)
bbox.x = Math.min(bbox.x, item.x) bbox.x = Math.min(bbox.x, item.x)
bbox.y = Math.min(bbox.y, item.y) bbox.y = Math.min(bbox.y, item.y)
bbox.width = Math.max(bbox.width, item.x+item.width) bbox.width = Math.max(bbox.width, item.x + item.width)
bbox.height = Math.max(bbox.height, item.y+item.height) bbox.height = Math.max(bbox.height, item.y + item.height)
} }
bbox.width -= bbox.x bbox.width -= bbox.x
bbox.height -= bbox.y bbox.height -= bbox.y
@ -882,10 +869,9 @@ Item {
// compute bounding box // compute bounding box
var bbox = boundingBox() var bbox = boundingBox()
// rescale to fit the bounding box in the view, zoom is limited to prevent huge text // rescale to fit the bounding box in the view, zoom is limited to prevent huge text
draggable.scale = Math.min(Math.min(root.width/bbox.width, root.height/bbox.height),maxZoom) draggable.scale = Math.min(Math.min(root.width / bbox.width, root.height / bbox.height), maxZoom)
// recenter // recenter
draggable.x = bbox.x*draggable.scale*-1 + (root.width-bbox.width*draggable.scale)*0.5 draggable.x = bbox.x * draggable.scale * -1 + (root.width - bbox.width * draggable.scale) * 0.5
draggable.y = bbox.y*draggable.scale*-1 + (root.height-bbox.height*draggable.scale)*0.5 draggable.y = bbox.y * draggable.scale * -1 + (root.height - bbox.height * draggable.scale) * 0.5
} }
} }

View file

@ -107,13 +107,13 @@ Item {
// Used to generate list of node's label sharing the same uid // Used to generate list of node's label sharing the same uid
function generateDuplicateList() { function generateDuplicateList() {
let str = "<b>Shares internal folder (data) with:</b>" let str = "<b>Shares internal folder (data) with:</b>"
for(let i = 0; i < node.duplicates.count; ++i) { for (let i = 0; i < node.duplicates.count; ++i) {
if(i % 5 === 0) if (i % 5 === 0)
str += "<br>" str += "<br>"
const currentNode = node.duplicates.at(i) const currentNode = node.duplicates.at(i)
if(i === node.duplicates.count - 1) { if (i === node.duplicates.count - 1) {
str += currentNode.nameToLabel(currentNode.name) str += currentNode.nameToLabel(currentNode.name)
return str return str
} }
@ -138,9 +138,8 @@ Item {
onEntered: root.entered() onEntered: root.entered()
onExited: root.exited() onExited: root.exited()
drag.onActiveChanged: { drag.onActiveChanged: {
if(!drag.active) if (!drag.active) {
{ root.moved(Qt.point(root.x, root.y))
root.moved(Qt.point(root.x, root.y));
} }
} }
@ -244,15 +243,23 @@ Item {
palette.text: Colors.sysPalette.text palette.text: Colors.sysPalette.text
ToolTip.text: toolTipText ToolTip.text: toolTipText
onPressed: { offsetReleased.running = false; toolTipText = visible ? generateDuplicateList() : "" } onPressed: {
onReleased: { toolTipText = "" ; offsetReleased.running = true } offsetReleased.running = false
toolTipText = visible ? generateDuplicateList() : ""
}
onReleased: {
toolTipText = ""
offsetReleased.running = true
}
onCanceled: released() onCanceled: released()
// Used for a better user experience with the button // Used for a better user experience with the button
// Avoid to change the text too quickly // Avoid to change the text too quickly
Timer { Timer {
id: offsetReleased id: offsetReleased
interval: 750; running: false; repeat: false interval: 750
running: false
repeat: false
onTriggered: parent.toolTipText = visible ? parent.baseText : "" onTriggered: parent.toolTipText = visible ? parent.baseText : ""
} }
} }
@ -521,4 +528,3 @@ Item {
} }
} }
} }

View file

@ -20,7 +20,7 @@ ListView {
id: chunkDelegate id: chunkDelegate
height: root.chunkHeight height: root.chunkHeight
width: root.chunkWidth width: root.chunkWidth
color: Colors.getChunkColor(object, {"NONE": root.defaultColor}) color: Colors.getChunkColor(object, { "NONE": root.defaultColor })
} }
} }

View file

@ -72,8 +72,7 @@ Panel {
hoverEnabled: true hoverEnabled: true
} }
function getLongestChunkTime(chunks) function getLongestChunkTime(chunks) {
{
if (chunks.count <= 1) if (chunks.count <= 1)
return 0 return 0

View file

@ -47,49 +47,44 @@ FocusScope {
function readSourceFile() { function readSourceFile() {
// make sure we are trying to load a statistics file // make sure we are trying to load a statistics file
if(!Filepath.urlToString(source).endsWith("status")) if (!Filepath.urlToString(source).endsWith("status"))
return; return
var xhr = new XMLHttpRequest; var xhr = new XMLHttpRequest
xhr.open("GET", source); xhr.open("GET", source)
xhr.onreadystatechange = function() { xhr.onreadystatechange = function() {
if (xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) { if (xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) {
// console.warn("StatusListModel: read valid file") // console.warn("StatusListModel: read valid file")
if(lastModified === undefined || lastModified !== xhr.getResponseHeader('Last-Modified')) { if (lastModified === undefined || lastModified !== xhr.getResponseHeader('Last-Modified')) {
lastModified = xhr.getResponseHeader('Last-Modified') lastModified = xhr.getResponseHeader('Last-Modified')
try { try {
var jsonObject = JSON.parse(xhr.responseText); var jsonObject = JSON.parse(xhr.responseText)
var entries = []; var entries = []
// prepare data to populate the ListModel from the input json object // prepare data to populate the ListModel from the input json object
for(var key in jsonObject) for (var key in jsonObject) {
{ var entry = {}
var entry = {}; entry["key"] = key
entry["key"] = key; entry["value"] = String(jsonObject[key])
entry["value"] = String(jsonObject[key]); entries.push(entry)
entries.push(entry);
} }
// reset the model with prepared data (limit to one update event) // reset the model with prepared data (limit to one update event)
statusListModel.clear(); statusListModel.clear()
statusListModel.append(entries); statusListModel.append(entries)
} } catch(exc) {
catch(exc)
{
// console.warn("StatusListModel: failed to read file") // console.warn("StatusListModel: failed to read file")
lastModified = undefined; lastModified = undefined
statusListModel.clear(); statusListModel.clear()
} }
} }
} } else {
else
{
// console.warn("StatusListModel: invalid file") // console.warn("StatusListModel: invalid file")
lastModified = undefined; lastModified = undefined
statusListModel.clear(); statusListModel.clear()
} }
}; }
xhr.send(); xhr.send()
} }
} }

View file

@ -79,10 +79,10 @@ Item {
} }
function getPropertyWithDefault(prop, name, defaultValue) { function getPropertyWithDefault(prop, name, defaultValue) {
if(prop.hasOwnProperty(name)) { if (prop.hasOwnProperty(name)) {
return prop[name]; return prop[name]
} }
return defaultValue; return defaultValue
} }
Timer { Timer {
@ -94,33 +94,30 @@ Item {
function readSourceFile() { function readSourceFile() {
// make sure we are trying to load a statistics file // make sure we are trying to load a statistics file
if(!Filepath.urlToString(source).endsWith("statistics")) if (!Filepath.urlToString(source).endsWith("statistics"))
return; return
var xhr = new XMLHttpRequest; var xhr = new XMLHttpRequest
xhr.open("GET", source); xhr.open("GET", source)
xhr.onreadystatechange = function() { xhr.onreadystatechange = function() {
if (xhr.readyState === XMLHttpRequest.DONE && xhr.status == 200) { if (xhr.readyState === XMLHttpRequest.DONE && xhr.status == 200) {
if (sourceModified === undefined || sourceModified < xhr.getResponseHeader('Last-Modified')) {
if(sourceModified === undefined || sourceModified < xhr.getResponseHeader('Last-Modified')) {
try { try {
root.jsonObject = JSON.parse(xhr.responseText); root.jsonObject = JSON.parse(xhr.responseText)
} } catch(exc) {
catch(exc)
{
console.warning("Failed to parse statistics file: " + source) console.warning("Failed to parse statistics file: " + source)
root.jsonObject = {}; root.jsonObject = {}
return; return
} }
resetCharts(); resetCharts()
sourceModified = xhr.getResponseHeader('Last-Modified') sourceModified = xhr.getResponseHeader('Last-Modified')
root.createCharts(); root.createCharts()
reloadTimer.restart(); reloadTimer.restart()
} }
} }
}; }
xhr.send(); xhr.send()
} }
function resetCharts() { function resetCharts() {
@ -151,7 +148,7 @@ Item {
var category var category
do { do {
category = jsonObject.computer.curves["cpuUsage." + categoryCount] category = jsonObject.computer.curves["cpuUsage." + categoryCount]
if(category !== undefined) { if (category !== undefined) {
categories.push(category) categories.push(category)
categoryCount++ categoryCount++
} }
@ -164,17 +161,17 @@ Item {
root.nbReads = categories[0].length-1 root.nbReads = categories[0].length-1
for(var j = 0; j < nbCores; j++) { for (var j = 0; j < nbCores; j++) {
var lineSerie = cpuChart.createSeries(ChartView.SeriesTypeLine, "CPU" + j, valueCpuX, valueCpuY) var lineSerie = cpuChart.createSeries(ChartView.SeriesTypeLine, "CPU" + j, valueCpuX, valueCpuY)
if(categories[j].length === 1) { if (categories[j].length === 1) {
lineSerie.append(0, categories[j][0]) lineSerie.append(0, categories[j][0])
lineSerie.append(root.deltaTime, categories[j][0]) lineSerie.append(root.deltaTime, categories[j][0])
} else { } else {
var displayLength = Math.min(maxDisplayLength, categories[j].length); var displayLength = Math.min(maxDisplayLength, categories[j].length)
var step = categories[j].length / displayLength; var step = categories[j].length / displayLength
for(var kk = 0; kk < displayLength; kk+=step) { for (var kk = 0; kk < displayLength; kk += step) {
var k = Math.floor(kk*step) var k = Math.floor(kk * step)
lineSerie.append(k * root.deltaTime, categories[j][k]) lineSerie.append(k * root.deltaTime, categories[j][k])
} }
} }
@ -184,35 +181,34 @@ Item {
var averageLine = cpuChart.createSeries(ChartView.SeriesTypeLine, "AVERAGE", valueCpuX, valueCpuY) var averageLine = cpuChart.createSeries(ChartView.SeriesTypeLine, "AVERAGE", valueCpuX, valueCpuY)
var average = [] var average = []
var displayLengthA = Math.min(maxDisplayLength, categories[0].length); var displayLengthA = Math.min(maxDisplayLength, categories[0].length)
var stepA = categories[0].length / displayLengthA; var stepA = categories[0].length / displayLengthA
for(var l = 0; l < displayLengthA; l+=step) { for (var l = 0; l < displayLengthA; l += step) {
average.push(0) average.push(0)
} }
for(var m = 0; m < categories.length; m++) { for (var m = 0; m < categories.length; m++) {
var displayLengthB = Math.min(maxDisplayLength, categories[m].length); var displayLengthB = Math.min(maxDisplayLength, categories[m].length)
var stepB = categories[0].length / displayLengthB; var stepB = categories[0].length / displayLengthB
for(var nn = 0; nn < displayLengthB; nn++) { for (var nn = 0; nn < displayLengthB; nn++) {
var n = Math.floor(nn*stepB) var n = Math.floor(nn * stepB)
average[nn] += categories[m][n] average[nn] += categories[m][n]
} }
} }
for(var q = 0; q < average.length; q++) { for (var q = 0; q < average.length; q++) {
average[q] = average[q] / (categories.length) average[q] = average[q] / (categories.length)
averageLine.append(q * root.deltaTime * stepA, average[q]) averageLine.append(q * root.deltaTime * stepA, average[q])
} }
averageLine.color = colors[colors.length-1] averageLine.color = colors[colors.length - 1]
} }
function hideOtherCpu(index) { function hideOtherCpu(index) {
for(var i = 0; i < cpuChart.count; i++) { for (var i = 0; i < cpuChart.count; i++) {
cpuChart.series(i).visible = false; cpuChart.series(i).visible = false
} }
cpuChart.series(index).visible = true; cpuChart.series(index).visible = true
} }
@ -226,10 +222,9 @@ Item {
root.ramTotal = getPropertyWithDefault(jsonObject.computer, 'ramTotal', -1) root.ramTotal = getPropertyWithDefault(jsonObject.computer, 'ramTotal', -1)
root.ramLabel = "RAM: " root.ramLabel = "RAM: "
if(root.ramTotal <= 0) if (root.ramTotal <= 0) {
{
var maxRamPeak = 0 var maxRamPeak = 0
for(var i = 0; i < ram.length; i++) { for (var i = 0; i < ram.length; i++) {
maxRamPeak = Math.max(maxRamPeak, ram[i]) maxRamPeak = Math.max(maxRamPeak, ram[i])
} }
root.ramTotal = maxRamPeak root.ramTotal = maxRamPeak
@ -238,19 +233,19 @@ Item {
var ramSerie = ramChart.createSeries(ChartView.SeriesTypeLine, root.ramLabel + root.ramTotal + "GB", valueRamX, valueRamY) var ramSerie = ramChart.createSeries(ChartView.SeriesTypeLine, root.ramLabel + root.ramTotal + "GB", valueRamX, valueRamY)
if(ram.length === 1) { if (ram.length === 1) {
// Create 2 entries if we have only one input value to create a segment that can be display // Create 2 entries if we have only one input value to create a segment that can be display
ramSerie.append(0, ram[0]); ramSerie.append(0, ram[0])
ramSerie.append(root.deltaTime, ram[0]); ramSerie.append(root.deltaTime, ram[0])
} else { } else {
var displayLength = Math.min(maxDisplayLength, ram.length); var displayLength = Math.min(maxDisplayLength, ram.length)
var step = ram.length / displayLength; var step = ram.length / displayLength
for(var ii = 0; ii < displayLength; ii++) { for(var ii = 0; ii < displayLength; ii++) {
var i = Math.floor(ii*step); var i = Math.floor(ii * step)
ramSerie.append(i * root.deltaTime, ram[i]); ramSerie.append(i * root.deltaTime, ram[i])
} }
} }
ramSerie.color = colors[10]; ramSerie.color = colors[10]
} }
/************************** /**************************
@ -269,9 +264,9 @@ Item {
var gpuUsedMemorySerie = gpuChart.createSeries(ChartView.SeriesTypeLine, "Memory", valueGpuX, valueGpuY) var gpuUsedMemorySerie = gpuChart.createSeries(ChartView.SeriesTypeLine, "Memory", valueGpuX, valueGpuY)
var gpuTemperatureSerie = gpuChart.createSeries(ChartView.SeriesTypeLine, "Temperature", valueGpuX, valueGpuY) var gpuTemperatureSerie = gpuChart.createSeries(ChartView.SeriesTypeLine, "Temperature", valueGpuX, valueGpuY)
var gpuMemoryRatio = root.gpuTotalMemory > 0 ? (100 / root.gpuTotalMemory) : 1; var gpuMemoryRatio = root.gpuTotalMemory > 0 ? (100 / root.gpuTotalMemory) : 1
if(gpuUsedMemory.length === 1) { if (gpuUsedMemory.length === 1) {
gpuUsedSerie.append(0, gpuUsed[0]) gpuUsedSerie.append(0, gpuUsed[0])
gpuUsedSerie.append(1 * root.deltaTime, gpuUsed[0]) gpuUsedSerie.append(1 * root.deltaTime, gpuUsed[0])
@ -282,9 +277,9 @@ Item {
gpuTemperatureSerie.append(1 * root.deltaTime, gpuTemperature[0]) gpuTemperatureSerie.append(1 * root.deltaTime, gpuTemperature[0])
root.gpuMaxAxis = Math.max(gpuMaxAxis, gpuTemperature[0]) root.gpuMaxAxis = Math.max(gpuMaxAxis, gpuTemperature[0])
} else { } else {
var displayLength = Math.min(maxDisplayLength, gpuUsedMemory.length); var displayLength = Math.min(maxDisplayLength, gpuUsedMemory.length)
var step = gpuUsedMemory.length / displayLength; var step = gpuUsedMemory.length / displayLength
for(var ii = 0; ii < displayLength; ii+=step) { for (var ii = 0; ii < displayLength; ii += step) {
var i = Math.floor(ii*step) var i = Math.floor(ii*step)
gpuUsedSerie.append(i * root.deltaTime, gpuUsed[i]) gpuUsedSerie.append(i * root.deltaTime, gpuUsed[i])
@ -356,7 +351,6 @@ Item {
width: parent.width width: parent.width
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
ChartViewCheckBox { ChartViewCheckBox {
id: allCPU id: allCPU
text: "ALL" text: "ALL"
@ -365,9 +359,8 @@ Item {
leftPadding: 0 leftPadding: 0
onClicked: { onClicked: {
var _checked = checked; var _checked = checked;
for(var i = 0; i < cpuChart.count; ++i) for (var i = 0; i < cpuChart.count; ++i) {
{ cpuChart.series(i).visible = _checked
cpuChart.series(i).visible = _checked;
} }
} }
} }
@ -378,7 +371,6 @@ Item {
Layout.fillHeight: true Layout.fillHeight: true
chartView: cpuChart chartView: cpuChart
} }
} }
} }
@ -386,7 +378,7 @@ Item {
id: cpuChart id: cpuChart
Layout.fillWidth: true Layout.fillWidth: true
Layout.preferredHeight: width/2 Layout.preferredHeight: width / 2
margins.top: 0 margins.top: 0
margins.bottom: 0 margins.bottom: 0
antialiasing: true antialiasing: true
@ -425,7 +417,6 @@ Item {
shadesBorderColor: textColor shadesBorderColor: textColor
labelsColor: textColor labelsColor: textColor
} }
} }
} }
@ -442,7 +433,7 @@ Item {
margins.top: 0 margins.top: 0
margins.bottom: 0 margins.bottom: 0
Layout.fillWidth: true Layout.fillWidth: true
Layout.preferredHeight: width/2 Layout.preferredHeight: width / 2
antialiasing: true antialiasing: true
legend.color: textColor legend.color: textColor
legend.labelColor: textColor legend.labelColor: textColor
@ -491,7 +482,6 @@ Item {
ColumnLayout { ColumnLayout {
InteractiveChartView { InteractiveChartView {
id: gpuChart id: gpuChart
@ -537,8 +527,6 @@ Item {
} }
} }
} }
} }
} }
} }

View file

@ -150,8 +150,8 @@ Item {
function getNbFinishedChunks(chunks) { function getNbFinishedChunks(chunks) {
var nbSuccess = 0 var nbSuccess = 0
for(var i = 0; i < chunks.count; i++) { for (var i = 0; i < chunks.count; i++) {
if(chunks.at(i).statusName === "SUCCESS") { if (chunks.at(i).statusName === "SUCCESS") {
nbSuccess += 1 nbSuccess += 1
} }
} }
@ -159,7 +159,7 @@ Item {
} }
Label { Label {
text: index+1 text: index + 1
Layout.preferredWidth: nbMetrics.width + 20 Layout.preferredWidth: nbMetrics.width + 20
Layout.preferredHeight: parent.height Layout.preferredHeight: parent.height
horizontalAlignment: Label.AlignHCenter horizontalAlignment: Label.AlignHCenter
@ -253,36 +253,36 @@ Item {
Layout.minimumWidth: progressMetrics.width + 20 Layout.minimumWidth: progressMetrics.width + 20
Layout.preferredHeight: parent.height Layout.preferredHeight: parent.height
ListView { ListView {
id: chunkList id: chunkList
width: parent.width width: parent.width
height: parent.height height: parent.height
orientation: ListView.Horizontal orientation: ListView.Horizontal
model: object.chunks model: object.chunks
property var node: object property var node: object
spacing: 3 spacing: 3
delegate: Label { delegate: Label {
width: (ListView.view.width / ListView.view.model.count) -3 width: (ListView.view.width / ListView.view.model.count) - 3
height: ListView.view.height height: ListView.view.height
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
background: Rectangle { background: Rectangle {
color: Colors.getChunkColor(object, {"NONE": bgColor}) color: Colors.getChunkColor(object, {"NONE": bgColor})
radius: 3 radius: 3
border.width: 2 border.width: 2
border.color: chunkList.node === uigraph.selectedNode ? Colors.sysPalette.text : Colors.getChunkColor(object, {"NONE": bgColor}) border.color: chunkList.node === uigraph.selectedNode ? Colors.sysPalette.text : Colors.getChunkColor(object, {"NONE": bgColor})
} }
MouseArea { MouseArea {
anchors.fill: parent anchors.fill: parent
onPressed: { onPressed: {
selectNode(chunkList.node) selectNode(chunkList.node)
}
} }
} }
} }
}
} }
} }
} }

View file

@ -12,21 +12,16 @@ var statusColorsExternOverrides = {
"SUBMITTED": "#2196F3" "SUBMITTED": "#2196F3"
} }
function getChunkColor(chunk, overrides) function getChunkColor(chunk, overrides) {
{ if (overrides && chunk.statusName in overrides) {
if(overrides && chunk.statusName in overrides)
{
return overrides[chunk.statusName] return overrides[chunk.statusName]
} } else if(chunk.execModeName === "EXTERN"
else if(chunk.execModeName === "EXTERN" && chunk.statusName in statusColorsExternOverrides) {
&& chunk.statusName in statusColorsExternOverrides)
{
return statusColorsExternOverrides[chunk.statusName] return statusColorsExternOverrides[chunk.statusName]
} } else if(chunk.statusName in statusColors) {
else if(chunk.statusName in statusColors)
{
return statusColors[chunk.statusName] return statusColors[chunk.statusName]
} }
console.warn("Unknown status : " + chunk.status) console.warn("Unknown status : " + chunk.status)
return "magenta" return "magenta"
} }