mirror of
https://github.com/alicevision/Meshroom.git
synced 2025-07-16 16:25:20 +02:00
[ui] Inspector3D: add media contextual menu
Contextual menu to expose additional actions: * open media containing folder * copy media path * advanced manual control over media (un)loading + fix MediaLibrary to avoid binding loop on 'visible' when directly modifying 'request' property
This commit is contained in:
parent
272cd24fb9
commit
c3750a33c3
3 changed files with 37 additions and 5 deletions
|
@ -72,3 +72,9 @@ class FilepathHelper(QObject):
|
||||||
def stringToUrl(self, path):
|
def stringToUrl(self, path):
|
||||||
""" Convert a path (string) to a QUrl using 'QUrl.fromLocalFile' method """
|
""" Convert a path (string) to a QUrl using 'QUrl.fromLocalFile' method """
|
||||||
return QUrl.fromLocalFile(path)
|
return QUrl.fromLocalFile(path)
|
||||||
|
|
||||||
|
@Slot(str, result=str)
|
||||||
|
@Slot(QUrl, result=str)
|
||||||
|
def normpath(self, path):
|
||||||
|
""" Returns native normalized path """
|
||||||
|
return os.path.normpath(self.asStr(path))
|
||||||
|
|
|
@ -193,7 +193,7 @@ FloatingPane {
|
||||||
Layout.alignment: Qt.AlignTop
|
Layout.alignment: Qt.AlignTop
|
||||||
text: model.visible ? MaterialIcons.visibility : MaterialIcons.visibility_off
|
text: model.visible ? MaterialIcons.visibility : MaterialIcons.visibility_off
|
||||||
font.pointSize: 10
|
font.pointSize: 10
|
||||||
ToolTip.text: model.visible ? "Hide" : "Show"
|
ToolTip.text: model.visible ? "Hide" : model.requested ? "Show" : model.valid ? "Load and Show" : "Load and Show when Available"
|
||||||
flat: true
|
flat: true
|
||||||
opacity: model.visible ? 1.0 : 0.6
|
opacity: model.visible ? 1.0 : 0.6
|
||||||
onClicked: {
|
onClicked: {
|
||||||
|
@ -272,6 +272,7 @@ FloatingPane {
|
||||||
id: mouseArea
|
id: mouseArea
|
||||||
anchors.fill: centralLayout
|
anchors.fill: centralLayout
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
|
acceptedButtons: Qt.AllButtons
|
||||||
onEntered: { if(model.attribute) uigraph.hoveredNode = model.attribute.node }
|
onEntered: { if(model.attribute) uigraph.hoveredNode = model.attribute.node }
|
||||||
onExited: { if(model.attribute) uigraph.hoveredNode = null }
|
onExited: { if(model.attribute) uigraph.hoveredNode = null }
|
||||||
onClicked: {
|
onClicked: {
|
||||||
|
@ -279,6 +280,8 @@ FloatingPane {
|
||||||
uigraph.selectedNode = model.attribute.node;
|
uigraph.selectedNode = model.attribute.node;
|
||||||
else
|
else
|
||||||
uigraph.selectedNode = null;
|
uigraph.selectedNode = null;
|
||||||
|
if(mouse.button == Qt.RightButton)
|
||||||
|
contextMenu.popup();
|
||||||
mediaListView.currentIndex = index;
|
mediaListView.currentIndex = index;
|
||||||
}
|
}
|
||||||
onDoubleClicked: {
|
onDoubleClicked: {
|
||||||
|
@ -286,6 +289,27 @@ FloatingPane {
|
||||||
camera.viewEntity(mediaLibrary.entityAt(index));
|
camera.viewEntity(mediaLibrary.entityAt(index));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Menu {
|
||||||
|
id: contextMenu
|
||||||
|
MenuItem {
|
||||||
|
text: "Open Containing Folder"
|
||||||
|
enabled: model.valid
|
||||||
|
onTriggered: Qt.openUrlExternally(Filepath.dirname(model.source))
|
||||||
|
}
|
||||||
|
MenuItem {
|
||||||
|
text: "Copy Path"
|
||||||
|
// hidden TextEdit to copy to clipboard
|
||||||
|
TextEdit { id: fullpath; visible: false; text: Filepath.normpath(model.source) }
|
||||||
|
onTriggered: { fullpath.selectAll(); fullpath.copy(); }
|
||||||
|
}
|
||||||
|
MenuSeparator {}
|
||||||
|
MenuItem {
|
||||||
|
text: model.requested ? "Unload Media" : "Load Media"
|
||||||
|
enabled: model.valid
|
||||||
|
onTriggered: model.requested = !model.requested
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Media unavailability indicator
|
// Media unavailability indicator
|
||||||
|
|
|
@ -194,10 +194,8 @@ Entity {
|
||||||
if(attribute) {
|
if(attribute) {
|
||||||
model.source = rawSource;
|
model.source = rawSource;
|
||||||
}
|
}
|
||||||
// auto-restore entity if raw source is in cache ...
|
// auto-restore entity if raw source is in cache
|
||||||
model.requested = forceRequest || (!model.valid && model.requested) || cache.contains(rawSource);
|
model.requested = forceRequest || (!model.valid && model.requested) || cache.contains(rawSource);
|
||||||
// ... and update media visibility (useful if media was hidden but loaded back from cache)
|
|
||||||
model.visible = model.requested;
|
|
||||||
model.valid = Filepath.exists(rawSource) && dependencyReady;
|
model.valid = Filepath.exists(rawSource) && dependencyReady;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -211,9 +209,13 @@ Entity {
|
||||||
remove(index)
|
remove(index)
|
||||||
}
|
}
|
||||||
|
|
||||||
onCurrentSourceChanged: updateModelAndCache()
|
onCurrentSourceChanged: updateModelAndCache(false)
|
||||||
|
|
||||||
onFinalSourceChanged: {
|
onFinalSourceChanged: {
|
||||||
|
// update media visibility
|
||||||
|
// (useful if media was explicitly unloaded or hidden but loaded back from cache)
|
||||||
|
model.visible = model.requested;
|
||||||
|
|
||||||
var cachedObject = cache.pop(rawSource);
|
var cachedObject = cache.pop(rawSource);
|
||||||
cached = cachedObject !== undefined;
|
cached = cachedObject !== undefined;
|
||||||
if(cached) {
|
if(cached) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue