diff --git a/capellambse/_diagram_cache.py b/capellambse/_diagram_cache.py index 6ba34c52c..a2c56ab65 100644 --- a/capellambse/_diagram_cache.py +++ b/capellambse/_diagram_cache.py @@ -65,6 +65,7 @@ def export( index: bool, force: t.Literal["exe", "docker", None], background: bool, + refresh: bool = False, ) -> None: if not isinstance( getattr(model, "_diagram_cache", None), local.LocalFileHandler @@ -90,6 +91,14 @@ def export( native_args = _find_executor(model, capella, force) with _native.native_capella(model, **native_args) as cli: assert cli.project + + if refresh: + cli( + *_native.ARGS_CMDLINE, + "-appid", + "org.polarsys.capella.refreshRepresentations", + ) + cli( *_native.ARGS_CMDLINE, "-appid", diff --git a/capellambse/diagram_cache.py b/capellambse/diagram_cache.py index 53187e7c4..06231dedd 100644 --- a/capellambse/diagram_cache.py +++ b/capellambse/diagram_cache.py @@ -5,6 +5,7 @@ import pathlib import sys +import typing as t import capellambse from capellambse import _diagram_cache, cli_helpers @@ -27,8 +28,8 @@ def _main() -> None: @click.option( "-m", "--model", - "model_", - type=cli_helpers.ModelCLI(), + "modelinfo", + type=cli_helpers.ModelInfoCLI(), required=True, help="Capella model to export diagrams from", ) @@ -56,6 +57,16 @@ def _main() -> None: help="Generate index.json and index.html files", show_default=True, ) + @click.option( + "--refresh / --no-refresh", + default=False, + help=( + "Refresh all diagrams before exporting them, to make sure their" + " contents are up to date with the model. Recommended, but" + " disabled by default because it may take a long time." + " NOTE: This may temporarily open a Capella window (see above)." + ), + ) @click.option("--exe", help="Name or path of the Capella executable") @click.option("--docker", help="Name of a Docker image containing Capella") @click.option( @@ -65,36 +76,67 @@ def _main() -> None: show_default=True, ) def _main( - model_: capellambse.MelodyModel, + modelinfo: dict[str, t.Any], output: pathlib.Path, format: str, index: bool, exe: str | None, docker: str | None, background: bool, - ) -> None: - model_._diagram_cache = capellambse.get_filehandler(output) - model_._diagram_cache_subdir = pathlib.PurePosixPath(".") + refresh: bool, + ) -> None: # noqa: D301 + """Export diagrams from a Capella model. + + This tool can be used to easily populate a diagram cache for use + with `capellambse.MelodyModel`. + + \b + Refreshing representations + -------------------------- + + By default, Capella will only automatically refresh diagrams on + an as-needed basis whenever a diagram is opened in the GUI. This + can lead to out-of-date images being written by its + "exportRepresentations" facility, which this tool uses. + + To avoid this problem, the '--refresh' switch can be used to + automatically refresh all diagrams and make sure they are up to + date with the model contents. + + Unfortunately, due to the way this refresh operation is + implemented in Capella, this may cause a Capella window to be + opened temporarily. It will automatically close once the + operation is done. + + PLEASE DO NOT CLOSE THE WINDOW that Capella opens during this + step, or the entire process will be aborted. + + Also be aware that using this option may lead to new objects + being added in odd places, which may cause severe readability + issues on the exported diagrams. + + Due to these issues, the automatic refresh is disabled by + default. + """ + modelinfo["diagram_cache"] = {"path": output} + model_ = capellambse.MelodyModel(**modelinfo) if docker: - _diagram_cache.export( - docker, - model_, - format=format, - index=index, - force="docker", - background=background, - ) + capella = docker + force = "docker" else: - exe = exe or "capella{VERSION}" - _diagram_cache.export( - exe, - model_, - format=format, - index=index, - force="exe", - background=background, - ) + capella = exe or "capella{VERSION}" + force = "exe" + + _diagram_cache.export( + capella, + model_, + format=format, + index=index, + force=force, # type: ignore + background=background, + refresh=refresh, + ) if __name__ == "__main__":