mirror of
https://github.com/alicevision/Meshroom.git
synced 2025-08-06 10:18:42 +02:00
[wip] Add intrinsic display inside image gallery
This commit is contained in:
parent
53b371dff9
commit
83c9600005
5 changed files with 595 additions and 80 deletions
|
@ -160,7 +160,7 @@ Panel {
|
||||||
onWidthChanged: {
|
onWidthChanged: {
|
||||||
//console.warn("viewpoint " + object.value.get("intrinsicId").value)
|
//console.warn("viewpoint " + object.value.get("intrinsicId").value)
|
||||||
//console.warn("viewpoint " + m.intrinsics.at(1).childAttribute("intrinsicId"))
|
//console.warn("viewpoint " + m.intrinsics.at(1).childAttribute("intrinsicId"))
|
||||||
console.warn("viewpoint " + m.intrinsics.at(0).value)
|
console.warn("viewpoint " + m.intrinsics.at(0).value.at(9).name)
|
||||||
|
|
||||||
//console.warn("viewpoint " + m.intrinsics.at(0))
|
//console.warn("viewpoint " + m.intrinsics.at(0))
|
||||||
|
|
||||||
|
@ -300,73 +300,6 @@ Panel {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ListView {
|
|
||||||
anchors.fill: parent
|
|
||||||
model: m.intrinsics
|
|
||||||
delegate: fruitDelegate
|
|
||||||
|
|
||||||
header: headerComponent
|
|
||||||
|
|
||||||
focus: true
|
|
||||||
|
|
||||||
highlight: Rectangle {
|
|
||||||
color: "lightblue"
|
|
||||||
width: parent.width
|
|
||||||
}
|
|
||||||
section {
|
|
||||||
property: value
|
|
||||||
criteria: ViewSection.FullString
|
|
||||||
delegate: Rectangle {
|
|
||||||
color: "#b0dfb0"
|
|
||||||
width: parent.width
|
|
||||||
height: childrenRect.height + 4
|
|
||||||
Text {
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
font.pixelSize: 16
|
|
||||||
font.bold: true
|
|
||||||
text: section
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Component { //instantiated when header is processed
|
|
||||||
id: headerComponent
|
|
||||||
Rectangle {
|
|
||||||
id: banner
|
|
||||||
width: parent.width; height: 50
|
|
||||||
gradient: clubcolors
|
|
||||||
border {color: "#9EDDF2"; width: 2}
|
|
||||||
Text {
|
|
||||||
anchors.centerIn: parent
|
|
||||||
text: "Club Members"
|
|
||||||
font.pixelSize: 32
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Gradient {
|
|
||||||
id: clubcolors
|
|
||||||
GradientStop { position: 0.0; color: "#8EE2FE"}
|
|
||||||
GradientStop { position: 0.66; color: "#7ED2EE"}
|
|
||||||
}
|
|
||||||
|
|
||||||
Component {
|
|
||||||
|
|
||||||
id: fruitDelegate
|
|
||||||
|
|
||||||
Row {
|
|
||||||
spacing: 10
|
|
||||||
Text {
|
|
||||||
text: object.value.get("width").value
|
|
||||||
color: "#efefef"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// TableView {
|
// TableView {
|
||||||
// id: tableView
|
// id: tableView
|
||||||
// anchors.fill: parent
|
// anchors.fill: parent
|
||||||
|
@ -386,24 +319,18 @@ Panel {
|
||||||
// tableView.forceLayout();
|
// tableView.forceLayout();
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// model: m.intrinsics
|
// model: TableModel {
|
||||||
|
|
||||||
//// model: TableModel {
|
// TableModelColumn { display: "checked" }
|
||||||
|
// TableModelColumn { display: "fruitName" }
|
||||||
|
|
||||||
//// TableModelColumn { display: "checked" }
|
// }
|
||||||
//// TableModelColumn { display: "fruitName" }
|
|
||||||
|
|
||||||
|
|
||||||
//// Component.onCompleted: {
|
|
||||||
//// console.warn(data(index(2,1), "display"))
|
|
||||||
//// }
|
|
||||||
//// }
|
|
||||||
|
|
||||||
|
|
||||||
// delegate: TextInput {
|
// delegate: TextInput {
|
||||||
// text: object.value.get("pxFocalLength").value.get("x").value
|
// text: model.display
|
||||||
// padding: 12
|
// padding: 12
|
||||||
// selectByMouse: false
|
// selectByMouse: true
|
||||||
|
|
||||||
// onAccepted: model.display = text
|
// onAccepted: model.display = text
|
||||||
|
|
||||||
|
@ -413,8 +340,77 @@ Panel {
|
||||||
// z: -1
|
// 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
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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: true
|
||||||
|
|
||||||
|
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 {
|
DropArea {
|
||||||
id: dropArea
|
id: dropArea
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
|
404
meshroom/ui/qml/ImageGallery/ImageIntrinsicDelegate.qml
Normal file
404
meshroom/ui/qml/ImageGallery/ImageIntrinsicDelegate.qml
Normal file
|
@ -0,0 +1,404 @@
|
||||||
|
import QtQuick 2.9
|
||||||
|
import QtQuick.Layouts 1.3
|
||||||
|
import QtQuick.Controls 2.2
|
||||||
|
import MaterialIcons 2.2
|
||||||
|
import Utils 1.0
|
||||||
|
|
||||||
|
/**
|
||||||
|
Instantiate a control to visualize and edit an Attribute based on its type.
|
||||||
|
*/
|
||||||
|
RowLayout {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
property variant attribute: null
|
||||||
|
property bool readOnly: false // whether the attribute's value can be modified
|
||||||
|
|
||||||
|
signal doubleClicked(var mouse, var attr)
|
||||||
|
|
||||||
|
spacing: 2
|
||||||
|
|
||||||
|
Pane {
|
||||||
|
background: Rectangle { color: Qt.darker(parent.palette.window, 1.1) }
|
||||||
|
padding: 0
|
||||||
|
Layout.preferredWidth: implicitWidth
|
||||||
|
Layout.fillHeight: true
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
spacing: 0
|
||||||
|
width: parent.width
|
||||||
|
height: parent.height
|
||||||
|
Label {
|
||||||
|
id: parameterLabel
|
||||||
|
|
||||||
|
Layout.fillHeight: true
|
||||||
|
Layout.fillWidth: true
|
||||||
|
horizontalAlignment: attribute.isOutput ? Qt.AlignRight : Qt.AlignLeft
|
||||||
|
elide: Label.ElideRight
|
||||||
|
padding: 5
|
||||||
|
wrapMode: Label.WrapAtWordBoundaryOrAnywhere
|
||||||
|
|
||||||
|
text: attribute.label
|
||||||
|
|
||||||
|
// Tooltip hint with attribute's description
|
||||||
|
ToolTip.text: "<b>" + object.desc.name + "</b><br>" + Format.plainToHtml(object.desc.description)
|
||||||
|
ToolTip.visible: parameterMA.containsMouse
|
||||||
|
ToolTip.delay: 800
|
||||||
|
|
||||||
|
// make label bold if attribute's value is not the default one
|
||||||
|
font.bold: !object.isOutput && !object.isDefault
|
||||||
|
|
||||||
|
// make label italic if attribute is a link
|
||||||
|
font.italic: object.isLink
|
||||||
|
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: parameterMA
|
||||||
|
anchors.fill: parent
|
||||||
|
hoverEnabled: true
|
||||||
|
acceptedButtons: Qt.AllButtons
|
||||||
|
onDoubleClicked: root.doubleClicked(mouse, root.attribute)
|
||||||
|
|
||||||
|
property Component menuComp: Menu {
|
||||||
|
id: paramMenu
|
||||||
|
|
||||||
|
property bool isFileAttribute: attribute.type == "File"
|
||||||
|
property bool isFilepath: isFileAttribute && Filepath.isFile(attribute.value)
|
||||||
|
|
||||||
|
MenuItem {
|
||||||
|
text: "Reset To Default Value"
|
||||||
|
enabled: root.editable && !attribute.isDefault
|
||||||
|
onTriggered: _reconstruction.resetAttribute(attribute)
|
||||||
|
}
|
||||||
|
|
||||||
|
MenuSeparator {
|
||||||
|
visible: paramMenu.isFileAttribute
|
||||||
|
height: visible ? implicitHeight : 0
|
||||||
|
}
|
||||||
|
|
||||||
|
MenuItem {
|
||||||
|
visible: paramMenu.isFileAttribute
|
||||||
|
height: visible ? implicitHeight : 0
|
||||||
|
text: paramMenu.isFilepath ? "Open Containing Folder" : "Open Folder"
|
||||||
|
onClicked: paramMenu.isFilepath ? Qt.openUrlExternally(Filepath.dirname(attribute.value)) :
|
||||||
|
Qt.openUrlExternally(Filepath.stringToUrl(attribute.value))
|
||||||
|
}
|
||||||
|
|
||||||
|
MenuItem {
|
||||||
|
visible: paramMenu.isFilepath
|
||||||
|
height: visible ? implicitHeight : 0
|
||||||
|
text: "Open File"
|
||||||
|
onClicked: Qt.openUrlExternally(Filepath.stringToUrl(attribute.value))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
forceActiveFocus()
|
||||||
|
if(mouse.button == Qt.RightButton)
|
||||||
|
{
|
||||||
|
var menu = menuComp.createObject(parameterLabel)
|
||||||
|
menu.parent = parameterLabel
|
||||||
|
menu.popup()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MaterialLabel {
|
||||||
|
visible: attribute.desc.advanced
|
||||||
|
text: MaterialIcons.build
|
||||||
|
color: palette.mid
|
||||||
|
font.pointSize: 8
|
||||||
|
padding: 4
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setTextFieldAttribute(value)
|
||||||
|
{
|
||||||
|
// editingFinished called even when TextField is readonly
|
||||||
|
if(!editable)
|
||||||
|
return
|
||||||
|
switch(attribute.type)
|
||||||
|
{
|
||||||
|
case "IntParam":
|
||||||
|
case "FloatParam":
|
||||||
|
_reconstruction.setAttribute(root.attribute, Number(value))
|
||||||
|
break;
|
||||||
|
case "File":
|
||||||
|
_reconstruction.setAttribute(root.attribute, value)
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
_reconstruction.setAttribute(root.attribute, value.trim())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pane {
|
||||||
|
// background: Rectangle { color: 'red' }
|
||||||
|
// Component{
|
||||||
|
// id : block
|
||||||
|
// Rectangle {
|
||||||
|
// color: 'green'
|
||||||
|
// width : 150
|
||||||
|
// height : 20
|
||||||
|
|
||||||
|
// Text{
|
||||||
|
// text: "Hello World!"
|
||||||
|
// font.family: "Helvetica"
|
||||||
|
// font.pointSize: 12
|
||||||
|
// color: "blue"
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// Component.onCompleted: {
|
||||||
|
// console.warn("Test " + attribute.type)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Loader{sourceComponent: block }
|
||||||
|
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
Loader {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
sourceComponent: {
|
||||||
|
switch(attribute.type)
|
||||||
|
{
|
||||||
|
//case "ChoiceParam": return attribute.desc.exclusive ? comboBox_component : multiChoice_component
|
||||||
|
case "IntParam": return slider_component
|
||||||
|
case "FloatParam": return slider_component
|
||||||
|
case "BoolParam": return checkbox_component
|
||||||
|
case "ListAttribute": return listAttribute_component
|
||||||
|
case "GroupAttribute": return groupAttribute_component
|
||||||
|
default: return textField_component
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: textField_component
|
||||||
|
TextField {
|
||||||
|
readOnly: !root.editable
|
||||||
|
text: attribute.value
|
||||||
|
selectByMouse: true
|
||||||
|
onEditingFinished: setTextFieldAttribute(text)
|
||||||
|
onAccepted: {
|
||||||
|
setTextFieldAttribute(text)
|
||||||
|
root.forceActiveFocus()
|
||||||
|
}
|
||||||
|
Component.onDestruction: {
|
||||||
|
if(activeFocus)
|
||||||
|
setTextFieldAttribute(text)
|
||||||
|
}
|
||||||
|
DropArea {
|
||||||
|
enabled: true
|
||||||
|
anchors.fill: parent
|
||||||
|
onDropped: {
|
||||||
|
if(drop.hasUrls)
|
||||||
|
setTextFieldAttribute(Filepath.urlToString(drop.urls[0]))
|
||||||
|
else if(drop.hasText && drop.text != '')
|
||||||
|
setTextFieldAttribute(drop.text)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: comboBox_component
|
||||||
|
ComboBox {
|
||||||
|
id: combo
|
||||||
|
enabled: root.editable
|
||||||
|
model: attribute.desc.values
|
||||||
|
Component.onCompleted: currentIndex = find(attribute.value)
|
||||||
|
onActivated: _reconstruction.setAttribute(attribute, currentText)
|
||||||
|
Connections {
|
||||||
|
target: attribute
|
||||||
|
onValueChanged: combo.currentIndex = combo.find(attribute.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: multiChoice_component
|
||||||
|
Flow {
|
||||||
|
Repeater {
|
||||||
|
id: checkbox_repeater
|
||||||
|
model: attribute.desc.values
|
||||||
|
delegate: CheckBox {
|
||||||
|
enabled: root.editable
|
||||||
|
text: modelData
|
||||||
|
checked: attribute.value.indexOf(modelData) >= 0
|
||||||
|
onToggled: {
|
||||||
|
var t = attribute.value
|
||||||
|
if(!checked) { t.splice(t.indexOf(modelData), 1) } // remove element
|
||||||
|
else { t.push(modelData) } // add element
|
||||||
|
_reconstruction.setAttribute(attribute, t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: slider_component
|
||||||
|
RowLayout {
|
||||||
|
TextField {
|
||||||
|
IntValidator {
|
||||||
|
id: intValidator
|
||||||
|
}
|
||||||
|
DoubleValidator {
|
||||||
|
id: doubleValidator
|
||||||
|
locale: 'C' // use '.' decimal separator disregarding the system locale
|
||||||
|
}
|
||||||
|
implicitWidth: 100
|
||||||
|
Layout.fillWidth: !slider.active
|
||||||
|
// cast value to string to avoid intrusive scientific notations on numbers
|
||||||
|
property string displayValue: String(slider.active && slider.item.pressed ? slider.item.formattedValue : attribute.value)
|
||||||
|
text: displayValue
|
||||||
|
selectByMouse: true
|
||||||
|
// Note: Use autoScroll as a workaround for alignment
|
||||||
|
// When the value change keep the text align to the left to be able to read the most important part
|
||||||
|
// of the number. When we are editing (item is in focus), the content should follow the editing.
|
||||||
|
autoScroll: activeFocus
|
||||||
|
validator: attribute.type == "FloatParam" ? doubleValidator : intValidator
|
||||||
|
onEditingFinished: setTextFieldAttribute(text)
|
||||||
|
onAccepted: {
|
||||||
|
setTextFieldAttribute(text)
|
||||||
|
// When the text is too long, display the left part
|
||||||
|
// (with the most important values and cut the floating point details)
|
||||||
|
ensureVisible(0)
|
||||||
|
}
|
||||||
|
Component.onDestruction: {
|
||||||
|
if(activeFocus)
|
||||||
|
setTextFieldAttribute(text)
|
||||||
|
}
|
||||||
|
Component.onCompleted: {
|
||||||
|
// When the text is too long, display the left part
|
||||||
|
// (with the most important values and cut the floating point details)
|
||||||
|
ensureVisible(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Loader {
|
||||||
|
id: slider
|
||||||
|
Layout.fillWidth: true
|
||||||
|
active: attribute.desc.range.length === 3
|
||||||
|
sourceComponent: Slider {
|
||||||
|
readonly property int stepDecimalCount: stepSize < 1 ? String(stepSize).split(".").pop().length : 0
|
||||||
|
readonly property real formattedValue: value.toFixed(stepDecimalCount)
|
||||||
|
enabled: true
|
||||||
|
value: attribute.value
|
||||||
|
from: attribute.desc.range[0]
|
||||||
|
to: attribute.desc.range[1]
|
||||||
|
stepSize: attribute.desc.range[2]
|
||||||
|
snapMode: Slider.SnapAlways
|
||||||
|
|
||||||
|
onPressedChanged: {
|
||||||
|
if(!pressed)
|
||||||
|
_reconstruction.setAttribute(attribute, formattedValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: checkbox_component
|
||||||
|
Row {
|
||||||
|
CheckBox {
|
||||||
|
enabled: true
|
||||||
|
checked: attribute.value
|
||||||
|
onToggled: _reconstruction.setAttribute(attribute, !attribute.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: listAttribute_component
|
||||||
|
ColumnLayout {
|
||||||
|
id: listAttribute_layout
|
||||||
|
width: parent.width
|
||||||
|
property bool expanded: false
|
||||||
|
RowLayout {
|
||||||
|
spacing: 4
|
||||||
|
ToolButton {
|
||||||
|
text: listAttribute_layout.expanded ? MaterialIcons.keyboard_arrow_down : MaterialIcons.keyboard_arrow_right
|
||||||
|
font.family: MaterialIcons.fontFamily
|
||||||
|
onClicked: listAttribute_layout.expanded = !listAttribute_layout.expanded
|
||||||
|
}
|
||||||
|
Label {
|
||||||
|
Layout.alignment: Qt.AlignVCenter
|
||||||
|
text: attribute.value.count + " elements"
|
||||||
|
}
|
||||||
|
ToolButton {
|
||||||
|
text: MaterialIcons.add_circle_outline
|
||||||
|
font.family: MaterialIcons.fontFamily
|
||||||
|
font.pointSize: 11
|
||||||
|
padding: 2
|
||||||
|
enabled: true
|
||||||
|
onClicked: _reconstruction.appendAttribute(attribute, undefined)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ListView {
|
||||||
|
id: lv
|
||||||
|
model: listAttribute_layout.expanded ? attribute.value : undefined
|
||||||
|
visible: model != undefined && count > 0
|
||||||
|
implicitHeight: Math.min(contentHeight, 300)
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.margins: 4
|
||||||
|
clip: true
|
||||||
|
spacing: 4
|
||||||
|
|
||||||
|
ScrollBar.vertical: ScrollBar { id: sb }
|
||||||
|
|
||||||
|
delegate: RowLayout {
|
||||||
|
id: item
|
||||||
|
property var childAttrib: object
|
||||||
|
layoutDirection: Qt.RightToLeft
|
||||||
|
width: lv.width - sb.width
|
||||||
|
Component.onCompleted: {
|
||||||
|
var cpt = Qt.createComponent("AttributeItemDelegate.qml")
|
||||||
|
var obj = cpt.createObject(item,
|
||||||
|
{'attribute': Qt.binding(function() { return item.childAttrib }),
|
||||||
|
'readOnly': Qt.binding(function() { return !root.editable })
|
||||||
|
})
|
||||||
|
obj.Layout.fillWidth = true
|
||||||
|
obj.label.text = index
|
||||||
|
obj.label.horizontalAlignment = Text.AlignHCenter
|
||||||
|
obj.label.verticalAlignment = Text.AlignVCenter
|
||||||
|
obj.doubleClicked.connect(function(attr) {root.doubleClicked(attr)})
|
||||||
|
}
|
||||||
|
ToolButton {
|
||||||
|
enabled: root.editable
|
||||||
|
text: MaterialIcons.remove_circle_outline
|
||||||
|
font.family: MaterialIcons.fontFamily
|
||||||
|
font.pointSize: 11
|
||||||
|
padding: 2
|
||||||
|
ToolTip.text: "Remove Element"
|
||||||
|
ToolTip.visible: hovered
|
||||||
|
onClicked: _reconstruction.removeAttribute(item.childAttrib)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: groupAttribute_component
|
||||||
|
ColumnLayout {
|
||||||
|
id: groupItem
|
||||||
|
Component.onCompleted: {
|
||||||
|
var cpt = Qt.createComponent("ImageIntrinsicEditor.qml");
|
||||||
|
var obj = cpt.createObject(groupItem,
|
||||||
|
{
|
||||||
|
'model': Qt.binding(function() { return attribute.value }),
|
||||||
|
'readOnly': Qt.binding(function() { return root.readOnly })
|
||||||
|
})
|
||||||
|
obj.Layout.fillWidth = true;
|
||||||
|
obj.attributeDoubleClicked.connect(function(attr) {root.doubleClicked(attr)})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
40
meshroom/ui/qml/ImageGallery/ImageIntrinsicEditor.qml
Normal file
40
meshroom/ui/qml/ImageGallery/ImageIntrinsicEditor.qml
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
import QtQuick 2.9
|
||||||
|
import QtQuick.Layouts 1.3
|
||||||
|
import QtQuick.Controls 2.2
|
||||||
|
import MaterialIcons 2.2
|
||||||
|
import Utils 1.0
|
||||||
|
|
||||||
|
ListView {
|
||||||
|
id: root
|
||||||
|
property bool readOnly: false
|
||||||
|
property int labelWidth: 180
|
||||||
|
|
||||||
|
signal upgradeRequest()
|
||||||
|
signal attributeDoubleClicked(var mouse, var attribute)
|
||||||
|
|
||||||
|
implicitHeight: contentHeight
|
||||||
|
|
||||||
|
spacing: 2
|
||||||
|
clip: true
|
||||||
|
ScrollBar.vertical: ScrollBar { id: scrollBar }
|
||||||
|
|
||||||
|
delegate: Loader {
|
||||||
|
active: object.enabled && (!object.desc.advanced)
|
||||||
|
visible: active
|
||||||
|
height: item ? item.implicitHeight : -spacing // compensate for spacing if item is hidden
|
||||||
|
|
||||||
|
sourceComponent: ImageIntrinsicDelegate {
|
||||||
|
width: root.width - scrollBar.width
|
||||||
|
readOnly: root.readOnly
|
||||||
|
attribute: object
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper MouseArea to lose edit/activeFocus
|
||||||
|
// when clicking on the background
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
onClicked: root.forceActiveFocus()
|
||||||
|
z: -1
|
||||||
|
}
|
||||||
|
}
|
73
meshroom/ui/qml/ImageGallery/ImageIntrinsicViewer.qml
Normal file
73
meshroom/ui/qml/ImageGallery/ImageIntrinsicViewer.qml
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
import QtQuick 2.9
|
||||||
|
import QtQuick.Controls 2.4
|
||||||
|
import QtQuick.Controls 1.4 as Controls1 // SplitView
|
||||||
|
import QtQuick.Layouts 1.3
|
||||||
|
import MaterialIcons 2.2
|
||||||
|
import Controls 1.0
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NodeEditor allows to visualize and edit the parameters of a Node.
|
||||||
|
* It mainly provides an attribute editor and a log inspector.
|
||||||
|
*/
|
||||||
|
Panel {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property variant intrinsics
|
||||||
|
property bool readOnly: false
|
||||||
|
|
||||||
|
signal attributeDoubleClicked(var mouse, var attribute)
|
||||||
|
signal upgradeRequest()
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
|
Loader {
|
||||||
|
Layout.fillHeight: true
|
||||||
|
Layout.fillWidth: true
|
||||||
|
sourceComponent: root.intrinsics ? editor_component : placeholder_component
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: placeholder_component
|
||||||
|
|
||||||
|
Item {
|
||||||
|
Column {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
MaterialLabel {
|
||||||
|
text: MaterialIcons.select_all
|
||||||
|
font.pointSize: 34
|
||||||
|
color: Qt.lighter(palette.mid, 1.2)
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
}
|
||||||
|
Label {
|
||||||
|
color: Qt.lighter(palette.mid, 1.2)
|
||||||
|
text: "Select a Node to access its Details"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: editor_component
|
||||||
|
|
||||||
|
Controls1.SplitView {
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
|
StackLayout {
|
||||||
|
Layout.fillHeight: true
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
currentIndex: 0
|
||||||
|
|
||||||
|
ImageIntrinsicEditor {
|
||||||
|
Layout.fillHeight: true
|
||||||
|
Layout.fillWidth: true
|
||||||
|
model: root.intrinsics.value
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,3 +2,5 @@ module ImageGallery
|
||||||
|
|
||||||
ImageGallery 1.0 ImageGallery.qml
|
ImageGallery 1.0 ImageGallery.qml
|
||||||
ImageDelegate 1.0 ImageDelegate.qml
|
ImageDelegate 1.0 ImageDelegate.qml
|
||||||
|
ImageIntrinsicDelegate 1.0 ImageIntrinsicDelegate.qml
|
||||||
|
ImageIntrinsicViewer 1.0 ImageIntrinsicViewer.qml
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue