Merge pull request #1839 from alicevision/dev/fixQmlWarnings

[ui] Fix all "TypeError" QML warnings
This commit is contained in:
Fabien Castan 2022-12-06 11:38:16 +01:00 committed by GitHub
commit a2f559f48a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 103 additions and 90 deletions

View file

@ -14,7 +14,7 @@ MessageDialog {
// the UIGraph instance // the UIGraph instance
property var uigraph property var uigraph
// alias to underlying compatibilityNodes model // alias to underlying compatibilityNodes model
readonly property var nodesModel: uigraph.graph.compatibilityNodes readonly property var nodesModel: uigraph ? uigraph.graph.compatibilityNodes : undefined
// the total number of compatibility issues // the total number of compatibility issues
readonly property int issueCount: (nodesModel != undefined) ? nodesModel.count : 0 readonly property int issueCount: (nodesModel != undefined) ? nodesModel.count : 0
// the number of CompatibilityNodes that can be upgraded // the number of CompatibilityNodes that can be upgraded
@ -47,7 +47,10 @@ MessageDialog {
title: "Compatibility issues detected" title: "Compatibility issues detected"
text: "This project contains " + issueCount + " node(s) incompatible with the current version of Meshroom." text: "This project contains " + issueCount + " node(s) incompatible with the current version of Meshroom."
detailedText: "Project was created with Meshroom " + uigraph.graph.fileReleaseVersion + "." detailedText: {
let releaseVersion = uigraph ? uigraph.graph.fileReleaseVersion : "0.0"
return "Project was created with Meshroom " + releaseVersion + "."
}
helperText: upgradableCount ? helperText: upgradableCount ?
upgradableCount + " node(s) can be upgraded but this might invalidate already computed data.\n" upgradableCount + " node(s) can be upgraded but this might invalidate already computed data.\n"

View file

@ -441,7 +441,7 @@ Item {
MenuItem { MenuItem {
text: "Submit" text: "Submit"
enabled: nodeMenu.canComputeNode && nodeMenu.canSubmitOrCompute > 1 enabled: nodeMenu.canComputeNode && nodeMenu.canSubmitOrCompute > 1
visible: uigraph.canSubmit visible: uigraph ? uigraph.canSubmit : false
height: visible ? implicitHeight : 0 height: visible ? implicitHeight : 0
onTriggered: submitRequest(nodeMenu.currentNode) onTriggered: submitRequest(nodeMenu.currentNode)
} }
@ -759,7 +759,7 @@ Item {
flat: true flat: true
model: ['Minimum', 'Maximum'] model: ['Minimum', 'Maximum']
implicitWidth: 80 implicitWidth: 80
currentIndex: uigraph.layout.depthMode currentIndex: uigraph ? uigraph.layout.depthMode : -1
onActivated: { onActivated: {
uigraph.layout.depthMode = currentIndex uigraph.layout.depthMode = currentIndex
} }

View file

@ -31,7 +31,7 @@ FocusScope {
selectByMouse: true selectByMouse: true
selectionColor: activePalette.highlight selectionColor: activePalette.highlight
color: activePalette.text color: activePalette.text
text: node.documentation text: node ? node.documentation : ""
wrapMode: TextEdit.Wrap wrapMode: TextEdit.Wrap
} }
} }

View file

@ -39,7 +39,7 @@ Item {
TextMetrics { TextMetrics {
id: nbMetrics id: nbMetrics
text: root.taskManager.nodes.count text: root.taskManager ? root.taskManager.nodes.count : "0"
} }
TextMetrics { TextMetrics {
@ -67,7 +67,7 @@ Item {
anchors.fill: parent anchors.fill: parent
ScrollBar.vertical: ScrollBar {} ScrollBar.vertical: ScrollBar {}
model: parent.taskManager.nodes model: parent.taskManager ? parent.taskManager.nodes : null
spacing: 3 spacing: 3
headerPositioning: ListView.OverlayHeader headerPositioning: ListView.OverlayHeader

View file

@ -58,7 +58,7 @@ Item {
} }
MenuItem { MenuItem {
text: "Define As Center Image" text: "Define As Center Image"
property var activeNode: _reconstruction.activeNodes.get("SfMTransform").node property var activeNode: _reconstruction ? _reconstruction.activeNodes.get("SfMTransform").node : null
enabled: !root.readOnly && _viewpoint.viewId != -1 && _reconstruction && activeNode enabled: !root.readOnly && _viewpoint.viewId != -1 && _reconstruction && activeNode
onClicked: activeNode.attribute("transformation").value = _viewpoint.viewId.toString() onClicked: activeNode.attribute("transformation").value = _viewpoint.viewId.toString()
} }

View file

@ -35,7 +35,7 @@ Panel {
QtObject { QtObject {
id: m id: m
property variant currentCameraInit: _reconstruction.tempCameraInit ? _reconstruction.tempCameraInit : root.cameraInit property variant currentCameraInit: _reconstruction && _reconstruction.tempCameraInit ? _reconstruction.tempCameraInit : root.cameraInit
property variant viewpoints: currentCameraInit ? currentCameraInit.attribute('viewpoints').value : undefined property variant viewpoints: currentCameraInit ? currentCameraInit.attribute('viewpoints').value : undefined
property variant intrinsics: currentCameraInit ? currentCameraInit.attribute('intrinsics').value : undefined property variant intrinsics: currentCameraInit ? currentCameraInit.attribute('intrinsics').value : undefined
property bool readOnly: root.readOnly || displayHDR.checked property bool readOnly: root.readOnly || displayHDR.checked
@ -144,7 +144,7 @@ Panel {
SensorDBDialog { SensorDBDialog {
id: sensorDBDialog id: sensorDBDialog
sensorDatabase: cameraInit ? Filepath.stringToUrl(cameraInit.attribute("sensorDatabase").value) : "" sensorDatabase: cameraInit ? Filepath.stringToUrl(cameraInit.attribute("sensorDatabase").value) : ""
readOnly: _reconstruction.computing readOnly: _reconstruction ? _reconstruction.computing : false
onUpdateIntrinsicsRequest: _reconstruction.rebuildIntrinsics(cameraInit) onUpdateIntrinsicsRequest: _reconstruction.rebuildIntrinsics(cameraInit)
} }
@ -273,11 +273,11 @@ Panel {
spacing: 2 spacing: 2
property bool valid: Qt.isQtObject(object) // object can be evaluated to null at some point during creation/deletion property bool valid: Qt.isQtObject(object) // object can be evaluated to null at some point during creation/deletion
property bool inViews: valid && _reconstruction.sfmReport && _reconstruction.isInViews(object) property bool inViews: valid && _reconstruction && _reconstruction.sfmReport && _reconstruction.isInViews(object)
// Camera Initialization indicator // Camera Initialization indicator
IntrinsicsIndicator { IntrinsicsIndicator {
intrinsic: parent.valid ? _reconstruction.getIntrinsic(object) : null intrinsic: parent.valid && _reconstruction ? _reconstruction.getIntrinsic(object) : null
metadata: imageDelegate.metadata metadata: imageDelegate.metadata
} }
@ -540,7 +540,7 @@ Panel {
RowLayout { RowLayout {
Layout.fillHeight: false Layout.fillHeight: false
visible: root.cameraInits.count > 1 visible: root.cameraInits ? root.cameraInits.count > 1 : false
Layout.alignment: Qt.AlignHCenter Layout.alignment: Qt.AlignHCenter
spacing: 2 spacing: 2
@ -560,8 +560,10 @@ Panel {
// display of group indices (real indices still are from // display of group indices (real indices still are from
// 0 to cameraInits.count - 1) // 0 to cameraInits.count - 1)
var l = []; var l = [];
for (var i = 1; i <= root.cameraInits.count; i++) { if (root.cameraInits) {
l.push(i); for (var i = 1; i <= root.cameraInits.count; i++) {
l.push(i);
}
} }
return l; return l;
} }
@ -569,13 +571,13 @@ Panel {
currentIndex: root.cameraInitIndex currentIndex: root.cameraInitIndex
onActivated: root.changeCurrentIndex(currentIndex) onActivated: root.changeCurrentIndex(currentIndex)
} }
Label { text: "/ " + (root.cameraInits.count) } Label { text: "/ " + (root.cameraInits ? root.cameraInits.count : "Unknown") }
ToolButton { ToolButton {
text: MaterialIcons.navigate_next text: MaterialIcons.navigate_next
font.family: MaterialIcons.fontFamily font.family: MaterialIcons.fontFamily
ToolTip.text: "Next Group (Alt+Right)" ToolTip.text: "Next Group (Alt+Right)"
ToolTip.visible: hovered ToolTip.visible: hovered
enabled: nodesCB.currentIndex < root.cameraInits.count - 1 enabled: root.cameraInits ? nodesCB.currentIndex < root.cameraInits.count - 1 : false
onClicked: nodesCB.incrementCurrentIndex() onClicked: nodesCB.incrementCurrentIndex()
} }
} }
@ -617,10 +619,10 @@ Panel {
Layout.minimumWidth: childrenRect.width Layout.minimumWidth: childrenRect.width
ToolTip.text: label + " Estimated Cameras" ToolTip.text: label + " Estimated Cameras"
iconText: MaterialIcons.videocam iconText: MaterialIcons.videocam
label: _reconstruction.nbCameras ? _reconstruction.nbCameras.toString() : "-" label: _reconstruction && _reconstruction.nbCameras ? _reconstruction.nbCameras.toString() : "-"
padding: 3 padding: 3
enabled: _reconstruction.cameraInit && _reconstruction.nbCameras enabled: _reconstruction ? _reconstruction.cameraInit && _reconstruction.nbCameras : false
checkable: true checkable: true
checked: false checked: false
@ -646,10 +648,10 @@ Panel {
Layout.minimumWidth: childrenRect.width Layout.minimumWidth: childrenRect.width
ToolTip.text: label + " Non Estimated Cameras" ToolTip.text: label + " Non Estimated Cameras"
iconText: MaterialIcons.videocam_off iconText: MaterialIcons.videocam_off
label: _reconstruction.nbCameras ? ((m.viewpoints ? m.viewpoints.count : 0) - _reconstruction.nbCameras.toString()).toString() : "-" label: _reconstruction && _reconstruction.nbCameras ? ((m.viewpoints ? m.viewpoints.count : 0) - _reconstruction.nbCameras.toString()).toString() : "-"
padding: 3 padding: 3
enabled: _reconstruction.cameraInit && _reconstruction.nbCameras enabled: _reconstruction ? _reconstruction.cameraInit && _reconstruction.nbCameras : false
checkable: true checkable: true
checked: false checked: false
@ -704,7 +706,7 @@ Panel {
MaterialToolLabelButton { MaterialToolLabelButton {
id: displayHDR id: displayHDR
Layout.minimumWidth: childrenRect.width Layout.minimumWidth: childrenRect.width
property var activeNode: _reconstruction.activeNodes.get("LdrToHdrMerge").node property var activeNode: _reconstruction ? _reconstruction.activeNodes.get("LdrToHdrMerge").node : null
ToolTip.text: "Visualize HDR images: " + (activeNode ? activeNode.label : "No Node") ToolTip.text: "Visualize HDR images: " + (activeNode ? activeNode.label : "No Node")
iconText: MaterialIcons.filter iconText: MaterialIcons.filter
label: activeNode ? activeNode.attribute("nbBrackets").value : "" label: activeNode ? activeNode.attribute("nbBrackets").value : ""
@ -747,7 +749,7 @@ Panel {
id: imageProcessing id: imageProcessing
Layout.minimumWidth: childrenRect.width Layout.minimumWidth: childrenRect.width
property var activeNode: _reconstruction.activeNodes.get("ImageProcessing").node property var activeNode: _reconstruction ? _reconstruction.activeNodes.get("ImageProcessing").node : null
font.pointSize: 15 font.pointSize: 15
padding: 0 padding: 0
ToolTip.text: "Preprocessed Images: " + (activeNode ? activeNode.label : "No Node") ToolTip.text: "Preprocessed Images: " + (activeNode ? activeNode.label : "No Node")

View file

@ -13,7 +13,7 @@ Panel {
id: root id: root
property variant reconstruction property variant reconstruction
readonly property variant liveSfmManager: reconstruction.liveSfmManager readonly property variant liveSfmManager: reconstruction ? reconstruction.liveSfmManager : null
title: "Live Reconstruction" title: "Live Reconstruction"
icon: Label { icon: Label {
@ -41,7 +41,7 @@ Panel {
width: parent.width width: parent.width
GroupBox { GroupBox {
Layout.fillWidth: true Layout.fillWidth: true
enabled: !liveSfmManager.running enabled: liveSfmManager ? !liveSfmManager.running : false
GridLayout { GridLayout {
width: parent.width width: parent.width
@ -59,7 +59,7 @@ Panel {
id: folderPath id: folderPath
Layout.fillWidth: true Layout.fillWidth: true
selectByMouse: true selectByMouse: true
text: liveSfmManager.folder text: liveSfmManager ? liveSfmManager.folder : ""
placeholderText: "Select a Folder" placeholderText: "Select a Folder"
} }
ToolButton { ToolButton {
@ -90,8 +90,8 @@ Panel {
Button { Button {
Layout.alignment: Qt.AlignCenter Layout.alignment: Qt.AlignCenter
text: checked ? "Stop" : "Start" text: checked ? "Stop" : "Start"
enabled: liveSfmManager.running || folderPath.text.trim() != '' enabled: liveSfmManager ? liveSfmManager.running || folderPath.text.trim() != '' : false
checked: liveSfmManager.running checked: liveSfmManager ? liveSfmManager.running : false
onClicked: { onClicked: {
if(!liveSfmManager.running) if(!liveSfmManager.running)
liveSfmManager.start(folderPath.text, minImg_SB.value) liveSfmManager.start(folderPath.text, minImg_SB.value)

View file

@ -24,7 +24,7 @@ FocusScope {
property alias useLensDistortionViewer: displayLensDistortionViewer.checked property alias useLensDistortionViewer: displayLensDistortionViewer.checked
property alias usePanoramaViewer: displayPanoramaViewer.checked property alias usePanoramaViewer: displayPanoramaViewer.checked
property var activeNodeFisheye: _reconstruction.activeNodes.get("PanoramaInit").node property var activeNodeFisheye: _reconstruction ? _reconstruction.activeNodes.get("PanoramaInit").node : null
property bool cropFisheye : activeNodeFisheye ? activeNodeFisheye.attribute("useFisheye").value : false property bool cropFisheye : activeNodeFisheye ? activeNodeFisheye.attribute("useFisheye").value : false
property bool enable8bitViewer: MeshroomApp.default8bitViewerEnabled property bool enable8bitViewer: MeshroomApp.default8bitViewerEnabled
@ -202,15 +202,15 @@ FocusScope {
if (useExternal) { if (useExternal) {
return sourceExternal; return sourceExternal;
} }
if (!displayedNode || outputAttribute.name == "gallery") { if (_reconstruction && (!displayedNode || outputAttribute.name == "gallery")) {
return getViewpointPath(_reconstruction.selectedViewId); return getViewpointPath(_reconstruction.selectedViewId);
} }
return getFileAttributePath(displayedNode, outputAttribute.name, _reconstruction.selectedViewId); return getFileAttributePath(displayedNode, outputAttribute.name, _reconstruction ? _reconstruction.selectedViewId : -1);
} }
function getMetadata() { function getMetadata() {
// entry point for getting the image metadata // entry point for getting the image metadata
if (useExternal) { if (useExternal || !_reconstruction) {
return {}; return {};
} else { } else {
return getViewpointMetadata(_reconstruction.selectedViewId); return getViewpointMetadata(_reconstruction.selectedViewId);
@ -220,6 +220,8 @@ FocusScope {
function getFileAttributePath(node, attrName, viewId) { function getFileAttributePath(node, attrName, viewId) {
// get output attribute with matching name // get output attribute with matching name
// and parse its value to get the image filepath // and parse its value to get the image filepath
if (!node)
return "";
for (var i = 0; i < node.attributes.count; i++) { for (var i = 0; i < node.attributes.count; i++) {
var attr = node.attributes.at(i); var attr = node.attributes.at(i);
if (attr.name == attrName) { if (attr.name == attrName) {
@ -429,7 +431,7 @@ FocusScope {
'sfmRequired': Qt.binding(function(){ return displayLensDistortionViewer.checked ? true : false;}), 'sfmRequired': Qt.binding(function(){ return displayLensDistortionViewer.checked ? true : false;}),
'surface.msfmData': Qt.binding(function() { return (msfmDataLoader.status === Loader.Ready && msfmDataLoader.item != null && msfmDataLoader.item.status === 2) ? msfmDataLoader.item : null; }), 'surface.msfmData': Qt.binding(function() { return (msfmDataLoader.status === Loader.Ready && msfmDataLoader.item != null && msfmDataLoader.item.status === 2) ? msfmDataLoader.item : null; }),
'canBeHovered': false, 'canBeHovered': false,
'idView': Qt.binding(function() { return _reconstruction.selectedViewId; }), 'idView': Qt.binding(function() { return (_reconstruction ? _reconstruction.selectedViewId : -1); }),
'cropFisheye': false 'cropFisheye': false
}) })
} else { } else {
@ -521,7 +523,7 @@ FocusScope {
Loader { Loader {
id: featuresViewerLoader id: featuresViewerLoader
active: displayFeatures.checked active: displayFeatures.checked
property var activeNode: _reconstruction.activeNodes.get("FeatureExtraction").node property var activeNode: _reconstruction ? _reconstruction.activeNodes.get("FeatureExtraction").node : null
// handle rotation/position based on available metadata // handle rotation/position based on available metadata
rotation: { rotation: {
@ -554,7 +556,7 @@ FocusScope {
// note: use a Loader to evaluate if a PanoramaInit node exist and displayFisheyeCircle checked at runtime // note: use a Loader to evaluate if a PanoramaInit node exist and displayFisheyeCircle checked at runtime
Loader { Loader {
anchors.centerIn: parent anchors.centerIn: parent
property var activeNode: _reconstruction.activeNodes.get("PanoramaInit").node property var activeNode: _reconstruction ? _reconstruction.activeNodes.get("PanoramaInit").node : null
active: (displayFisheyeCircleLoader.checked && activeNode) active: (displayFisheyeCircleLoader.checked && activeNode)
// handle rotation/position based on available metadata // handle rotation/position based on available metadata
@ -602,7 +604,7 @@ FocusScope {
Loader { Loader {
id: colorCheckerViewerLoader id: colorCheckerViewerLoader
anchors.centerIn: parent anchors.centerIn: parent
property var activeNode: _reconstruction.activeNodes.get("ColorCheckerDetection").node property var activeNode: _reconstruction ? _reconstruction.activeNodes.get("ColorCheckerDetection").node : null
active: (displayColorCheckerViewerLoader.checked && activeNode) active: (displayColorCheckerViewerLoader.checked && activeNode)
@ -706,7 +708,7 @@ FocusScope {
id: mfeaturesLoader id: mfeaturesLoader
property bool isUsed: displayFeatures.checked property bool isUsed: displayFeatures.checked
property var activeNode: root.aliceVisionPluginAvailable ? _reconstruction.activeNodes.get("FeatureExtraction").node : null property var activeNode: root.aliceVisionPluginAvailable && _reconstruction ? _reconstruction.activeNodes.get("FeatureExtraction").node : null
property bool isComputed: activeNode && activeNode.isComputed property bool isComputed: activeNode && activeNode.isComputed
active: false active: false
@ -749,7 +751,7 @@ FocusScope {
} }
// For lens distortion viewer: use all nodes creating a sfmData file // For lens distortion viewer: use all nodes creating a sfmData file
var nodeType = displayLensDistortionViewer.checked ? 'sfmData' : 'sfm' var nodeType = displayLensDistortionViewer.checked ? 'sfmData' : 'sfm'
var sfmNode = _reconstruction.activeNodes.get(nodeType).node var sfmNode = _reconstruction ? _reconstruction.activeNodes.get(nodeType).node : null
if(sfmNode === null){ if(sfmNode === null){
return null return null
} }
@ -827,7 +829,7 @@ FocusScope {
id: mtracksLoader id: mtracksLoader
property bool isUsed: displayFeatures.checked || displaySfmStatsView.checked || displaySfmDataGlobalStats.checked || displayPanoramaViewer.checked property bool isUsed: displayFeatures.checked || displaySfmStatsView.checked || displaySfmDataGlobalStats.checked || displayPanoramaViewer.checked
property var activeNode: root.aliceVisionPluginAvailable ? _reconstruction.activeNodes.get('FeatureMatching').node : null property var activeNode: root.aliceVisionPluginAvailable && _reconstruction ? _reconstruction.activeNodes.get('FeatureMatching').node : null
property bool isComputed: activeNode && activeNode.isComputed property bool isComputed: activeNode && activeNode.isComputed
active: false active: false
@ -921,7 +923,7 @@ FocusScope {
id: ldrHdrCalibrationGraph id: ldrHdrCalibrationGraph
anchors.fill: parent anchors.fill: parent
property var activeNode: _reconstruction.activeNodes.get('LdrToHdrCalibration').node property var activeNode: _reconstruction ? _reconstruction.activeNodes.get('LdrToHdrCalibration').node : null
property var isEnabled: displayLdrHdrCalibrationGraph.checked && activeNode && activeNode.isComputed property var isEnabled: displayLdrHdrCalibrationGraph.checked && activeNode && activeNode.isComputed
// active: isEnabled // active: isEnabled
// Setting "active" from true to false creates a crash on linux with Qt 5.14.2. // Setting "active" from true to false creates a crash on linux with Qt 5.14.2.
@ -995,7 +997,7 @@ FocusScope {
} }
MaterialToolButton { MaterialToolButton {
id: displayLensDistortionViewer id: displayLensDistortionViewer
property var activeNode: root.aliceVisionPluginAvailable ? _reconstruction.activeNodes.get('sfmData').node : null property var activeNode: root.aliceVisionPluginAvailable && _reconstruction ? _reconstruction.activeNodes.get('sfmData').node : null
property bool isComputed: { property bool isComputed: {
if(!activeNode) if(!activeNode)
return false; return false;
@ -1031,7 +1033,7 @@ FocusScope {
} }
MaterialToolButton { MaterialToolButton {
id: displayPanoramaViewer id: displayPanoramaViewer
property var activeNode: root.aliceVisionPluginAvailable ? _reconstruction.activeNodes.get('SfMTransform').node : null property var activeNode: root.aliceVisionPluginAvailable && _reconstruction ? _reconstruction.activeNodes.get('SfMTransform').node : null
property bool isComputed: { property bool isComputed: {
if(!activeNode) if(!activeNode)
return false; return false;
@ -1083,7 +1085,7 @@ FocusScope {
} }
MaterialToolButton { MaterialToolButton {
id: displayFisheyeCircleLoader id: displayFisheyeCircleLoader
property var activeNode: _reconstruction.activeNodes.get('PanoramaInit').node property var activeNode: _reconstruction ? _reconstruction.activeNodes.get('PanoramaInit').node : null
ToolTip.text: "Display Fisheye Circle: " + (activeNode ? activeNode.label : "No Node") ToolTip.text: "Display Fisheye Circle: " + (activeNode ? activeNode.label : "No Node")
text: MaterialIcons.vignette text: MaterialIcons.vignette
// text: MaterialIcons.panorama_fish_eye // text: MaterialIcons.panorama_fish_eye
@ -1096,7 +1098,7 @@ FocusScope {
} }
MaterialToolButton { MaterialToolButton {
id: displayColorCheckerViewerLoader id: displayColorCheckerViewerLoader
property var activeNode: _reconstruction.activeNodes.get('ColorCheckerDetection').node property var activeNode: _reconstruction ? _reconstruction.activeNodes.get('ColorCheckerDetection').node : null
ToolTip.text: "Display Color Checker: " + (activeNode ? activeNode.label : "No Node") ToolTip.text: "Display Color Checker: " + (activeNode ? activeNode.label : "No Node")
text: MaterialIcons.view_comfy //view_module grid_on gradient view_comfy border_all text: MaterialIcons.view_comfy //view_module grid_on gradient view_comfy border_all
font.pointSize: 11 font.pointSize: 11
@ -1121,7 +1123,7 @@ FocusScope {
MaterialToolButton { MaterialToolButton {
id: displayLdrHdrCalibrationGraph id: displayLdrHdrCalibrationGraph
property var activeNode: _reconstruction.activeNodes.get("LdrToHdrCalibration").node property var activeNode: _reconstruction ? _reconstruction.activeNodes.get("LdrToHdrCalibration").node : null
property bool isComputed: activeNode && activeNode.isComputed property bool isComputed: activeNode && activeNode.isComputed
ToolTip.text: "Display Camera Response Function: " + (activeNode ? activeNode.label : "No Node") ToolTip.text: "Display Camera Response Function: " + (activeNode ? activeNode.label : "No Node")
text: MaterialIcons.timeline text: MaterialIcons.timeline
@ -1166,7 +1168,7 @@ FocusScope {
} }
MaterialToolButton { MaterialToolButton {
property var activeNode: root.oiioPluginAvailable ? _reconstruction.activeNodes.get('allDepthMap').node : null property var activeNode: root.oiioPluginAvailable && _reconstruction ? _reconstruction.activeNodes.get('allDepthMap').node : null
enabled: activeNode enabled: activeNode
ToolTip.text: "View Depth Map in 3D (" + (activeNode ? activeNode.label : "No DepthMap Node Selected") + ")" ToolTip.text: "View Depth Map in 3D (" + (activeNode ? activeNode.label : "No DepthMap Node Selected") + ")"
text: MaterialIcons.input text: MaterialIcons.input
@ -1180,7 +1182,7 @@ FocusScope {
MaterialToolButton { MaterialToolButton {
id: displaySfmStatsView id: displaySfmStatsView
property var activeNode: root.aliceVisionPluginAvailable ? _reconstruction.activeNodes.get('sfm').node : null property var activeNode: root.aliceVisionPluginAvailable && _reconstruction ? _reconstruction.activeNodes.get('sfm').node : null
font.family: MaterialIcons.fontFamily font.family: MaterialIcons.fontFamily
text: MaterialIcons.assessment text: MaterialIcons.assessment
@ -1205,7 +1207,7 @@ FocusScope {
MaterialToolButton { MaterialToolButton {
id: displaySfmDataGlobalStats id: displaySfmDataGlobalStats
property var activeNode: root.aliceVisionPluginAvailable ? _reconstruction.activeNodes.get('sfm').node : null property var activeNode: root.aliceVisionPluginAvailable && _reconstruction ? _reconstruction.activeNodes.get('sfm').node : null
font.family: MaterialIcons.fontFamily font.family: MaterialIcons.fontFamily
text: MaterialIcons.language text: MaterialIcons.language

View file

@ -64,7 +64,7 @@ AlembicEntity {
*/ */
PhongMaterial{ PhongMaterial{
id: mat id: mat
ambient: viewId === _reconstruction.selectedViewId ? activePalette.highlight : customColor // "#CCC" ambient: _reconstruction && viewId === _reconstruction.selectedViewId ? activePalette.highlight : customColor // "#CCC"
diffuse: cameraPicker.containsMouse ? Qt.lighter(activePalette.highlight, 1.2) : ambient diffuse: cameraPicker.containsMouse ? Qt.lighter(activePalette.highlight, 1.2) : ambient
}, },
ObjectPicker { ObjectPicker {

View file

@ -112,7 +112,7 @@ FloatingPane {
// Synchronization // Synchronization
MaterialToolButton { MaterialToolButton {
id: syncViewpointCamera id: syncViewpointCamera
enabled: _reconstruction.sfmReport enabled: _reconstruction ? _reconstruction.sfmReport : false
text: MaterialIcons.linked_camera text: MaterialIcons.linked_camera
ToolTip.text: "Sync with Image Selection" ToolTip.text: "Sync with Image Selection"
checked: enabled && Viewer3DSettings.syncViewpointCamera checked: enabled && Viewer3DSettings.syncViewpointCamera
@ -200,8 +200,8 @@ FloatingPane {
// add mediaLibrary.count in the binding to ensure 'entity' // add mediaLibrary.count in the binding to ensure 'entity'
// is re-evaluated when mediaLibrary delegates are modified // is re-evaluated when mediaLibrary delegates are modified
property bool loading: model.status === SceneLoader.Loading property bool loading: model.status === SceneLoader.Loading
property bool hovered: model.attribute ? uigraph.hoveredNode === model.attribute.node : containsMouse property bool hovered: model.attribute ? (uigraph ? uigraph.hoveredNode === model.attribute.node : false) : containsMouse
property bool isSelectedNode: model.attribute ? uigraph.selectedNode === model.attribute.node : false property bool isSelectedNode: model.attribute ? (uigraph ? uigraph.selectedNode === model.attribute.node : false) : false
onIsSelectedNodeChanged: updateCurrentIndex() onIsSelectedNodeChanged: updateCurrentIndex()

View file

@ -26,7 +26,7 @@ FocusScope {
readonly property vector3d defaultCamUpVector: Qt.vector3d(0.0, 1.0, 0.0) readonly property vector3d defaultCamUpVector: Qt.vector3d(0.0, 1.0, 0.0)
readonly property vector3d defaultCamViewCenter: Qt.vector3d(0.0, 0.0, 0.0) readonly property vector3d defaultCamViewCenter: Qt.vector3d(0.0, 0.0, 0.0)
readonly property var viewpoint: _reconstruction.selectedViewpoint readonly property var viewpoint: _reconstruction ? _reconstruction.selectedViewpoint : null
readonly property bool doSyncViewpointCamera: Viewer3DSettings.syncViewpointCamera && (viewpoint && viewpoint.isReconstructed) readonly property bool doSyncViewpointCamera: Viewer3DSettings.syncViewpointCamera && (viewpoint && viewpoint.isReconstructed)
// functions // functions

View file

@ -20,7 +20,7 @@ Item {
id: root id: root
property variant reconstruction: _reconstruction property variant reconstruction: _reconstruction
readonly property variant cameraInits: _reconstruction.cameraInits readonly property variant cameraInits: _reconstruction ? _reconstruction.cameraInits : null
property bool readOnly: false property bool readOnly: false
property alias panel3dViewer: panel3dViewerLoader.item property alias panel3dViewer: panel3dViewerLoader.item
readonly property Viewer2D viewer2D: viewer2D readonly property Viewer2D viewer2D: viewer2D
@ -50,7 +50,7 @@ Item {
// Load reconstruction's current SfM file // Load reconstruction's current SfM file
function viewSfM() { function viewSfM() {
var activeNode = _reconstruction.activeNodes.get('sfm').node; var activeNode = _reconstruction.activeNodes ? _reconstruction.activeNodes.get('sfm').node : null;
if(!activeNode) if(!activeNode)
return; return;
if(panel3dViewerLoader.active) { if(panel3dViewerLoader.active) {
@ -75,9 +75,9 @@ Item {
Layout.fillHeight: true Layout.fillHeight: true
readOnly: root.readOnly readOnly: root.readOnly
cameraInits: root.cameraInits cameraInits: root.cameraInits
cameraInit: reconstruction.cameraInit cameraInit: reconstruction ? reconstruction.cameraInit : null
tempCameraInit: reconstruction.tempCameraInit tempCameraInit: reconstruction ? reconstruction.tempCameraInit : null
cameraInitIndex: reconstruction.cameraInitIndex cameraInitIndex: reconstruction ? reconstruction.cameraInitIndex : -1
onRemoveImageRequest: reconstruction.removeAttribute(attribute) onRemoveImageRequest: reconstruction.removeAttribute(attribute)
onFilesDropped: reconstruction.handleFilesDrop(drop, augmentSfm ? null : cameraInit) onFilesDropped: reconstruction.handleFilesDrop(drop, augmentSfm ? null : cameraInit)
} }
@ -208,7 +208,7 @@ Item {
// Load reconstructed model // Load reconstructed model
Button { Button {
readonly property var outputAttribute: _reconstruction.texturing ? _reconstruction.texturing.attribute("outputMesh") : null readonly property var outputAttribute: _reconstruction && _reconstruction.texturing ? _reconstruction.texturing.attribute("outputMesh") : null
readonly property bool outputReady: outputAttribute && _reconstruction.texturing.globalStatus === "SUCCESS" readonly property bool outputReady: outputAttribute && _reconstruction.texturing.globalStatus === "SUCCESS"
readonly property int outputMediaIndex: c_viewer3D.library.find(outputAttribute) readonly property int outputMediaIndex: c_viewer3D.library.find(outputAttribute)

View file

@ -24,8 +24,8 @@ ApplicationWindow {
visible: true visible: true
title: { title: {
var t = (_reconstruction.graph && _reconstruction.graph.filepath) ? _reconstruction.graph.filepath : "Untitled" var t = (_reconstruction && _reconstruction.graph && _reconstruction.graph.filepath) ? _reconstruction.graph.filepath : "Untitled"
if(!_reconstruction.undoStack.clean) if (_reconstruction && !_reconstruction.undoStack.clean)
t += "*" t += "*"
t += " - " + Qt.application.name + " " + Qt.application.version t += " - " + Qt.application.name + " " + Qt.application.version
return t return t
@ -73,12 +73,12 @@ ApplicationWindow {
property var _callback: undefined property var _callback: undefined
title: Filepath.basename(_reconstruction.graph.filepath) || "Unsaved Project" title: (_reconstruction ? Filepath.basename(_reconstruction.graph.filepath) : "") || "Unsaved Project"
preset: "Info" preset: "Info"
canCopy: false canCopy: false
text: _reconstruction.graph.filepath ? "Current project has unsaved modifications." text: _reconstruction && _reconstruction.graph.filepath ? "Current project has unsaved modifications."
: "Current project has not been saved." : "Current project has not been saved."
helperText: _reconstruction.graph.filepath ? "Would you like to save those changes?" helperText: _reconstruction && _reconstruction.graph.filepath ? "Would you like to save those changes?"
: "Would you like to save this project?" : "Would you like to save this project?"
standardButtons: Dialog.Save | Dialog.Cancel | Dialog.Discard standardButtons: Dialog.Save | Dialog.Cancel | Dialog.Discard
@ -165,14 +165,18 @@ ApplicationWindow {
property bool warnIfUnsaved: true property bool warnIfUnsaved: true
// evaluate if global reconstruction computation can be started // evaluate if global reconstruction computation can be started
property bool canStartComputation: _reconstruction.viewpoints.count >= 2 // at least 2 images property bool canStartComputation: _reconstruction ?
&& !_reconstruction.computing // computation is not started _reconstruction.viewpoints.count >= 2 // at least 2 images
&& _reconstruction.graph.canComputeLeaves // graph has no uncomputable nodes && !_reconstruction.computing // computation is not started
&& _reconstruction.graph.canComputeLeaves : // graph has no uncomputable nodes
false
// evaluate if graph computation can be submitted externally // evaluate if graph computation can be submitted externally
property bool canSubmit: _reconstruction.canSubmit // current setup allows to compute externally property bool canSubmit: _reconstruction ?
&& canStartComputation // can be computed _reconstruction.canSubmit // current setup allows to compute externally
&& _reconstruction.graph.filepath // graph is saved on disk && canStartComputation // can be computed
&& _reconstruction.graph.filepath : // graph is saved on disk
false
function compute(node, force) { function compute(node, force) {
if(!force && warnIfUnsaved && !_reconstruction.graph.filepath) if(!force && warnIfUnsaved && !_reconstruction.graph.filepath)
@ -276,7 +280,7 @@ ApplicationWindow {
preset: "Warning" preset: "Warning"
title: "Unsaved Project" title: "Unsaved Project"
text: "Data will be computed in the default cache folder if project remains unsaved." text: "Data will be computed in the default cache folder if project remains unsaved."
detailedText: "Default cache folder: " + _reconstruction.graph.cacheDir detailedText: "Default cache folder: " + (_reconstruction ? _reconstruction.graph.cacheDir : "unknown")
helperText: "Save project first?" helperText: "Save project first?"
standardButtons: Dialog.Discard | Dialog.Cancel | Dialog.Save standardButtons: Dialog.Discard | Dialog.Cancel | Dialog.Save
@ -377,7 +381,7 @@ ApplicationWindow {
// is busy building intrinsics while importing images // is busy building intrinsics while importing images
id: buildingIntrinsicsDialog id: buildingIntrinsicsDialog
modal: true modal: true
visible: _reconstruction.buildingIntrinsics visible: _reconstruction ? _reconstruction.buildingIntrinsics : false
closePolicy: Popup.NoAutoClose closePolicy: Popup.NoAutoClose
title: "Initializing Cameras" title: "Initializing Cameras"
icon.text: MaterialIcons.camera icon.text: MaterialIcons.camera
@ -404,19 +408,19 @@ ApplicationWindow {
Action { Action {
id: undoAction id: undoAction
property string tooltip: 'Undo "' +_reconstruction.undoStack.undoText +'"' property string tooltip: 'Undo "' + (_reconstruction ? _reconstruction.undoStack.undoText : "Unknown") + '"'
text: "Undo" text: "Undo"
shortcut: "Ctrl+Z" shortcut: "Ctrl+Z"
enabled: _reconstruction.undoStack.canUndo && _reconstruction.undoStack.isUndoableIndex enabled: _reconstruction ? _reconstruction.undoStack.canUndo && _reconstruction.undoStack.isUndoableIndex : false
onTriggered: _reconstruction.undoStack.undo() onTriggered: _reconstruction.undoStack.undo()
} }
Action { Action {
id: redoAction id: redoAction
property string tooltip: 'Redo "' +_reconstruction.undoStack.redoText +'"' property string tooltip: 'Redo "' + (_reconstruction ? _reconstruction.undoStack.redoText : "Unknown") + '"'
text: "Redo" text: "Redo"
shortcut: "Ctrl+Shift+Z" shortcut: "Ctrl+Shift+Z"
enabled: _reconstruction.undoStack.canRedo && !_reconstruction.undoStack.lockedRedo enabled: _reconstruction ? _reconstruction.undoStack.canRedo && !_reconstruction.undoStack.lockedRedo : false
onTriggered: _reconstruction.undoStack.redo() onTriggered: _reconstruction.undoStack.redo()
} }
Action { Action {
@ -424,16 +428,18 @@ ApplicationWindow {
property string tooltip: { property string tooltip: {
var s = "Copy selected node" var s = "Copy selected node"
s += (_reconstruction.selectedNodes.count > 1 ? "s (" : " (") + getSelectedNodesName() s += (_reconstruction && _reconstruction.selectedNodes.count > 1 ? "s (" : " (") + getSelectedNodesName()
s += ") to the clipboard" s += ") to the clipboard"
return s return s
} }
text: "Copy Node" + (_reconstruction.selectedNodes.count > 1 ? "s " : " ") text: "Copy Node" + (_reconstruction && _reconstruction.selectedNodes.count > 1 ? "s " : " ")
enabled: _reconstruction.selectedNodes.count > 0 enabled: _reconstruction ? _reconstruction.selectedNodes.count > 0 : false
onTriggered: graphEditor.copyNodes() onTriggered: graphEditor.copyNodes()
function getSelectedNodesName() function getSelectedNodesName()
{ {
if (!_reconstruction)
return ""
var nodesName = "" var nodesName = ""
for (var i = 0; i < _reconstruction.selectedNodes.count; i++) for (var i = 0; i < _reconstruction.selectedNodes.count; i++)
{ {
@ -612,7 +618,7 @@ ApplicationWindow {
id: saveAction id: saveAction
text: "Save" text: "Save"
shortcut: "Ctrl+S" shortcut: "Ctrl+S"
enabled: (_reconstruction.graph && !_reconstruction.graph.filepath) || !_reconstruction.undoStack.clean enabled: _reconstruction ? (_reconstruction.graph && !_reconstruction.graph.filepath) || !_reconstruction.undoStack.clean : false
onTriggered: { onTriggered: {
if(_reconstruction.graph.filepath) { if(_reconstruction.graph.filepath) {
_reconstruction.save() _reconstruction.save()
@ -742,7 +748,7 @@ ApplicationWindow {
TextField { TextField {
readOnly: true readOnly: true
selectByMouse: true selectByMouse: true
text: _reconstruction.graph.cacheDir text: _reconstruction ? _reconstruction.graph.cacheDir : "Unknown"
color: Qt.darker(palette.text, 1.2) color: Qt.darker(palette.text, 1.2)
background: Item {} background: Item {}
} }
@ -809,12 +815,12 @@ ApplicationWindow {
} }
Button { Button {
text: "Stop" text: "Stop"
enabled: _reconstruction.computingLocally enabled: _reconstruction ? _reconstruction.computingLocally : false
onClicked: _reconstruction.stopExecution() onClicked: _reconstruction.stopExecution()
} }
Item { width: 20; height: 1 } Item { width: 20; height: 1 }
Button { Button {
visible: _reconstruction.canSubmit visible: _reconstruction ? _reconstruction.canSubmit : false
text: "Submit" text: "Submit"
onClicked: computeManager.submit(null) onClicked: computeManager.submit(null)
} }
@ -839,7 +845,7 @@ ApplicationWindow {
id: chunksListView id: chunksListView
Layout.fillWidth: true Layout.fillWidth: true
height: 6 height: 6
model: _reconstruction.sortedDFSChunks model: _reconstruction ? _reconstruction.sortedDFSChunks : null
} }
WorkspaceView { WorkspaceView {
@ -848,7 +854,7 @@ ApplicationWindow {
Layout.fillHeight: true Layout.fillHeight: true
Layout.minimumHeight: 50 Layout.minimumHeight: 50
reconstruction: _reconstruction reconstruction: _reconstruction
readOnly: _reconstruction.computing readOnly: _reconstruction ? _reconstruction.computing : false
function viewNode(node, mouse) { function viewNode(node, mouse) {
// 2D viewer // 2D viewer
@ -899,7 +905,7 @@ ApplicationWindow {
updatingStatus = false updatingStatus = false
} }
property bool updatingStatus: false property bool updatingStatus: false
enabled: !updatingStatus && !_reconstruction.computingLocally enabled: !updatingStatus && (_reconstruction ? !_reconstruction.computingLocally : false)
} }
MaterialToolButton { MaterialToolButton {
text: MaterialIcons.more_vert text: MaterialIcons.more_vert
@ -914,7 +920,7 @@ ApplicationWindow {
x: -width + parent.width x: -width + parent.width
MenuItem { MenuItem {
text: "Clear Pending Status" text: "Clear Pending Status"
enabled: !_reconstruction.computingLocally enabled: _reconstruction ? !_reconstruction.computingLocally : false
onTriggered: _reconstruction.graph.clearSubmittedNodes() onTriggered: _reconstruction.graph.clearSubmittedNodes()
} }
MenuItem { MenuItem {
@ -948,7 +954,7 @@ ApplicationWindow {
visible: graphEditorPanel.currentTab === 1 visible: graphEditorPanel.currentTab === 1
uigraph: _reconstruction uigraph: _reconstruction
taskManager: _reconstruction.taskManager taskManager: _reconstruction ? _reconstruction.taskManager : null
anchors.fill: parent anchors.fill: parent
} }
@ -958,8 +964,8 @@ ApplicationWindow {
NodeEditor { NodeEditor {
id: nodeEditor id: nodeEditor
width: Math.round(parent.width * 0.3) width: Math.round(parent.width * 0.3)
node: _reconstruction.selectedNode node: _reconstruction ? _reconstruction.selectedNode : null
property bool computing: _reconstruction.computing property bool computing: _reconstruction ? _reconstruction.computing : false
// Make NodeEditor readOnly when computing // Make NodeEditor readOnly when computing
readOnly: node ? node.locked : false readOnly: node ? node.locked : false