Merge pull request #2624 from alicevision/fix/NodeEditorTab

[ui] NodeEditor: Addressed Tab Retention when switching Node selection
This commit is contained in:
Candice Bentéjac 2024-12-31 13:30:10 +01:00 committed by GitHub
commit 05863369f5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 217 additions and 182 deletions

View file

@ -215,6 +215,7 @@ class Graph(BaseObject):
super(Graph, self).__init__(parent)
self.name = name
self._loading = False
self._saving = False
self._updateEnabled = True
self._updateRequested = False
self.dirtyTopology = False
@ -251,6 +252,11 @@ class Graph(BaseObject):
def isLoading(self):
""" Return True if the graph is currently being loaded. """
return self._loading
@property
def isSaving(self):
""" Return True if the graph is currently being saved. """
return self._saving
@Slot(str)
def load(self, filepath, setupProjectFile=True, importProject=False, publishOutputs=False):
@ -1347,6 +1353,23 @@ class Graph(BaseObject):
return str(self.toDict())
def save(self, filepath=None, setupProjectFile=True, template=False):
"""
Save the current Meshroom graph as a serialized ".mg" file.
Args:
filepath: project filepath to save as.
setupProjectFile: Store the reference to the project file and setup the cache directory.
If false, it only saves the graph of the project file as a template.
template: If true, saves the current graph as a template.
"""
# Update the saving flag indicating that the current graph is being saved
self._saving = True
try:
self._save(filepath=filepath, setupProjectFile=setupProjectFile, template=template)
finally:
self._saving = False
def _save(self, filepath=None, setupProjectFile=True, template=False):
path = filepath or self._filepath
if not path:
raise ValueError("filepath must be specified for unsaved files.")
@ -1636,6 +1659,7 @@ class Graph(BaseObject):
edges = Property(BaseObject, edges.fget, constant=True)
filepathChanged = Signal()
filepath = Property(str, lambda self: self._filepath, notify=filepathChanged)
isSaving = Property(bool, isSaving.fget, constant=True)
fileReleaseVersion = Property(str, lambda self: self.header.get(Graph.IO.Keys.ReleaseVersion, "0.0"),
notify=filepathChanged)
fileDateVersion = Property(float, fileDateVersion.fget, fileDateVersion.fset, notify=filepathChanged)

View file

@ -20,6 +20,16 @@ Page {
property alias unsavedDialog: unsavedDialog
property alias workspaceView: workspaceView
readonly property var scenefile: _reconstruction ? _reconstruction.graph.filepath : "";
onScenefileChanged: {
// Check if we're not currently saving and emit the currentProjectChanged signal
if (! _reconstruction.graph.isSaving) {
// Refresh the NodeEditor
nodeEditor.refresh();
}
}
Settings {
id: settingsUILayout
category: "UILayout"

View file

@ -42,6 +42,14 @@ Panel {
}
}
function refresh() {
/**
* Refresh properties of the Node Editor.
*/
// Reset tab bar's current index
tabBar.currentIndex = 0;
}
headerBar: RowLayout {
Label {
id: computationInfo
@ -372,6 +380,9 @@ Panel {
property bool isComputable: root.node !== null && root.node.isComputable
// The indices of the tab bar which can be shown for incomputable nodes
readonly property var nonComputableTabIndices: [0, 4, 5];
Layout.fillWidth: true
width: childrenRect.width
position: TabBar.Footer
@ -415,9 +426,11 @@ Panel {
rightPadding: leftPadding
}
onIsComputableChanged: {
if (!isComputable) {
tabBar.currentIndex = 0
onVisibleChanged: {
// If we have a node selected and the node is not Computable
// Reset the currentIndex to 0, if the current index is not allowed for an incomputable node
if ((root.node && !root.node.isComputable) && (nonComputableTabIndices.indexOf(tabBar.currentIndex) === -1)) {
tabBar.currentIndex = 0;
}
}
}

View file

@ -310,220 +310,208 @@ Item {
*** CPU UI ***
**************************/
ColumnLayout {
Button {
id: toggleCpuBtn
Layout.fillWidth: true
text: "Toggle CPU's"
state: "closed"
Button {
id: toggleCpuBtn
Layout.fillWidth: true
text: "Toggle CPU's"
state: "closed"
onClicked: state === "opened" ? state = "closed" : state = "opened"
onClicked: state === "opened" ? state = "closed" : state = "opened"
MaterialLabel {
text: MaterialIcons.arrow_drop_down
font.pointSize: 14
anchors.right: parent.right
}
states: [
State {
name: "opened"
PropertyChanges { target: cpuBtnContainer; visible: true }
PropertyChanges { target: toggleCpuBtn; down: true }
},
State {
name: "closed"
PropertyChanges { target: cpuBtnContainer; visible: false }
PropertyChanges { target: toggleCpuBtn; down: false }
}
]
MaterialLabel {
text: MaterialIcons.arrow_drop_down
font.pointSize: 14
anchors.right: parent.right
}
Item {
id: cpuBtnContainer
states: [
State {
name: "opened"
PropertyChanges { target: cpuBtnContainer; visible: true }
PropertyChanges { target: toggleCpuBtn; down: true }
},
State {
name: "closed"
PropertyChanges { target: cpuBtnContainer; visible: false }
PropertyChanges { target: toggleCpuBtn; down: false }
}
]
}
Layout.fillWidth: true
implicitHeight: childrenRect.height
Layout.leftMargin: 25
Item {
id: cpuBtnContainer
RowLayout {
width: parent.width
anchors.horizontalCenter: parent.horizontalCenter
Layout.fillWidth: true
implicitHeight: childrenRect.height
Layout.leftMargin: 25
ChartViewCheckBox {
id: allCPU
text: "ALL"
color: textColor
checkState: cpuLegend.buttonGroup.checkState
leftPadding: 0
onClicked: {
var _checked = checked;
for (var i = 0; i < cpuChart.count; ++i) {
cpuChart.series(i).visible = _checked
}
RowLayout {
width: parent.width
anchors.horizontalCenter: parent.horizontalCenter
ChartViewCheckBox {
id: allCPU
text: "ALL"
color: textColor
checkState: cpuLegend.buttonGroup.checkState
leftPadding: 0
onClicked: {
var _checked = checked;
for (var i = 0; i < cpuChart.count; ++i) {
cpuChart.series(i).visible = _checked
}
}
ChartViewLegend {
id: cpuLegend
Layout.fillWidth: true
Layout.fillHeight: true
chartView: cpuChart
}
}
}
InteractiveChartView {
id: cpuChart
Layout.fillWidth: true
Layout.preferredHeight: width / 2
margins.top: 0
margins.bottom: 0
antialiasing: true
legend.visible: false
theme: ChartView.ChartThemeLight
backgroundColor: "transparent"
plotAreaColor: "transparent"
titleColor: textColor
visible: (root.fileVersion > 0.0) // Only visible if we have valid information
title: "CPU: " + root.nbCores + " cores, " + root.cpuFrequency + "MHz"
ValueAxis {
id: valueCpuY
min: 0
max: 100
titleText: "<span style='color: " + textColor + "'>%</span>"
color: textColor
gridLineColor: textColor
minorGridLineColor: textColor
shadesColor: textColor
shadesBorderColor: textColor
labelsColor: textColor
}
ValueAxis {
id: valueCpuX
min: 0
max: root.deltaTime * Math.max(1, root.nbReads)
titleText: "<span style='color: " + textColor + "'>Minutes</span>"
color: textColor
gridLineColor: textColor
minorGridLineColor: textColor
shadesColor: textColor
shadesBorderColor: textColor
labelsColor: textColor
ChartViewLegend {
id: cpuLegend
Layout.fillWidth: true
Layout.fillHeight: true
chartView: cpuChart
}
}
}
InteractiveChartView {
id: cpuChart
Layout.fillWidth: true
Layout.preferredHeight: width / 2
margins.top: 0
margins.bottom: 0
antialiasing: true
legend.visible: false
theme: ChartView.ChartThemeLight
backgroundColor: "transparent"
plotAreaColor: "transparent"
titleColor: textColor
visible: (root.fileVersion > 0.0) // Only visible if we have valid information
title: "CPU: " + root.nbCores + " cores, " + root.cpuFrequency + "MHz"
ValueAxis {
id: valueCpuY
min: 0
max: 100
titleText: "<span style='color: " + textColor + "'>%</span>"
color: textColor
gridLineColor: textColor
minorGridLineColor: textColor
shadesColor: textColor
shadesBorderColor: textColor
labelsColor: textColor
}
ValueAxis {
id: valueCpuX
min: 0
max: root.deltaTime * Math.max(1, root.nbReads)
titleText: "<span style='color: " + textColor + "'>Minutes</span>"
color: textColor
gridLineColor: textColor
minorGridLineColor: textColor
shadesColor: textColor
shadesBorderColor: textColor
labelsColor: textColor
}
}
/**************************
*** RAM UI ***
**************************/
ColumnLayout {
InteractiveChartView {
id: ramChart
margins.top: 0
margins.bottom: 0
Layout.fillWidth: true
Layout.preferredHeight: width / 2
antialiasing: true
legend.color: textColor
legend.labelColor: textColor
legend.visible: false
theme: ChartView.ChartThemeLight
backgroundColor: "transparent"
plotAreaColor: "transparent"
titleColor: textColor
InteractiveChartView {
id: ramChart
margins.top: 0
margins.bottom: 0
Layout.fillWidth: true
Layout.preferredHeight: width / 2
antialiasing: true
legend.color: textColor
legend.labelColor: textColor
legend.visible: false
theme: ChartView.ChartThemeLight
backgroundColor: "transparent"
plotAreaColor: "transparent"
titleColor: textColor
visible: (root.fileVersion > 0.0) // Only visible if we have valid information
title: root.ramLabel + root.ramTotal + "GB"
visible: (root.fileVersion > 0.0) // Only visible if we have valid information
title: root.ramLabel + root.ramTotal + "GB"
ValueAxis {
id: valueRamY
min: 0
max: 100
titleText: "<span style='color: " + textColor + "'>%</span>"
color: textColor
gridLineColor: textColor
minorGridLineColor: textColor
shadesColor: textColor
shadesBorderColor: textColor
labelsColor: textColor
}
ValueAxis {
id: valueRamY
min: 0
max: 100
titleText: "<span style='color: " + textColor + "'>%</span>"
color: textColor
gridLineColor: textColor
minorGridLineColor: textColor
shadesColor: textColor
shadesBorderColor: textColor
labelsColor: textColor
}
ValueAxis {
id: valueRamX
min: 0
max: root.deltaTime * Math.max(1, root.nbReads)
titleText: "<span style='color: " + textColor + "'>Minutes</span>"
color: textColor
gridLineColor: textColor
minorGridLineColor: textColor
shadesColor: textColor
shadesBorderColor: textColor
labelsColor: textColor
}
ValueAxis {
id: valueRamX
min: 0
max: root.deltaTime * Math.max(1, root.nbReads)
titleText: "<span style='color: " + textColor + "'>Minutes</span>"
color: textColor
gridLineColor: textColor
minorGridLineColor: textColor
shadesColor: textColor
shadesBorderColor: textColor
labelsColor: textColor
}
}
/**************************
*** GPU UI ***
**************************/
ColumnLayout {
InteractiveChartView {
id: gpuChart
InteractiveChartView {
id: gpuChart
Layout.fillWidth: true
Layout.preferredHeight: width/2
margins.top: 0
margins.bottom: 0
antialiasing: true
legend.color: textColor
legend.labelColor: textColor
theme: ChartView.ChartThemeLight
backgroundColor: "transparent"
plotAreaColor: "transparent"
titleColor: textColor
Layout.fillWidth: true
Layout.preferredHeight: width/2
margins.top: 0
margins.bottom: 0
antialiasing: true
legend.color: textColor
legend.labelColor: textColor
theme: ChartView.ChartThemeLight
backgroundColor: "transparent"
plotAreaColor: "transparent"
titleColor: textColor
visible: (root.fileVersion >= 2.0) // No GPU information was collected before stats 2.0 fileVersion
title: (root.gpuName || root.gpuTotalMemory) ? ("GPU: " + root.gpuName + ", " + root.gpuTotalMemory + "MB") : "No GPU"
visible: (root.fileVersion >= 2.0) // No GPU information was collected before stats 2.0 fileVersion
title: (root.gpuName || root.gpuTotalMemory) ? ("GPU: " + root.gpuName + ", " + root.gpuTotalMemory + "MB") : "No GPU"
ValueAxis {
id: valueGpuY
min: 0
max: root.gpuMaxAxis
titleText: "<span style='color: " + textColor + "'>%, °C</span>"
color: textColor
gridLineColor: textColor
minorGridLineColor: textColor
shadesColor: textColor
shadesBorderColor: textColor
labelsColor: textColor
}
ValueAxis {
id: valueGpuY
min: 0
max: root.gpuMaxAxis
titleText: "<span style='color: " + textColor + "'>%, °C</span>"
color: textColor
gridLineColor: textColor
minorGridLineColor: textColor
shadesColor: textColor
shadesBorderColor: textColor
labelsColor: textColor
}
ValueAxis {
id: valueGpuX
min: 0
max: root.deltaTime * Math.max(1, root.nbReads)
titleText: "<span style='color: " + textColor + "'>Minutes</span>"
color: textColor
gridLineColor: textColor
minorGridLineColor: textColor
shadesColor: textColor
shadesBorderColor: textColor
labelsColor: textColor
}
ValueAxis {
id: valueGpuX
min: 0
max: root.deltaTime * Math.max(1, root.nbReads)
titleText: "<span style='color: " + textColor + "'>Minutes</span>"
color: textColor
gridLineColor: textColor
minorGridLineColor: textColor
shadesColor: textColor
shadesBorderColor: textColor
labelsColor: textColor
}
}
}