flamenco/addon/flamenco/preferences.py
Sybren A. Stüvel 3b4da656c9 Add-on: cache manager info in a JSON file
Instead of storing the cached manager info in the Blender preferences,
store the info in a JSON file. The file is located in the user prefs
folder (`~/.config/blender/{version}/config` on Linux).

This also reduces the number of 'refresh' operators to a single one, which
then fetches all necessary info from the Manager.

This fixes an issue (reported via chat) where worker tags were sometimes
not retained across file saves.
2024-03-04 13:08:53 +01:00

169 lines
5.2 KiB
Python

# SPDX-License-Identifier: GPL-3.0-or-later
# <pep8 compliant>
from pathlib import Path
import bpy
from . import projects, manager_info
def discard_flamenco_client(context):
"""Discard any cached Flamenco client after the Manager URL changes."""
from . import comms
comms.discard_flamenco_data()
context.window_manager.flamenco_status_ping = ""
def _refresh_the_planet(context: bpy.types.Context) -> None:
"""Refresh all GUI areas."""
for win in context.window_manager.windows:
for area in win.screen.areas:
for region in area.regions:
region.tag_redraw()
def _manager_url_updated(prefs, context):
discard_flamenco_client(context)
from . import comms
api_client = comms.flamenco_api_client(prefs.manager_url)
# Warning, be careful what of the context to access here. Accessing /
# changing too much can cause crashes, infinite loops, etc.
comms.ping_manager(context.window_manager, context.scene, api_client)
_refresh_the_planet(context)
_project_finder_enum_items = [
(key, info.label, info.description) for key, info in projects.finders.items()
]
class WorkerTag(bpy.types.PropertyGroup):
id: bpy.props.StringProperty(name="id") # type: ignore
name: bpy.props.StringProperty(name="Name") # type: ignore
description: bpy.props.StringProperty(name="Description") # type: ignore
class FlamencoPreferences(bpy.types.AddonPreferences):
bl_idname = "flamenco"
manager_url: bpy.props.StringProperty( # type: ignore
name="Manager URL",
description="Location of the Manager",
default="http://localhost:8080/",
update=_manager_url_updated,
)
project_finder: bpy.props.EnumProperty( # type: ignore
name="Project Finder",
description="Strategy for Flamenco to find the top level directory of your project",
default=_project_finder_enum_items[0][0],
items=_project_finder_enum_items,
)
# Property that gets its value from the above _job_storage, and cannot be
# set. This makes it read-only in the GUI.
job_storage_for_gui: bpy.props.StringProperty( # type: ignore
name="Job Storage Directory",
subtype="DIR_PATH",
default="",
options={"SKIP_SAVE"},
description="Directory where blend files are stored when submitting them to Flamenco. This value is determined by Flamenco Manager",
get=lambda prefs: prefs._job_storage(),
)
def draw(self, context: bpy.types.Context) -> None:
layout = self.layout
layout.use_property_decorate = False
layout.use_property_split = True
col = layout.column()
row = col.row(align=True)
row.prop(self, "manager_url")
row.operator("flamenco.ping_manager", text="", icon="FILE_REFRESH")
def text_row(parent, label):
split = parent.split(factor=0.4)
split.label(text="")
split.label(text=label)
manager = manager_info.load_cached()
if not manager:
text_row(col, "Press the refresh button before using Flamenco")
if context.window_manager.flamenco_status_ping:
text_row(col, context.window_manager.flamenco_status_ping)
else:
aligned = col.column(align=True)
text_row(aligned, "Press the refresh button to check the connection")
text_row(aligned, "and update the job storage location")
if manager and manager.shared_storage.shaman_enabled:
text_row(col, "Shaman enabled")
col.prop(self, "job_storage_for_gui", text="Job Storage")
# Project Root
col = layout.column(align=True)
col.prop(self, "project_finder")
try:
project_root = self.project_root()
except ValueError:
pass
else:
text_row(col, str(project_root))
def project_root(self) -> Path:
"""Use the configured project finder to find the project root directory."""
if not self.project_finder:
# Just a sanity fallback for missing preferences. It should be
# covered by the 'default=...' of the property, but just to be sure.
self.project_finder = "BLENDER_PROJECT"
# It is assumed that the blendfile is saved.
blendfile = Path(bpy.data.filepath)
return projects.for_blendfile(blendfile, self.project_finder)
def _job_storage(self) -> str:
info = manager_info.load_cached()
if not info:
return "Unknown, refresh first."
return str(info.shared_storage.location)
def get(context: bpy.types.Context) -> FlamencoPreferences:
"""Return the add-on preferences."""
prefs = context.preferences.addons["flamenco"].preferences
assert isinstance(
prefs, FlamencoPreferences
), "Expected FlamencoPreferences, got %s instead" % (type(prefs))
return prefs
def manager_url(context: bpy.types.Context) -> str:
"""Returns the configured Manager URL."""
prefs = get(context)
return str(prefs.manager_url)
classes = (
WorkerTag,
FlamencoPreferences,
)
_register, _unregister = bpy.utils.register_classes_factory(classes)
def register():
_register()
bpy.context.window_manager.flamenco_status_ping = ""
def unregister():
_unregister()