[ui] Generate the "New Pipeline" menu based on the found project files

The "New Pipeline" menu is automatically filled with the list
of the project files that were found dynamically. Pipelines can thus
be initialized with templates without restarting Meshroom app.
This commit is contained in:
Candice Bentéjac 2022-07-13 18:20:34 +02:00
parent 8fb0c778d1
commit 578c1f01c0
2 changed files with 43 additions and 31 deletions

View file

@ -1,5 +1,6 @@
import logging import logging
import os import os
import re
import argparse import argparse
from PySide2.QtCore import Qt, QUrl, Slot, QJsonValue, Property, Signal, qInstallMessageHandler, QtMsgType, QSettings from PySide2.QtCore import Qt, QUrl, Slot, QJsonValue, Property, Signal, qInstallMessageHandler, QtMsgType, QSettings
@ -177,6 +178,16 @@ class MeshroomApp(QApplication):
self.engine.load(os.path.normpath(url)) self.engine.load(os.path.normpath(url))
def _pipelineTemplateFiles(self):
templates = []
for key in sorted(meshroom.core.pipelineTemplates.keys()):
# Use uppercase letters in the names as separators to format the templates' name nicely
# e.g: the template "panoramaHdr" will be shown as "Panorama Hdr" in the menu
name = " ".join(re.findall('[A-Z][^A-Z]*', key[0].upper() + key[1:]))
variant = {"name": name, "key": key, "path": meshroom.core.pipelineTemplates[key]}
templates.append(variant)
return templates
def _recentProjectFiles(self): def _recentProjectFiles(self):
projects = [] projects = []
settings = QSettings() settings = QSettings()
@ -317,6 +328,7 @@ class MeshroomApp(QApplication):
} }
] ]
pipelineTemplateFilesChanged = Signal()
recentProjectFilesChanged = Signal() recentProjectFilesChanged = Signal()
pipelineTemplateFiles = Property("QVariantList", _pipelineTemplateFiles, notify=pipelineTemplateFilesChanged)
recentProjectFiles = Property("QVariantList", _recentProjectFiles, notify=recentProjectFilesChanged) recentProjectFiles = Property("QVariantList", _recentProjectFiles, notify=recentProjectFilesChanged)

View file

@ -409,38 +409,38 @@ ApplicationWindow {
onTriggered: ensureSaved(function() { _reconstruction.new() }) onTriggered: ensureSaved(function() { _reconstruction.new() })
} }
Menu { Menu {
id: newPipelineMenu
title: "New Pipeline" title: "New Pipeline"
TextMetrics { enabled: newPipelineMenuItems.model != undefined && newPipelineMenuItems.model.length > 0
id: textMetrics property int maxWidth: 1000
font: action_PG_CT.font property int fullWidth: {
elide: Text.ElideNone var result = 0;
text: action_PG_CT.text for (var i = 0; i < count; ++i) {
var item = itemAt(i);
result = Math.max(item.implicitWidth + item.padding * 2, result);
}
return result;
} }
implicitWidth: textMetrics.width + 10 // largest text width + margin implicitWidth: fullWidth
Action { Repeater {
text: "Photogrammetry" id: newPipelineMenuItems
onTriggered: ensureSaved(function() { _reconstruction.new("photogrammetry") }) model: MeshroomApp.pipelineTemplateFiles
} MenuItem {
Action { onTriggered: ensureSaved(function() {
text: "Panorama HDR" _reconstruction.new(modelData["key"])
onTriggered: ensureSaved(function() { _reconstruction.new("panoramahdr") }) })
}
Action { text: fileTextMetrics.elidedText
text: "Panorama Fisheye HDR" TextMetrics {
onTriggered: ensureSaved(function() { _reconstruction.new("panoramafisheyehdr") }) id: fileTextMetrics
} text: modelData["name"]
Action { elide: Text.ElideLeft
id: action_PG_CT elideWidth: newPipelineMenu.maxWidth
text: "Photogrammetry and Camera Tracking (experimental)" }
onTriggered: ensureSaved(function() { _reconstruction.new("photogrammetryandcameratracking") }) ToolTip.text: modelData["path"]
} ToolTip.visible: hovered
Action { ToolTip.delay: 200
text: "Camera Tracking (experimental)" }
onTriggered: ensureSaved(function() { _reconstruction.new("cameratracking") })
}
Action {
text: "Photogrammetry Draft (No CUDA)"
onTriggered: ensureSaved(function() { _reconstruction.new("photogrammetrydraft") })
} }
} }
Action { Action {