diff --git a/meshroom/env.py b/meshroom/env.py new file mode 100644 index 0000000000..3036db206f --- /dev/null +++ b/meshroom/env.py @@ -0,0 +1,70 @@ +""" +Meshroom environment variable management. +""" + +__all__ = [ + "EnvVar", + "EnvVarHelpAction", +] + +import argparse +import os +from dataclasses import dataclass +from enum import Enum +import sys +from typing import Any, Type + + +@dataclass +class VarDefinition: + """Environment variable definition.""" + + # The type to cast the value to. + valueType: Type + # Default value if the variable is not set in the environment. + default: str + # Description of the purpose of the variable. + description: str = "" + + def __str__(self) -> str: + return f"{self.description} ({self.valueType.__name__}, default: '{self.default}')" + + +class EnvVar(Enum): + """Meshroom environment variables catalog.""" + + # UI - Debug + MESHROOM_QML_DEBUG = VarDefinition(bool, "False", "Enable QML debugging") + MESHROOM_QML_DEBUG_PARAMS = VarDefinition( + str, "port:3768", "QML debugging params as expected by -qmljsdebugger" + ) + + @staticmethod + def get(envVar: "EnvVar") -> Any: + """Get the value of `envVar`, cast to the variable type.""" + value = os.environ.get(envVar.name, envVar.value.default) + return EnvVar._cast(value, envVar.value.valueType) + + @staticmethod + def _cast(value: str, valueType: Type) -> Any: + if valueType is str: + return value + elif valueType is bool: + return value.lower() in {"true", "1", "on"} + return valueType(value) + + @classmethod + def help(cls) -> str: + """Return a formatted string with the details of each environment variables.""" + return "\n".join([f"{var.name}: {var.value}" for var in cls]) + + +class EnvVarHelpAction(argparse.Action): + """Argparse action for printing Meshroom environment variables help and exit.""" + + DEFAULT_HELP = "Print Meshroom environment variables help and exit." + + def __call__(self, parser, namespace, value, option_string=None): + print("Meshroom environment variables:") + print(EnvVar.help()) + sys.exit(0) diff --git a/meshroom/ui/app.py b/meshroom/ui/app.py index 884b885111..82696401da 100644 --- a/meshroom/ui/app.py +++ b/meshroom/ui/app.py @@ -8,6 +8,8 @@ from PySide6 import QtCore from PySide6.QtCore import Qt, QUrl, QJsonValue, qInstallMessageHandler, QtMsgType, QSettings from PySide6.QtGui import QIcon +from PySide6.QtQml import QQmlDebuggingEnabler +from PySide6.QtQuickControls2 import QQuickStyle from PySide6.QtWidgets import QApplication import meshroom @@ -15,6 +17,8 @@ from meshroom.core.taskManager import TaskManager from meshroom.common import Property, Variant, Signal, Slot +from meshroom.env import EnvVar, EnvVarHelpAction + from meshroom.ui import components from meshroom.ui.components.clipboard import ClipboardHelper from meshroom.ui.components.filepath import FilepathHelper @@ -181,17 +185,29 @@ def createMeshroomParser(args): + '\n'.join([' - ' + p for p in meshroom.core.pipelineTemplates]), ) + advanced_group = parser.add_argument_group("Advanced Options") + advanced_group.add_argument( + "--env-help", + action=EnvVarHelpAction, + nargs=0, + help=EnvVarHelpAction.DEFAULT_HELP, + ) + return parser.parse_args(args[1:]) class MeshroomApp(QApplication): """ Meshroom UI Application. """ - def __init__(self, args): + def __init__(self, inputArgs): meshroom.core.initPipelines() - QtArgs = [args[0], '-style', 'Fusion'] + args[1:] # force Fusion style by default - - args = createMeshroomParser(args) + args = createMeshroomParser(inputArgs) + qtArgs = [] + + if EnvVar.get(EnvVar.MESHROOM_QML_DEBUG): + debuggerParams = EnvVar.get(EnvVar.MESHROOM_QML_DEBUG_PARAMS) + self.debugger = QQmlDebuggingEnabler(printWarning=True) + qtArgs = [f"-qmljsdebugger={debuggerParams}"] logStringToPython = { 'fatal': logging.FATAL, @@ -203,7 +219,7 @@ def __init__(self, args): } logging.getLogger().setLevel(logStringToPython[args.verbose]) - super(MeshroomApp, self).__init__(QtArgs) + super(MeshroomApp, self).__init__(inputArgs[:1] + qtArgs) self.setOrganizationName('AliceVision') self.setApplicationName('Meshroom') @@ -213,6 +229,9 @@ def __init__(self, args): font.setPointSize(9) self.setFont(font) + # Use Fusion style by default. + QQuickStyle.setStyle("Fusion") + pwd = os.path.dirname(__file__) self.setWindowIcon(QIcon(os.path.join(pwd, "img/meshroom.svg")))