mirror of
https://github.com/alicevision/Meshroom.git
synced 2025-05-22 05:26:29 +02:00
[ui] Viewer2D: refactoring to simplify layouts
* fix mousearea order * add alpha backgroud * move HDR as a tool button Conflicts: meshroom/ui/qml/Viewer/CircleGizmo.qml meshroom/ui/qml/Viewer/Viewer2D.qml
This commit is contained in:
parent
c9c24b7ff0
commit
d70c625fac
4 changed files with 323 additions and 290 deletions
BIN
meshroom/ui/img/checkerboard_light.png
Normal file
BIN
meshroom/ui/img/checkerboard_light.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 102 B |
|
@ -46,8 +46,8 @@ FloatingPane {
|
|||
id: displayModeCB
|
||||
flat: true
|
||||
Layout.fillWidth: true
|
||||
model: featuresViewer.displayModes
|
||||
onActivated: featuresViewer.displayMode = currentIndex
|
||||
model: root.featuresViewer.displayModes
|
||||
onActivated: root.featuresViewer.displayMode = currentIndex
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -67,12 +67,12 @@ FloatingPane {
|
|||
implicitHeight: contentHeight
|
||||
implicitWidth: contentItem.childrenRect.width
|
||||
|
||||
model: featuresViewer !== null ? featuresViewer.model : 0
|
||||
model: root.featuresViewer !== null ? root.featuresViewer.model : 0
|
||||
|
||||
delegate: RowLayout {
|
||||
id: featureType
|
||||
|
||||
property var viewer: featuresViewer.itemAt(index)
|
||||
property var viewer: root.featuresViewer.itemAt(index)
|
||||
spacing: 4
|
||||
|
||||
// Visibility toogle
|
||||
|
@ -86,10 +86,10 @@ FloatingPane {
|
|||
ColorChart {
|
||||
implicitWidth: 12
|
||||
implicitHeight: implicitWidth
|
||||
colors: featuresViewer.colors
|
||||
colors: root.featuresViewer.colors
|
||||
currentIndex: featureType.viewer.colorIndex
|
||||
// offset FeaturesViewer color set when changing the color of one feature type
|
||||
onColorPicked: featuresViewer.colorOffset = colorIndex - index
|
||||
// offset featuresViewer color set when changing the color of one feature type
|
||||
onColorPicked: root.featuresViewer.colorOffset = colorIndex - index
|
||||
}
|
||||
// Feature type name
|
||||
Label {
|
||||
|
|
|
@ -13,9 +13,9 @@ FocusScope {
|
|||
property var metadata
|
||||
property var viewIn3D
|
||||
|
||||
property Component floatViewerComp: Qt.createComponent("FloatImage.qml", imgContainer)
|
||||
property Component floatViewerComp: Qt.createComponent("FloatImage.qml")
|
||||
readonly property bool floatViewerAvailable: floatViewerComp.status === Component.Ready
|
||||
property bool useFloatImageViewer: false
|
||||
property alias useFloatImageViewer: displayHDR.checked
|
||||
|
||||
function clear()
|
||||
{
|
||||
|
@ -31,148 +31,6 @@ FocusScope {
|
|||
}
|
||||
}
|
||||
|
||||
// functions
|
||||
function fit() {
|
||||
if(imgContainer.image.status != Image.Ready)
|
||||
return;
|
||||
imgContainer.scale = Math.min(imgContainer.width/imgContainer.image.width, imgContainer.height/imgContainer.image.height)
|
||||
imgContainer.x = Math.max((imgContainer.width-imgContainer.width*imgContainer.scale)*0.5, 0)
|
||||
imgContainer.y = Math.max((imgContainer.height-imgContainer.height*imgContainer.scale)*0.5, 0)
|
||||
}
|
||||
|
||||
function getImageFile(type) {
|
||||
if (type == "image") {
|
||||
return root.source;
|
||||
} else if (_reconstruction.depthMap != undefined && _reconstruction.selectedViewId >= 0) {
|
||||
return Filepath.stringToUrl(_reconstruction.depthMap.internalFolder+_reconstruction.selectedViewId+"_"+type+"Map.exr");
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
// context menu
|
||||
property Component contextMenu: Menu {
|
||||
MenuItem {
|
||||
text: "Fit"
|
||||
onTriggered: fit()
|
||||
}
|
||||
MenuItem {
|
||||
text: "Zoom 100%"
|
||||
onTriggered: {
|
||||
imgContainer.scale = 1
|
||||
imgContainer.x = Math.max((imgContainer.width-imgContainer.width*imgContainer.scale)*0.5, 0)
|
||||
imgContainer.y = Math.max((imgContainer.height-imgContainer.height*imgContainer.scale)*0.5, 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Image
|
||||
Item {
|
||||
id: imgContainer
|
||||
transformOrigin: Item.TopLeft
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
|
||||
property var image: qtImageViewerLoader.active ? qtImageViewerLoader.item : floatImageViewerLoader.item
|
||||
|
||||
// qtAliceVision Image Viewer
|
||||
Loader {
|
||||
id: floatImageViewerLoader
|
||||
active: root.useFloatImageViewer
|
||||
visible: (floatImageViewerLoader.status === Loader.Ready)
|
||||
anchors.centerIn: parent
|
||||
|
||||
Component.onCompleted: {
|
||||
// instantiate and initialize a FeaturesViewer component dynamically using Loader.setSource
|
||||
// Note: It does not work to use previously created component,
|
||||
// so we re-create it with setSource.
|
||||
// floatViewerComp.createObject(floatImageViewerLoader, {
|
||||
setSource("FloatImage.qml", {
|
||||
'source': Qt.binding(function() { return getImageFile(imageType.type); }),
|
||||
'gamma': Qt.binding(function() { return imageToolbar.gammaValue; }),
|
||||
'offset': Qt.binding(function() { return imageToolbar.offsetValue; }),
|
||||
'channelModeString': Qt.binding(function() { return imageToolbar.channelModeValue; }),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Simple QML Image Viewer (using Qt or qtOIIO to load images)
|
||||
Loader {
|
||||
id: qtImageViewerLoader
|
||||
active: (!root.useFloatImageViewer) || (floatImageViewerLoader.status === Loader.Error)
|
||||
anchors.centerIn: parent
|
||||
sourceComponent: Image {
|
||||
id: qtImageViewer
|
||||
asynchronous: true
|
||||
smooth: false
|
||||
fillMode: Image.PreserveAspectFit
|
||||
autoTransform: true
|
||||
onWidthChanged: if(status==Image.Ready) fit()
|
||||
source: getImageFile(imageType.type)
|
||||
onStatusChanged: {
|
||||
// update cache source when image is loaded
|
||||
if(status === Image.Ready)
|
||||
qtImageViewerCache.source = source
|
||||
}
|
||||
|
||||
// Image cache of the last loaded image
|
||||
// Only visible when the main one is loading, to keep an image
|
||||
// displayed at all time and smoothen transitions
|
||||
Image {
|
||||
id: qtImageViewerCache
|
||||
|
||||
anchors.fill: parent
|
||||
asynchronous: true
|
||||
smooth: parent.smooth
|
||||
fillMode: parent.fillMode
|
||||
autoTransform: parent.autoTransform
|
||||
|
||||
visible: qtImageViewer.status === Image.Loading
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// FeatureViewer: display view extracted feature points
|
||||
// note: requires QtAliceVision plugin - use a Loader to evaluate plugin avaibility at runtime
|
||||
Loader {
|
||||
id: featuresViewerLoader
|
||||
|
||||
active: displayFeatures.checked
|
||||
|
||||
// handle rotation/position based on available metadata
|
||||
rotation: {
|
||||
var orientation = metadata ? metadata["Orientation"] : 0
|
||||
switch(orientation) {
|
||||
case "6": return 90;
|
||||
case "8": return -90;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
x: (imgContainer.image && rotation === 90) ? imgContainer.image.paintedWidth : 0
|
||||
y: (imgContainer.image && rotation === -90) ? imgContainer.image.paintedHeight : 0
|
||||
|
||||
Component.onCompleted: {
|
||||
// instantiate and initialize a FeaturesViewer component dynamically using Loader.setSource
|
||||
setSource("FeaturesViewer.qml", {
|
||||
'active': Qt.binding(function() { return displayFeatures.checked; }),
|
||||
'viewId': Qt.binding(function() { return _reconstruction.selectedViewId; }),
|
||||
'model': Qt.binding(function() { return _reconstruction.featureExtraction.attribute("describerTypes").value; }),
|
||||
'folder': Qt.binding(function() { return Filepath.stringToUrl(_reconstruction.featureExtraction.attribute("output").value); }),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Busy indicator
|
||||
BusyIndicator {
|
||||
anchors.centerIn: parent
|
||||
// running property binding seems broken, only dynamic binding assignment works
|
||||
Component.onCompleted: {
|
||||
running = Qt.binding(function() { return imgContainer.image && imgContainer.image.status === Image.Loading })
|
||||
}
|
||||
// disable the visibility when unused to avoid stealing the mouseEvent to the image color picker
|
||||
visible: running
|
||||
}
|
||||
|
||||
// mouse area
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
|
@ -203,12 +61,44 @@ FocusScope {
|
|||
}
|
||||
}
|
||||
|
||||
// functions
|
||||
function fit() {
|
||||
if(imgContainer.image.status != Image.Ready)
|
||||
return;
|
||||
imgContainer.scale = Math.min(imgLayout.width / imgContainer.image.width, root.height / imgContainer.image.height)
|
||||
imgContainer.x = Math.max((imgLayout.width - imgContainer.image.width * imgContainer.scale)*0.5, 0)
|
||||
imgContainer.y = Math.max((imgLayout.height - imgContainer.image.height * imgContainer.scale)*0.5, 0)
|
||||
// console.warn("fit: imgLayout.width: " + imgContainer.scale + ", imgContainer.image.width: " + imgContainer.image.width)
|
||||
// console.warn("fit: imgContainer.scale: " + imgContainer.scale + ", x: " + imgContainer.x + ", y: " + imgContainer.y)
|
||||
}
|
||||
|
||||
function getImageFile(type) {
|
||||
if (type == "image") {
|
||||
return root.source;
|
||||
} else if (_reconstruction.depthMap != undefined && _reconstruction.selectedViewId >= 0) {
|
||||
return Filepath.stringToUrl(_reconstruction.depthMap.internalFolder+_reconstruction.selectedViewId+"_"+type+"Map.exr");
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
// context menu
|
||||
property Component contextMenu: Menu {
|
||||
MenuItem {
|
||||
text: "Fit"
|
||||
onTriggered: fit()
|
||||
}
|
||||
MenuItem {
|
||||
text: "Zoom 100%"
|
||||
onTriggered: {
|
||||
imgContainer.scale = 1
|
||||
imgContainer.x = Math.max((imgLayout.width-imgContainer.width*imgContainer.scale)*0.5, 0)
|
||||
imgContainer.y = Math.max((imgLayout.height-imgContainer.height*imgContainer.scale)*0.5, 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: topToolbar
|
||||
anchors.top: parent.top
|
||||
anchors.margins: 0
|
||||
width: parent.width
|
||||
spacing: 0
|
||||
anchors.fill: parent
|
||||
|
||||
ImageToolbar {
|
||||
id: imageToolbar
|
||||
|
@ -232,147 +122,300 @@ FocusScope {
|
|||
}
|
||||
}
|
||||
|
||||
FloatingPane {
|
||||
id: imagePathToolbar
|
||||
anchors.margins: 0
|
||||
radius: 0
|
||||
padding: 4
|
||||
visible: displayImagePathAction.checked
|
||||
// Image
|
||||
Item {
|
||||
id: imgLayout
|
||||
Layout.fillWidth: true
|
||||
|
||||
RowLayout {
|
||||
Layout.fillHeight: true
|
||||
clip: true
|
||||
Image {
|
||||
id: alphaBackground
|
||||
anchors.fill: parent
|
||||
|
||||
// selectable filepath to source image
|
||||
TextField {
|
||||
padding: 0
|
||||
background: Item {}
|
||||
horizontalAlignment: TextInput.AlignLeft
|
||||
Layout.fillWidth: true
|
||||
font.pointSize: 8
|
||||
readOnly: true
|
||||
selectByMouse: true
|
||||
text: Filepath.urlToString(getImageFile(imageType.type))
|
||||
}
|
||||
|
||||
// show which depthmap node is active
|
||||
Label {
|
||||
id: depthMapNodeName
|
||||
visible: (_reconstruction.depthMap != undefined) && (imageType.type != "image")
|
||||
text: (_reconstruction.depthMap != undefined ? _reconstruction.depthMap.label : "")
|
||||
font.pointSize: 8
|
||||
|
||||
horizontalAlignment: TextInput.AlignLeft
|
||||
Layout.fillWidth: false
|
||||
Layout.preferredWidth: contentWidth
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Image Metadata overlay Pane
|
||||
ImageMetadataView {
|
||||
width: 350
|
||||
anchors {
|
||||
top: topToolbar.bottom
|
||||
right: parent.right
|
||||
bottom: bottomToolbar.top
|
||||
}
|
||||
|
||||
visible: metadataCB.checked
|
||||
// only load metadata model if visible
|
||||
metadata: visible ? root.metadata : {}
|
||||
}
|
||||
|
||||
|
||||
Loader {
|
||||
id: featuresOverlay
|
||||
anchors.bottom: bottomToolbar.top
|
||||
anchors.left: parent.left
|
||||
anchors.margins: 2
|
||||
active: displayFeatures.checked
|
||||
|
||||
sourceComponent: FeaturesInfoOverlay {
|
||||
featureExtractionNode: _reconstruction.featureExtraction
|
||||
pluginStatus: featuresViewerLoader.status
|
||||
featuresViewer: featuresViewerLoader.item
|
||||
}
|
||||
}
|
||||
|
||||
FloatingPane {
|
||||
id: bottomToolbar
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.margins: 0
|
||||
width: parent.width
|
||||
topPadding: 2
|
||||
bottomPadding: topPadding
|
||||
|
||||
RowLayout {
|
||||
anchors.fill: parent
|
||||
|
||||
// zoom label
|
||||
Label {
|
||||
text: ((imgContainer.image && (imgContainer.image.status == Image.Ready)) ? imgContainer.scale.toFixed(2) : "1.00") + "x"
|
||||
state: "xsmall"
|
||||
}
|
||||
MaterialToolButton {
|
||||
id: displayFeatures
|
||||
font.pointSize: 11
|
||||
ToolTip.text: "Display Features"
|
||||
checkable: true
|
||||
text: MaterialIcons.scatter_plot
|
||||
visible: displayAlphaBackground.checked
|
||||
fillMode: Image.Tile
|
||||
horizontalAlignment: Image.AlignLeft
|
||||
verticalAlignment: Image.AlignTop
|
||||
source: "../../img/checkerboard_light.png"
|
||||
scale: 4
|
||||
smooth: false
|
||||
}
|
||||
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
Label {
|
||||
id: resolutionLabel
|
||||
text: imgContainer.image ? (imgContainer.image.sourceSize.width + "x" + imgContainer.image.sourceSize.height) : ""
|
||||
id: imgContainer
|
||||
transformOrigin: Item.TopLeft
|
||||
|
||||
// qtAliceVision Image Viewer
|
||||
Loader {
|
||||
id: floatImageViewerLoader
|
||||
active: root.useFloatImageViewer
|
||||
visible: (floatImageViewerLoader.status === Loader.Ready)
|
||||
anchors.centerIn: parent
|
||||
elide: Text.ElideMiddle
|
||||
|
||||
Component.onCompleted: {
|
||||
// instantiate and initialize a FeaturesViewer component dynamically using Loader.setSource
|
||||
// Note: It does not work to use previously created component,
|
||||
// so we re-create it with setSource.
|
||||
// floatViewerComp.createObject(floatImageViewerLoader, {
|
||||
setSource("FloatImage.qml", {
|
||||
'source': Qt.binding(function() { return getImageFile(imageType.type); }),
|
||||
'gamma': Qt.binding(function() { return imageToolbar.gammaValue; }),
|
||||
'offset': Qt.binding(function() { return imageToolbar.offsetValue; }),
|
||||
'channelModeString': Qt.binding(function() { return imageToolbar.channelModeValue; }),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Simple QML Image Viewer (using Qt or qtOIIO to load images)
|
||||
Loader {
|
||||
id: qtImageViewerLoader
|
||||
active: (!root.useFloatImageViewer) || (floatImageViewerLoader.status === Loader.Error)
|
||||
anchors.centerIn: parent
|
||||
sourceComponent: Image {
|
||||
id: qtImageViewer
|
||||
asynchronous: true
|
||||
smooth: false
|
||||
fillMode: Image.PreserveAspectFit
|
||||
autoTransform: true
|
||||
onWidthChanged: if(status==Image.Ready) fit()
|
||||
source: getImageFile(imageType.type)
|
||||
onStatusChanged: {
|
||||
// update cache source when image is loaded
|
||||
if(status === Image.Ready)
|
||||
qtImageViewerCache.source = source
|
||||
}
|
||||
|
||||
// Image cache of the last loaded image
|
||||
// Only visible when the main one is loading, to keep an image
|
||||
// displayed at all time and smoothen transitions
|
||||
Image {
|
||||
id: qtImageViewerCache
|
||||
|
||||
anchors.fill: parent
|
||||
asynchronous: true
|
||||
smooth: parent.smooth
|
||||
fillMode: parent.fillMode
|
||||
autoTransform: parent.autoTransform
|
||||
|
||||
visible: qtImageViewer.status === Image.Loading
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
property var image: qtImageViewerLoader.active ? qtImageViewerLoader.item : floatImageViewerLoader.item
|
||||
width: image ? image.width : 1
|
||||
height: image ? image.height : 1
|
||||
scale: 1.0
|
||||
|
||||
// FeatureViewer: display view extracted feature points
|
||||
// note: requires QtAliceVision plugin - use a Loader to evaluate plugin avaibility at runtime
|
||||
Loader {
|
||||
id: featuresViewerLoader
|
||||
|
||||
active: displayFeatures.checked
|
||||
|
||||
// handle rotation/position based on available metadata
|
||||
rotation: {
|
||||
var orientation = metadata ? metadata["Orientation"] : 0
|
||||
switch(orientation) {
|
||||
case "6": return 90;
|
||||
case "8": return -90;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
x: (imgContainer.image && rotation === 90) ? imgContainer.image.paintedWidth : 0
|
||||
y: (imgContainer.image && rotation === -90) ? imgContainer.image.paintedHeight : 0
|
||||
|
||||
Component.onCompleted: {
|
||||
// instantiate and initialize a FeaturesViewer component dynamically using Loader.setSource
|
||||
setSource("FeaturesViewer.qml", {
|
||||
'active': Qt.binding(function() { return displayFeatures.checked; }),
|
||||
'viewId': Qt.binding(function() { return _reconstruction.selectedViewId; }),
|
||||
'model': Qt.binding(function() { return _reconstruction.featureExtraction.attribute("describerTypes").value; }),
|
||||
'folder': Qt.binding(function() { return Filepath.stringToUrl(_reconstruction.featureExtraction.attribute("output").value); }),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ComboBox {
|
||||
id: imageType
|
||||
// set min size to 5 characters + one margin for the combobox
|
||||
Layout.minimumWidth: 6.0 * Qt.application.font.pixelSize
|
||||
Layout.preferredWidth: Layout.minimumWidth
|
||||
flat: true
|
||||
|
||||
property var types: ["image", "depth", "sim"]
|
||||
property string type: types[currentIndex]
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
spacing: 0
|
||||
FloatingPane {
|
||||
id: imagePathToolbar
|
||||
Layout.fillWidth: true
|
||||
// Layout.fillHeight: true
|
||||
Layout.preferredHeight: childrenRect.height
|
||||
visible: displayImagePathAction.checked
|
||||
|
||||
model: types
|
||||
enabled: _reconstruction.depthMap != undefined
|
||||
}
|
||||
RowLayout {
|
||||
width: parent.width
|
||||
height: childrenRect.height
|
||||
|
||||
MaterialToolButton {
|
||||
font.pointSize: 11
|
||||
enabled: _reconstruction.depthMap != undefined
|
||||
ToolTip.text: "View Depth Map in 3D (" + (_reconstruction.depthMap != undefined ? _reconstruction.depthMap.label : "No DepthMap Node Selected") + ")"
|
||||
text: MaterialIcons.input
|
||||
// selectable filepath to source image
|
||||
TextField {
|
||||
padding: 0
|
||||
background: Item {}
|
||||
horizontalAlignment: TextInput.AlignLeft
|
||||
Layout.fillWidth: true
|
||||
height: contentHeight
|
||||
font.pointSize: 8
|
||||
readOnly: true
|
||||
selectByMouse: true
|
||||
text: Filepath.urlToString(getImageFile(imageType.type))
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
root.viewIn3D(root.getImageFile("depth"))
|
||||
// show which depthmap node is active
|
||||
Label {
|
||||
id: depthMapNodeName
|
||||
visible: (_reconstruction.depthMap != undefined) && (imageType.type != "image")
|
||||
text: (_reconstruction.depthMap != undefined ? _reconstruction.depthMap.label : "")
|
||||
font.pointSize: 8
|
||||
|
||||
horizontalAlignment: TextInput.AlignLeft
|
||||
Layout.fillWidth: false
|
||||
Layout.preferredWidth: contentWidth
|
||||
height: contentHeight
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Item {
|
||||
id: imgPlaceholder
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
|
||||
ToolButton {
|
||||
id: metadataCB
|
||||
padding: 3
|
||||
// Image Metadata overlay Pane
|
||||
ImageMetadataView {
|
||||
width: 350
|
||||
anchors {
|
||||
top: parent.top
|
||||
right: parent.right
|
||||
bottom: parent.bottom
|
||||
}
|
||||
|
||||
font.family: MaterialIcons.fontFamily
|
||||
text: MaterialIcons.info_outline
|
||||
visible: metadataCB.checked
|
||||
// only load metadata model if visible
|
||||
metadata: visible ? root.metadata : {}
|
||||
}
|
||||
|
||||
ToolTip.text: "Image Metadata"
|
||||
ToolTip.visible: hovered
|
||||
Loader {
|
||||
id: featuresOverlay
|
||||
anchors {
|
||||
bottom: parent.bottom
|
||||
left: parent.left
|
||||
margins: 2
|
||||
}
|
||||
active: displayFeatures.checked
|
||||
|
||||
font.pointSize: 12
|
||||
smooth: false
|
||||
flat: true
|
||||
checkable: enabled
|
||||
sourceComponent: FeaturesInfoOverlay {
|
||||
featureExtractionNode: _reconstruction.featureExtraction
|
||||
pluginStatus: featuresViewerLoader.status
|
||||
featuresViewer: featuresViewerLoader.item
|
||||
}
|
||||
}
|
||||
}
|
||||
FloatingPane {
|
||||
id: bottomToolbar
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: childrenRect.height
|
||||
|
||||
RowLayout {
|
||||
anchors.fill: parent
|
||||
|
||||
// zoom label
|
||||
Label {
|
||||
text: ((imgContainer.image && (imgContainer.image.status == Image.Ready)) ? imgContainer.scale.toFixed(2) : "1.00") + "x"
|
||||
state: "xsmall"
|
||||
}
|
||||
MaterialToolButton {
|
||||
id: displayAlphaBackground
|
||||
font.pointSize: 11
|
||||
ToolTip.text: "Alpha Background"
|
||||
checkable: true
|
||||
text: MaterialIcons.texture
|
||||
}
|
||||
MaterialToolButton {
|
||||
id: displayHDR
|
||||
font.pointSize: 20
|
||||
padding: 0
|
||||
ToolTip.text: "HDR Floating Point Viewer"
|
||||
text: MaterialIcons.hdr_on
|
||||
checkable: true
|
||||
checked: false
|
||||
enabled: root.floatViewerAvailable
|
||||
}
|
||||
MaterialToolButton {
|
||||
id: displayFeatures
|
||||
font.pointSize: 11
|
||||
ToolTip.text: "Display Features"
|
||||
checkable: true
|
||||
text: MaterialIcons.scatter_plot
|
||||
}
|
||||
|
||||
Item {
|
||||
Layout.fillWidth: true
|
||||
Label {
|
||||
id: resolutionLabel
|
||||
text: imgContainer.image ? (imgContainer.image.sourceSize.width + "x" + imgContainer.image.sourceSize.height) : ""
|
||||
anchors.centerIn: parent
|
||||
elide: Text.ElideMiddle
|
||||
}
|
||||
}
|
||||
|
||||
ComboBox {
|
||||
id: imageType
|
||||
// set min size to 5 characters + one margin for the combobox
|
||||
Layout.minimumWidth: 6.0 * Qt.application.font.pixelSize
|
||||
Layout.preferredWidth: Layout.minimumWidth
|
||||
flat: true
|
||||
|
||||
property var types: ["image", "depth", "sim"]
|
||||
property string type: types[currentIndex]
|
||||
|
||||
model: types
|
||||
enabled: _reconstruction.depthMap != undefined
|
||||
}
|
||||
|
||||
MaterialToolButton {
|
||||
font.pointSize: 11
|
||||
enabled: _reconstruction.depthMap != undefined
|
||||
ToolTip.text: "View Depth Map in 3D (" + (_reconstruction.depthMap != undefined ? _reconstruction.depthMap.label : "No DepthMap Node Selected") + ")"
|
||||
text: MaterialIcons.input
|
||||
|
||||
onClicked: {
|
||||
root.viewIn3D(root.getImageFile("depth"))
|
||||
}
|
||||
}
|
||||
|
||||
ToolButton {
|
||||
id: metadataCB
|
||||
padding: 3
|
||||
|
||||
font.family: MaterialIcons.fontFamily
|
||||
text: MaterialIcons.info_outline
|
||||
|
||||
ToolTip.text: "Image Metadata"
|
||||
ToolTip.visible: hovered
|
||||
|
||||
font.pointSize: 12
|
||||
smooth: false
|
||||
flat: true
|
||||
checkable: enabled
|
||||
enabled: _reconstruction.selectedViewId >= 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Busy indicator
|
||||
BusyIndicator {
|
||||
anchors.centerIn: parent
|
||||
// running property binding seems broken, only dynamic binding assignment works
|
||||
Component.onCompleted: {
|
||||
running = Qt.binding(function() { return imgContainer.image && imgContainer.image.status === Image.Loading })
|
||||
}
|
||||
// disable the visibility when unused to avoid stealing the mouseEvent to the image color picker
|
||||
visible: running
|
||||
}
|
||||
}
|
||||
|
|
|
@ -95,21 +95,12 @@ Item {
|
|||
id: imageViewerMenu
|
||||
y: parent.height
|
||||
x: -width + parent.width
|
||||
Action {
|
||||
id: useFloatImageViewerAction
|
||||
text: "Use HDR Image Viewer"
|
||||
checkable: true
|
||||
checked: false
|
||||
enabled: viewer2D.floatViewerAvailable
|
||||
|
||||
// tooltip: "Floating Point Image Viewer allows to visualize image with the full color dynamic. It is useful for HDR or RAW visualization. (Requires a plugin)"
|
||||
}
|
||||
Action {
|
||||
id: displayImageToolBarAction
|
||||
text: "Display HDR Toolbar"
|
||||
checkable: true
|
||||
checked: true
|
||||
enabled: useFloatImageViewerAction.checked
|
||||
enabled: viewer2D.useFloatImageViewer
|
||||
}
|
||||
Action {
|
||||
id: displayImagePathAction
|
||||
|
@ -124,7 +115,6 @@ Item {
|
|||
Viewer2D {
|
||||
id: viewer2D
|
||||
anchors.fill: parent
|
||||
useFloatImageViewer: useFloatImageViewerAction.checked
|
||||
|
||||
viewIn3D: root.load3DMedia
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue