mirror of
https://github.com/alicevision/Meshroom.git
synced 2025-08-03 00:38:41 +02:00
Remove the files used when the display was made by a list view based on the attribute editor.
935 lines
34 KiB
QML
935 lines
34 KiB
QML
import QtQuick 2.14
|
|
import QtQuick.Controls 2.3
|
|
import QtQuick.Layouts 1.3
|
|
import MaterialIcons 2.2
|
|
import QtQml.Models 2.2
|
|
import Qt.labs.qmlmodels 1.0
|
|
|
|
import Controls 1.0
|
|
import Utils 1.0
|
|
|
|
/**
|
|
* ImageGallery displays as a grid of Images a model containing Viewpoints objects.
|
|
* It manages a model of multiple CameraInit nodes as individual groups.
|
|
*/
|
|
Panel {
|
|
id: root
|
|
|
|
property variant cameraInits
|
|
property variant cameraInit
|
|
property variant tempCameraInit
|
|
readonly property alias currentItem: grid.currentItem
|
|
readonly property string currentItemSource: grid.currentItem ? grid.currentItem.source : ""
|
|
readonly property var currentItemMetadata: grid.currentItem ? grid.currentItem.metadata : undefined
|
|
readonly property int centerViewId: (_reconstruction && _reconstruction.sfmTransform) ? parseInt(_reconstruction.sfmTransform.attribute("transformation").value) : 0
|
|
|
|
property int defaultCellSize: 160
|
|
property int currentIndex: 0
|
|
property bool readOnly: false
|
|
|
|
property string filter: ""
|
|
property bool filterValue: true
|
|
|
|
signal removeImageRequest(var attribute)
|
|
signal filesDropped(var drop, var augmentSfm)
|
|
|
|
title: "Images"
|
|
implicitWidth: (root.defaultCellSize + 2) * 2
|
|
|
|
function changeCurrentIndex(newIndex) {
|
|
_reconstruction.cameraInitIndex = newIndex
|
|
}
|
|
|
|
QtObject {
|
|
id: m
|
|
property variant currentCameraInit: _reconstruction.tempCameraInit ? _reconstruction.tempCameraInit : root.cameraInit
|
|
property variant viewpoints: currentCameraInit ? currentCameraInit.attribute('viewpoints').value : undefined
|
|
property variant intrinsics: currentCameraInit ? currentCameraInit.attribute('intrinsics').value : undefined
|
|
property bool readOnly: root.readOnly || displayHDR.checked
|
|
}
|
|
|
|
property variant parsedIntrinsic
|
|
|
|
|
|
// function populate_model()
|
|
// {
|
|
// for (var property in parsedIntrinsic) {
|
|
// console.warn(property + ': ' + parsedIntrinsic[property]+'; ')
|
|
// intrinsicModel.append({'name' : property, 'value' : parsedIntrinsic[property]})
|
|
// }
|
|
// }
|
|
|
|
// function populate_model()
|
|
// {
|
|
// intrinsicModel.clear()
|
|
// for (var intr in parsedIntrinsic) {
|
|
// intrinsicModel.append(parsedIntrinsic[intr])
|
|
// }
|
|
// }
|
|
|
|
function populate_model()
|
|
{
|
|
intrinsicModel.clear()
|
|
for (var intr in parsedIntrinsic) {
|
|
intrinsicModel.appendRow(parsedIntrinsic[intr])
|
|
}
|
|
//console.warn(intrinsicModel.rowCount)
|
|
}
|
|
|
|
// function populate_model()
|
|
// {
|
|
// intrinsicModel.clear()
|
|
// let CurrentIntrinsic = {}
|
|
// console.warn("Populate Model")
|
|
// for (var intr in parsedIntrinsic) {
|
|
// for (var property in parsedIntrinsic[intr]) {
|
|
// if(property.localeCompare("Locked") === 0){
|
|
// CurrentIntrinsic[property] = {'label' : property, 'value' : parsedIntrinsic[intr][property]}
|
|
// intrinsicModel.append(CurrentIntrinsic)
|
|
// console.warn("Append to Model")
|
|
// for (var prop in CurrentIntrinsic) {
|
|
// delete CurrentIntrinsic[prop];
|
|
// }
|
|
// }else{
|
|
// CurrentIntrinsic[property] = {'label' : property, 'value' : parsedIntrinsic[intr][property]}
|
|
// }
|
|
// }
|
|
// }
|
|
// console.warn(intrinsicModel.count)
|
|
// }
|
|
|
|
//Parse
|
|
// Id : value
|
|
// function parseIntr(){
|
|
// parsedIntrinsic = {}
|
|
|
|
// for(var i = 0; i < m.intrinsics.count; i++){
|
|
// parsedIntrinsic[i] = {}
|
|
// for(var j=0; j < m.intrinsics.at(i).value.count; j++){
|
|
// var currentAttribute = m.intrinsics.at(i).value.at(j)
|
|
// if(currentAttribute.type === "GroupAttribute" || currentAttribute.type === "ListAttribute"){
|
|
// parsedIntrinsic[i][currentAttribute.label] = {}
|
|
// for(var k=0; k < currentAttribute.value.count; k++){
|
|
// parsedIntrinsic[i][currentAttribute.label][currentAttribute.value.at(k).label] = currentAttribute.value.at(k).value
|
|
|
|
// }
|
|
// }
|
|
// else{
|
|
// parsedIntrinsic[i][currentAttribute.label] = currentAttribute.value
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
// for (var intr in parsedIntrinsic) {
|
|
// for (var property in parsedIntrinsic[intr]) {
|
|
// console.warn(property + ': ' + parsedIntrinsic[intr][property] +'; ')
|
|
// }
|
|
// }
|
|
|
|
// populate_model()
|
|
// //console.warn(parsedIntrinsic.count)
|
|
// }
|
|
|
|
function parseIntr(){
|
|
parsedIntrinsic = {}
|
|
|
|
var currentCameraInitIntrinsics = m.intrinsics
|
|
|
|
//Loop through all intrinsics
|
|
for(var i = 0; i < currentCameraInitIntrinsics.count; i++){
|
|
parsedIntrinsic[i] = {}
|
|
|
|
//Loop through all attributes
|
|
for(var j=0; j < currentCameraInitIntrinsics.at(i).value.count; j++){
|
|
var currentAttribute = currentCameraInitIntrinsics.at(i).value.at(j)
|
|
//parsedIntrinsic[i][currentAttribute.label] = {}
|
|
if(currentAttribute.type === "GroupAttribute"){
|
|
//parsedIntrinsic[i][currentAttribute.label] = currentAttribute
|
|
for(var k=0; k < currentAttribute.value.count; k++){
|
|
parsedIntrinsic[i][currentAttribute.label + " " + currentAttribute.value.at(k).label] = currentAttribute.value.at(k)
|
|
//console.warn(currentAttribute.label + " " + currentAttribute.value.at(k).label)
|
|
}
|
|
}
|
|
else if(currentAttribute.type === "ListAttribute"){
|
|
|
|
}
|
|
else{
|
|
parsedIntrinsic[i][currentAttribute.label] = currentAttribute
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// for (var intr in parsedIntrinsic) {
|
|
// for (var property in parsedIntrinsic[intr]) {
|
|
// console.warn(property + ': ' + parsedIntrinsic[intr][property].type +'; ')
|
|
// }
|
|
// }
|
|
|
|
populate_model()
|
|
//console.warn(parsedIntrinsic.count)
|
|
}
|
|
|
|
|
|
|
|
headerBar: RowLayout {
|
|
MaterialToolButton {
|
|
text: MaterialIcons.more_vert
|
|
font.pointSize: 11
|
|
padding: 2
|
|
checkable: true
|
|
checked: galleryMenu.visible
|
|
onClicked: galleryMenu.open()
|
|
Menu {
|
|
id: galleryMenu
|
|
y: parent.height
|
|
x: -width + parent.width
|
|
MenuItem {
|
|
text: "Edit Sensor Database..."
|
|
onTriggered: {
|
|
sensorDBDialog.open()
|
|
}
|
|
}
|
|
|
|
Menu {
|
|
title: "Advanced"
|
|
Action {
|
|
id: displayViewIdsAction
|
|
text: "Display View IDs"
|
|
checkable: true
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
SensorDBDialog {
|
|
id: sensorDBDialog
|
|
sensorDatabase: cameraInit ? Filepath.stringToUrl(cameraInit.attribute("sensorDatabase").value) : ""
|
|
readOnly: _reconstruction.computing
|
|
onUpdateIntrinsicsRequest: _reconstruction.rebuildIntrinsics(cameraInit)
|
|
}
|
|
|
|
ColumnLayout {
|
|
anchors.fill: parent
|
|
spacing: 4
|
|
|
|
//Resize table view on width changed
|
|
onWidthChanged: {
|
|
//tableView.forceLayout()
|
|
|
|
//console.warn()
|
|
}
|
|
|
|
GridView {
|
|
id: grid
|
|
|
|
Layout.fillWidth: true
|
|
Layout.fillHeight: true
|
|
|
|
interactive: !intrinsicsFilterButton.checked
|
|
|
|
ScrollBar.vertical: ScrollBar {
|
|
minimumSize: 0.05
|
|
active : !intrinsicsFilterButton.checked
|
|
visible: !intrinsicsFilterButton.checked
|
|
|
|
}
|
|
|
|
focus: true
|
|
clip: true
|
|
cellWidth: thumbnailSizeSlider.value
|
|
cellHeight: cellWidth
|
|
highlightFollowsCurrentItem: true
|
|
keyNavigationEnabled: true
|
|
|
|
// Update grid current item when selected view changes
|
|
Connections {
|
|
target: _reconstruction
|
|
onSelectedViewIdChanged: {
|
|
var idx = grid.model.find(_reconstruction.selectedViewId, "viewId")
|
|
if(idx >= 0)
|
|
grid.currentIndex = idx
|
|
}
|
|
|
|
}
|
|
|
|
|
|
model: SortFilterDelegateModel {
|
|
id: sortedModel
|
|
model: m.viewpoints
|
|
sortRole: "path"
|
|
// TODO: provide filtering on reconstruction status
|
|
filterRole: _reconstruction.sfmReport ? root.filter : ""
|
|
filterValue: root.filterValue
|
|
// in modelData:
|
|
// if(filterRole == roleName)
|
|
// return _reconstruction.isReconstructed(item.model.object)
|
|
|
|
// override modelData to return basename of viewpoint's path for sorting
|
|
function modelData(item, roleName) {
|
|
if(filterRole == roleName)
|
|
return _reconstruction.isReconstructed(item.model.object)
|
|
var value = item.model.object.childAttribute(roleName).value
|
|
if(roleName == sortRole)
|
|
return Filepath.basename(value)
|
|
else
|
|
return value
|
|
}
|
|
|
|
delegate: ImageDelegate {
|
|
id: imageDelegate
|
|
|
|
viewpoint: object.value
|
|
width: grid.cellWidth
|
|
height: grid.cellHeight
|
|
readOnly: m.readOnly
|
|
displayViewId: displayViewIdsAction.checked
|
|
visible: !intrinsicsFilterButton.checked
|
|
|
|
isCurrentItem: GridView.isCurrentItem
|
|
|
|
onWidthChanged: {
|
|
//console.warn("viewpoint " + object.value.get("intrinsicId").value)
|
|
//console.warn("viewpoint " + m.intrinsics.at(1).childAttribute("intrinsicId"))
|
|
//console.warn("viewpoint " + m.intrinsics.at(0).value.at(9).name)
|
|
|
|
//console.warn("viewpoint " + m.intrinsics.at(0))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// console.warn("viewpoint2 " + (m.viewpoints?m.viewpoints.value:"pute"))
|
|
// console.warn("intrin " + m.currentCameraInit.attribute('intrinsics').value.count)
|
|
// //console.warn(viewpoint.get("poseId").value)
|
|
//console.warn(_reconstruction.isReconstructed(object))
|
|
|
|
}
|
|
|
|
onIsCurrentItemChanged: {
|
|
if(isCurrentItem)
|
|
_reconstruction.selectedViewId = viewpoint.get("viewId").value
|
|
}
|
|
|
|
onPressed: {
|
|
grid.currentIndex = DelegateModel.filteredIndex
|
|
if(mouse.button == Qt.LeftButton)
|
|
grid.forceActiveFocus()
|
|
}
|
|
|
|
function sendRemoveRequest()
|
|
{
|
|
if(!readOnly)
|
|
removeImageRequest(object)
|
|
}
|
|
|
|
onRemoveRequest: sendRemoveRequest()
|
|
Keys.onDeletePressed: sendRemoveRequest()
|
|
|
|
RowLayout {
|
|
anchors.top: parent.top
|
|
anchors.left: parent.left
|
|
anchors.right: parent.right
|
|
anchors.margins: 2
|
|
spacing: 2
|
|
|
|
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)
|
|
|
|
// Camera Initialization indicator
|
|
IntrinsicsIndicator {
|
|
intrinsic: parent.valid ? _reconstruction.getIntrinsic(object) : null
|
|
metadata: imageDelegate.metadata
|
|
}
|
|
|
|
// Rig indicator
|
|
Loader {
|
|
id: rigIndicator
|
|
property int rigId: parent.valid ? object.childAttribute("rigId").value : -1
|
|
active: rigId >= 0
|
|
sourceComponent: ImageBadge {
|
|
property int rigSubPoseId: model.object.childAttribute("subPoseId").value
|
|
text: MaterialIcons.link
|
|
ToolTip.text: "<b>Rig: Initialized</b><br>" +
|
|
"Rig ID: " + rigIndicator.rigId + " <br>" +
|
|
"SubPose: " + rigSubPoseId
|
|
}
|
|
}
|
|
|
|
// Center of SfMTransform
|
|
Loader {
|
|
id: sfmTransformIndicator
|
|
active: viewpoint && (viewpoint.get("viewId").value == centerViewId)
|
|
sourceComponent: ImageBadge {
|
|
text: MaterialIcons.gamepad
|
|
ToolTip.text: "Camera used to define the center of the scene."
|
|
}
|
|
}
|
|
|
|
Item { Layout.fillWidth: true }
|
|
|
|
// Reconstruction status indicator
|
|
Loader {
|
|
active: parent.inViews
|
|
visible: active
|
|
sourceComponent: ImageBadge {
|
|
property bool reconstructed: _reconstruction.sfmReport && _reconstruction.isReconstructed(model.object)
|
|
text: reconstructed ? MaterialIcons.videocam : MaterialIcons.videocam_off
|
|
color: reconstructed ? Colors.green : Colors.red
|
|
ToolTip.text: "<b>Camera: " + (reconstructed ? "" : "Not ") + "Reconstructed</b>"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Keyboard shortcut to change current image group
|
|
Keys.priority: Keys.BeforeItem
|
|
Keys.onPressed: {
|
|
if(event.modifiers & Qt.AltModifier)
|
|
{
|
|
event.accepted = true
|
|
if(event.key == Qt.Key_Right)
|
|
root.changeCurrentIndex(Math.min(root.cameraInits.count - 1, root.currentIndex + 1))
|
|
else if(event.key == Qt.Key_Left)
|
|
root.changeCurrentIndex(Math.max(0, root.currentIndex - 1))
|
|
}
|
|
}
|
|
|
|
// Explanatory placeholder when no image has been added yet
|
|
Column {
|
|
id: dropImagePlaceholder
|
|
anchors.centerIn: parent
|
|
visible: (m.viewpoints ? m.viewpoints.count == 0 : true)
|
|
spacing: 4
|
|
Label {
|
|
anchors.horizontalCenter: parent.horizontalCenter
|
|
text: MaterialIcons.photo_library
|
|
font.pointSize: 24
|
|
font.family: MaterialIcons.fontFamily
|
|
}
|
|
Label {
|
|
text: "Drop Image Files / Folders"
|
|
}
|
|
}
|
|
// Placeholder when the filtered images list is empty
|
|
Column {
|
|
id: noImageImagePlaceholder
|
|
anchors.centerIn: parent
|
|
visible: (m.viewpoints ? m.viewpoints.count != 0 : false) && !dropImagePlaceholder.visible && grid.model.count == 0 && !intrinsicsFilterButton.checked
|
|
spacing: 4
|
|
Label {
|
|
anchors.horizontalCenter: parent.horizontalCenter
|
|
text: MaterialIcons.filter_none
|
|
font.pointSize: 24
|
|
font.family: MaterialIcons.fontFamily
|
|
}
|
|
Label {
|
|
text: "No images in this filtered view"
|
|
}
|
|
}
|
|
|
|
|
|
// TableView {
|
|
// id: tableView
|
|
// anchors.fill: parent
|
|
// Layout.fillWidth: true
|
|
// columnSpacing: 1
|
|
// rowSpacing: 1
|
|
|
|
// // Create a kind of responsive width base on the grid width
|
|
// // Require a forceLayout() call to be updated
|
|
// columnWidthProvider: function (column) {
|
|
// return grid.width;
|
|
// }
|
|
|
|
// boundsBehavior: Flickable.StopAtBounds
|
|
// visible: (m.viewpoints ? m.viewpoints.count != 0 : false) && intrinsicsFilterButton.checked
|
|
// onVisibleChanged:{
|
|
// tableView.forceLayout();
|
|
// }
|
|
|
|
// model: TableModel {
|
|
|
|
// TableModelColumn { display: "checked" }
|
|
// TableModelColumn { display: "fruitName" }
|
|
|
|
// }
|
|
|
|
|
|
// delegate: TextInput {
|
|
// text: model.display
|
|
// padding: 12
|
|
// selectByMouse: true
|
|
|
|
// onAccepted: model.display = text
|
|
|
|
// Rectangle {
|
|
// anchors.fill: parent
|
|
// color: "#efefef"
|
|
// z: -1
|
|
// }
|
|
// }
|
|
|
|
// Component.onCompleted: {
|
|
// model.appendRow(m.intrinsics.at(0).value)
|
|
//// console.log(model.getRow(0).display);
|
|
//// console.log(model.rows[0].fruitName);
|
|
// }
|
|
// }
|
|
|
|
|
|
// ImageIntrinsicViewer {
|
|
// id: nodeEditor
|
|
// width: Math.round(parent.width)
|
|
// intrinsics: m.intrinsics
|
|
// }
|
|
|
|
RowLayout{
|
|
anchors.fill: parent
|
|
Layout.fillWidth: true
|
|
Layout.fillHeight: true
|
|
// ListView{
|
|
// Layout.fillHeight: true
|
|
// Layout.fillWidth: true
|
|
// orientation: ListView.Vertical
|
|
|
|
|
|
// model: intrinsicModel
|
|
|
|
// delegate: IntrinsicDisplayDelegate{
|
|
|
|
// }
|
|
// }
|
|
|
|
// ListModel{
|
|
// id : intrinsicModel
|
|
// dynamicRoles:true
|
|
|
|
// }
|
|
|
|
TableView{
|
|
id : intrinsicTable
|
|
Layout.fillHeight: true
|
|
Layout.fillWidth: true
|
|
|
|
model: intrinsicModel
|
|
|
|
delegate: IntrinsicDisplayDelegate{}
|
|
}
|
|
|
|
TableModel{
|
|
id : intrinsicModel
|
|
|
|
TableModelColumn { display: "Id" }
|
|
TableModelColumn { display: "Initial Focal Length" }
|
|
TableModelColumn { display: "Focal Length x" }
|
|
TableModelColumn { display: "Focal Length y" }
|
|
TableModelColumn { display: "Camera Type" }
|
|
TableModelColumn { display: "Width" }
|
|
TableModelColumn { display: "Height" }
|
|
TableModelColumn { display: "Sensor Width" }
|
|
TableModelColumn { display: "Sensor Height" }
|
|
TableModelColumn { display: "Serial Number" }
|
|
TableModelColumn { display: "Principal Point x" }
|
|
TableModelColumn { display: "Principal Point y" }
|
|
TableModelColumn { display: "Locked" }
|
|
|
|
}
|
|
|
|
// HorizontalHeaderView {
|
|
// id: horizontalHeader
|
|
// syncView: tableView
|
|
// anchors.left: tableView.left
|
|
// }
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// ListView {
|
|
// id: listView
|
|
// anchors.fill: parent
|
|
// Layout.fillWidth: true
|
|
// property bool readOnly: false
|
|
// property int labelWidth: 180
|
|
|
|
// signal upgradeRequest()
|
|
// signal attributeDoubleClicked(var mouse, var attribute)
|
|
|
|
// model : m.intrinsics
|
|
|
|
// spacing: 2
|
|
// clip: true
|
|
// ScrollBar.vertical: ScrollBar { id: scrollBar }
|
|
// visible: intrinsicsFilterButton.checked
|
|
|
|
// delegate: Loader {
|
|
// active: object.enabled && (!object.desc.advanced)
|
|
// visible: active
|
|
// sourceComponent: ImageIntrinsicDelegate {
|
|
// width: listView.width
|
|
// readOnly: listView.readOnly
|
|
// attribute: model.object
|
|
// onDoubleClicked: listView.attributeDoubleClicked(mouse, attr)
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
|
|
|
|
// Pane {
|
|
// background: Rectangle { color: 'red' }
|
|
// width : 150
|
|
// height : 200
|
|
// Component{
|
|
// id : block
|
|
// Rectangle {
|
|
// color: 'green'
|
|
// width : 15
|
|
// height : 20
|
|
|
|
// Text{
|
|
// text: "Hello World!"
|
|
// font.family: "Helvetica"
|
|
// font.pointSize: 24
|
|
// color: "blue"
|
|
// }
|
|
// }
|
|
// }
|
|
// Loader{sourceComponent: block }
|
|
// }
|
|
|
|
|
|
|
|
DropArea {
|
|
id: dropArea
|
|
anchors.fill: parent
|
|
enabled: !m.readOnly && !intrinsicsFilterButton.checked
|
|
keys: ["text/uri-list"]
|
|
// TODO: onEntered: call specific method to filter files based on extension
|
|
onDropped: {
|
|
var augmentSfm = augmentArea.hovered
|
|
root.filesDropped(drop, augmentSfm)
|
|
}
|
|
|
|
// Background opacifier
|
|
Rectangle {
|
|
visible: dropArea.containsDrag
|
|
anchors.fill: parent
|
|
color: root.palette.window
|
|
opacity: 0.8
|
|
}
|
|
|
|
ColumnLayout {
|
|
anchors.fill: parent
|
|
visible: dropArea.containsDrag
|
|
spacing: 1
|
|
Label {
|
|
id: addArea
|
|
property bool hovered: dropArea.drag.y < height
|
|
Layout.fillWidth: true
|
|
Layout.fillHeight: true
|
|
horizontalAlignment: Text.AlignHCenter
|
|
verticalAlignment: Text.AlignVCenter
|
|
text: "Add Images"
|
|
font.bold: true
|
|
background: Rectangle {
|
|
color: parent.hovered ? parent.palette.highlight : parent.palette.window
|
|
opacity: 0.8
|
|
border.color: parent.palette.highlight
|
|
}
|
|
}
|
|
|
|
// DropArea overlay
|
|
Label {
|
|
id: augmentArea
|
|
property bool hovered: visible && dropArea.drag.y >= y
|
|
Layout.fillWidth: true
|
|
Layout.preferredHeight: parent.height * 0.3
|
|
horizontalAlignment: Text.AlignHCenter
|
|
verticalAlignment: Text.AlignVCenter
|
|
text: "Augment Reconstruction"
|
|
font.bold: true
|
|
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
|
|
visible: m.viewpoints ? m.viewpoints.count > 0 : false
|
|
background: Rectangle {
|
|
color: parent.hovered ? palette.highlight : palette.window
|
|
opacity: 0.8
|
|
border.color: parent.palette.highlight
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
RowLayout {
|
|
Layout.fillHeight: false
|
|
visible: root.cameraInits.count > 1
|
|
Layout.alignment: Qt.AlignHCenter
|
|
spacing: 2
|
|
|
|
ToolButton {
|
|
text: MaterialIcons.navigate_before
|
|
font.family: MaterialIcons.fontFamily
|
|
ToolTip.text: "Previous Group (Alt+Left)"
|
|
ToolTip.visible: hovered
|
|
enabled: nodesCB.currentIndex > 0
|
|
onClicked: nodesCB.decrementCurrentIndex()
|
|
}
|
|
Label { id: groupLabel; text: "Group " }
|
|
ComboBox {
|
|
id: nodesCB
|
|
model: root.cameraInits.count
|
|
implicitWidth: 40
|
|
currentIndex: root.currentIndex
|
|
onActivated: root.changeCurrentIndex(currentIndex)
|
|
}
|
|
Label { text: "/ " + (root.cameraInits.count - 1) }
|
|
ToolButton {
|
|
text: MaterialIcons.navigate_next
|
|
font.family: MaterialIcons.fontFamily
|
|
ToolTip.text: "Next Group (Alt+Right)"
|
|
ToolTip.visible: hovered
|
|
enabled: root.currentIndex < root.cameraInits.count - 1
|
|
onClicked: nodesCB.incrementCurrentIndex()
|
|
}
|
|
}
|
|
}
|
|
|
|
footerContent: RowLayout {
|
|
// Images count
|
|
id: footer
|
|
|
|
function resetButtons(){
|
|
inputImagesFilterButton.checked = false
|
|
estimatedCamerasFilterButton.checked = false
|
|
nonEstimatedCamerasFilterButton.checked = false
|
|
}
|
|
|
|
MaterialToolLabelButton {
|
|
id : inputImagesFilterButton
|
|
Layout.minimumWidth: childrenRect.width
|
|
ToolTip.text: grid.model.count + " Input Images"
|
|
iconText: MaterialIcons.image
|
|
label: (m.viewpoints ? m.viewpoints.count : 0)
|
|
padding: 3
|
|
|
|
checkable: true
|
|
checked: true
|
|
|
|
onCheckedChanged:{
|
|
if(checked) {
|
|
root.filter = ""
|
|
root.filterValue = true
|
|
estimatedCamerasFilterButton.checked = false
|
|
nonEstimatedCamerasFilterButton.checked = false
|
|
intrinsicsFilterButton.checked = false;
|
|
}
|
|
}
|
|
}
|
|
// Estimated cameras count
|
|
MaterialToolLabelButton {
|
|
id : estimatedCamerasFilterButton
|
|
Layout.minimumWidth: childrenRect.width
|
|
ToolTip.text: label + " Estimated Cameras"
|
|
iconText: MaterialIcons.videocam
|
|
label: _reconstruction ? _reconstruction.nbCameras.toString() : "0"
|
|
padding: 3
|
|
|
|
enabled: _reconstruction.cameraInit && _reconstruction.nbCameras
|
|
checkable: true
|
|
checked: false
|
|
|
|
onCheckedChanged:{
|
|
if(checked) {
|
|
root.filter = "viewId"
|
|
root.filterValue = true
|
|
inputImagesFilterButton.checked = false
|
|
nonEstimatedCamerasFilterButton.checked = false
|
|
intrinsicsFilterButton.checked = false;
|
|
}
|
|
}
|
|
onEnabledChanged:{
|
|
if(!enabled) {
|
|
checked = false
|
|
inputImagesFilterButton.checked = true;
|
|
}
|
|
}
|
|
|
|
}
|
|
// Non estimated cameras count
|
|
MaterialToolLabelButton {
|
|
id : nonEstimatedCamerasFilterButton
|
|
Layout.minimumWidth: childrenRect.width
|
|
ToolTip.text: label + " Non Estimated Cameras"
|
|
iconText: MaterialIcons.videocam_off
|
|
label: _reconstruction ? ((m.viewpoints ? m.viewpoints.count : 0) - _reconstruction.nbCameras.toString()).toString() : "0"
|
|
padding: 3
|
|
|
|
enabled: _reconstruction.cameraInit && _reconstruction.nbCameras
|
|
checkable: true
|
|
checked: false
|
|
|
|
onCheckedChanged:{
|
|
if(checked) {
|
|
filter = "viewId"
|
|
root.filterValue = false
|
|
inputImagesFilterButton.checked = false
|
|
estimatedCamerasFilterButton.checked = false
|
|
intrinsicsFilterButton.checked = false;
|
|
}
|
|
}
|
|
onEnabledChanged:{
|
|
if(!enabled) {
|
|
checked = false
|
|
inputImagesFilterButton.checked = true;
|
|
}
|
|
}
|
|
|
|
}
|
|
MaterialToolLabelButton {
|
|
id : intrinsicsFilterButton
|
|
Layout.minimumWidth: childrenRect.width
|
|
ToolTip.text: label + " Number of intrinsics"
|
|
iconText: MaterialIcons.camera
|
|
label: _reconstruction ? (m.intrinsics ? m.intrinsics.count : 0) : "0"
|
|
padding: 3
|
|
|
|
|
|
enabled: m.intrinsics ? m.intrinsics.count > 0 : false
|
|
checkable: true
|
|
checked: false
|
|
|
|
onCheckedChanged:{
|
|
if(checked) {
|
|
inputImagesFilterButton.checked = false
|
|
estimatedCamerasFilterButton.checked = false
|
|
nonEstimatedCamerasFilterButton.checked = false
|
|
}
|
|
parseIntr()
|
|
}
|
|
onEnabledChanged:{
|
|
if(!enabled) {
|
|
checked = false
|
|
inputImagesFilterButton.checked = true;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
Item { Layout.fillHeight: true; Layout.fillWidth: true }
|
|
|
|
MaterialToolLabelButton {
|
|
id: displayHDR
|
|
Layout.minimumWidth: childrenRect.width
|
|
property var activeNode: _reconstruction.activeNodes.get("LdrToHdrMerge").node
|
|
ToolTip.text: "Visualize HDR images: " + (activeNode ? activeNode.label : "No Node")
|
|
iconText: MaterialIcons.filter
|
|
label: activeNode ? activeNode.attribute("nbBrackets").value : ""
|
|
visible: activeNode
|
|
enabled: activeNode && activeNode.isComputed
|
|
property string nodeID: activeNode ? (activeNode.label + activeNode.isComputed) : ""
|
|
onNodeIDChanged: {
|
|
if(checked) {
|
|
open();
|
|
}
|
|
}
|
|
onEnabledChanged: {
|
|
// Reset the toggle to avoid getting stuck
|
|
// with the HDR node checked but disabled.
|
|
if(checked) {
|
|
checked = false;
|
|
close();
|
|
}
|
|
}
|
|
checkable: true
|
|
checked: false
|
|
onClicked: {
|
|
if(checked) {
|
|
open();
|
|
} else {
|
|
close();
|
|
}
|
|
}
|
|
function open() {
|
|
if(imageProcessing.checked)
|
|
imageProcessing.checked = false;
|
|
_reconstruction.setupTempCameraInit(activeNode, "outSfMData");
|
|
}
|
|
function close() {
|
|
_reconstruction.clearTempCameraInit();
|
|
}
|
|
}
|
|
|
|
MaterialToolButton {
|
|
id: imageProcessing
|
|
Layout.minimumWidth: childrenRect.width
|
|
|
|
property var activeNode: _reconstruction.activeNodes.get("ImageProcessing").node
|
|
font.pointSize: 15
|
|
padding: 0
|
|
ToolTip.text: "Preprocessed Images: " + (activeNode ? activeNode.label : "No Node")
|
|
text: MaterialIcons.wallpaper
|
|
visible: activeNode && activeNode.attribute("outSfMData").value
|
|
enabled: activeNode && activeNode.isComputed
|
|
property string nodeID: activeNode ? (activeNode.label + activeNode.isComputed) : ""
|
|
onNodeIDChanged: {
|
|
if(checked) {
|
|
open();
|
|
}
|
|
}
|
|
onEnabledChanged: {
|
|
// Reset the toggle to avoid getting stuck
|
|
// with the HDR node checked but disabled.
|
|
if(checked) {
|
|
checked = false;
|
|
close();
|
|
}
|
|
}
|
|
checkable: true
|
|
checked: false
|
|
onClicked: {
|
|
if(checked) {
|
|
open();
|
|
} else {
|
|
close();
|
|
}
|
|
}
|
|
function open() {
|
|
if(displayHDR.checked)
|
|
displayHDR.checked = false;
|
|
_reconstruction.setupTempCameraInit(activeNode, "outSfMData");
|
|
}
|
|
function close() {
|
|
_reconstruction.clearTempCameraInit();
|
|
}
|
|
}
|
|
|
|
Item { Layout.fillHeight: true; width: 1 }
|
|
|
|
// Thumbnail size icon and slider
|
|
MaterialToolButton {
|
|
Layout.minimumWidth: childrenRect.width
|
|
|
|
text: MaterialIcons.photo_size_select_large
|
|
ToolTip.text: "Thumbnails Scale"
|
|
padding: 0
|
|
anchors.margins: 0
|
|
font.pointSize: 11
|
|
onClicked: { thumbnailSizeSlider.value = defaultCellSize; }
|
|
}
|
|
Slider {
|
|
id: thumbnailSizeSlider
|
|
from: 70
|
|
value: defaultCellSize
|
|
to: 250
|
|
implicitWidth: 70
|
|
}
|
|
}
|
|
}
|