mirror of
https://github.com/alicevision/Meshroom.git
synced 2025-05-31 09:56:32 +02:00
[ui] handle multiple CameraInit nodes in a Reconstruction
* [ui] ImageGallery: add control to navigate image groups * [graph] expose Node.attribute as a Slot
This commit is contained in:
parent
1f0ed1f2c9
commit
273cfd9f0e
5 changed files with 220 additions and 122 deletions
|
@ -2,17 +2,18 @@ import QtQuick 2.7
|
|||
import QtQuick.Controls 2.3
|
||||
import QtQuick.Layouts 1.3
|
||||
import MaterialIcons 2.2
|
||||
import "filepath.js" as Filepath
|
||||
import QtQml.Models 2.2
|
||||
|
||||
|
||||
/**
|
||||
* 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 alias model: grid.model
|
||||
property variant cameraInits
|
||||
property variant cameraInit
|
||||
readonly property string currentItemSource: grid.currentItem ? grid.currentItem.source : ""
|
||||
readonly property var currentItemMetadata: grid.currentItem ? grid.currentItem.metadata : undefined
|
||||
signal removeImageRequest(var attribute)
|
||||
|
@ -21,9 +22,13 @@ Panel {
|
|||
implicitWidth: 100
|
||||
implicitHeight: 300
|
||||
title: "Images"
|
||||
property int currentIndex: 0
|
||||
readonly property variant viewpoints: cameraInit.attribute('viewpoints').value
|
||||
signal filesDropped(var drop)
|
||||
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
spacing: 4
|
||||
|
||||
GridView {
|
||||
id: grid
|
||||
|
@ -31,102 +36,46 @@ Panel {
|
|||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
|
||||
cellWidth: thumbnailSizeSlider.value
|
||||
cellHeight: cellWidth
|
||||
ScrollBar.vertical: ScrollBar {}
|
||||
keyNavigationEnabled: true
|
||||
highlightFollowsCurrentItem: true
|
||||
|
||||
focus: true
|
||||
clip: true
|
||||
cellWidth: thumbnailSizeSlider.value
|
||||
cellHeight: cellWidth
|
||||
highlightFollowsCurrentItem: true
|
||||
keyNavigationEnabled: true
|
||||
model: root.viewpoints
|
||||
|
||||
|
||||
delegate: Item {
|
||||
id: imageDelegate
|
||||
|
||||
readonly property bool isCurrentItem: grid.currentIndex == index
|
||||
readonly property alias source: _viewpoint.source
|
||||
readonly property alias metadata: _viewpoint.metadata
|
||||
|
||||
// retrieve viewpoints inner data
|
||||
QtObject {
|
||||
id: _viewpoint
|
||||
readonly property string source: object.value.get("path").value
|
||||
readonly property var metadata: JSON.parse(object.value.get("metadata").value)
|
||||
// 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.currentIndex = Math.min(root.cameraInits.count - 1, root.currentIndex + 1)
|
||||
else if(event.key == Qt.Key_Left)
|
||||
root.currentIndex = Math.max(0, root.currentIndex - 1)
|
||||
}
|
||||
}
|
||||
|
||||
delegate: ImageDelegate {
|
||||
viewpoint: object.value
|
||||
width: grid.cellWidth
|
||||
height: grid.cellHeight
|
||||
|
||||
MouseArea {
|
||||
id: imageMA
|
||||
anchors.fill: parent
|
||||
anchors.margins: 6
|
||||
hoverEnabled: true
|
||||
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
||||
onPressed: {
|
||||
grid.currentIndex = index
|
||||
if(mouse.button == Qt.RightButton)
|
||||
imageMenu.popup()
|
||||
else
|
||||
grid.forceActiveFocus()
|
||||
}
|
||||
Menu {
|
||||
id: imageMenu
|
||||
MenuItem {
|
||||
text: "Show Containing Folder"
|
||||
onClicked: {
|
||||
Qt.openUrlExternally(Filepath.dirname(imageDelegate.source))
|
||||
}
|
||||
}
|
||||
MenuItem {
|
||||
text: "Remove"
|
||||
enabled: !root.readOnly
|
||||
onClicked: removeImageRequest(object)
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
spacing: 0
|
||||
|
||||
// Image thumbnail and background
|
||||
Rectangle {
|
||||
id: imageBackground
|
||||
color: Qt.darker(palette.base, 1.15)
|
||||
Layout.fillHeight: true
|
||||
Layout.fillWidth: true
|
||||
border.color: grid.currentIndex == index ? palette.highlight : Qt.darker(palette.highlight)
|
||||
border.width: imageMA.containsMouse || imageDelegate.isCurrentItem ? 2 : 0
|
||||
Image {
|
||||
anchors.fill: parent
|
||||
anchors.margins: 4
|
||||
source: imageDelegate.source
|
||||
sourceSize: Qt.size(100, 100)
|
||||
asynchronous: true
|
||||
autoTransform: true
|
||||
fillMode: Image.PreserveAspectFit
|
||||
}
|
||||
}
|
||||
// Image basename
|
||||
Label {
|
||||
Layout.fillWidth: true
|
||||
padding: 2
|
||||
font.pointSize: 8
|
||||
elide: Text.ElideMiddle
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
text: Filepath.basename(imageDelegate.source)
|
||||
background: Rectangle {
|
||||
color: imageDelegate.isCurrentItem ? palette.highlight : "transparent"
|
||||
}
|
||||
}
|
||||
}
|
||||
isCurrentItem: grid.currentIndex == index
|
||||
onPressed: {
|
||||
grid.currentIndex = index
|
||||
if(mouse.button == Qt.LeftButton)
|
||||
grid.forceActiveFocus()
|
||||
}
|
||||
}
|
||||
|
||||
// Explanatory placeholder when no image has been added yet
|
||||
Column {
|
||||
anchors.centerIn: parent
|
||||
visible: model.count == 0
|
||||
visible: grid.model.count == 0
|
||||
spacing: 4
|
||||
Label {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
@ -145,7 +94,7 @@ Panel {
|
|||
enabled: !root.readOnly
|
||||
// TODO: onEntered: call specific method to filter files based on extension
|
||||
onDropped: {
|
||||
_reconstruction.handleFilesDrop(drop)
|
||||
root.filesDropped(drop)
|
||||
}
|
||||
// DropArea overlay
|
||||
Rectangle {
|
||||
|
@ -156,6 +105,40 @@ Panel {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Layout.fillHeight: false
|
||||
visible: root.cameraInits.count > 1
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
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 { text: "Group " }
|
||||
ComboBox {
|
||||
id: nodesCB
|
||||
model: root.cameraInits.count
|
||||
implicitWidth: 40
|
||||
currentIndex: root.currentIndex
|
||||
onActivated: root.currentIndex = 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 {
|
||||
|
@ -164,7 +147,7 @@ Panel {
|
|||
// Image count
|
||||
Label {
|
||||
Layout.fillWidth: true
|
||||
text: model.count + " image" + (model.count > 1 ? "s" : "")
|
||||
text: grid.model.count + " image" + (grid.model.count > 1 ? "s" : "")
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue