feat(presets): Implement NamedViewPresets for per-file view settings
This commit is contained in:
@@ -226,6 +226,7 @@ class AppController:
|
||||
self._pending_actions: Dict[str, ConfirmDialog] = {}
|
||||
self._pending_ask_dialog: bool = False
|
||||
self.mcp_config: models.MCPConfiguration = models.MCPConfiguration()
|
||||
self.view_presets: list[models.NamedViewPreset] = []
|
||||
self.rag_config: Optional[models.RAGConfig] = None
|
||||
self.rag_engine: Optional[rag_engine.RAGEngine] = None
|
||||
self.rag_status: str = 'idle'
|
||||
@@ -2449,6 +2450,12 @@ class AppController:
|
||||
self.tool_presets = self.tool_preset_manager.load_all_presets()
|
||||
self.bias_profiles = self.tool_preset_manager.load_all_bias_profiles()
|
||||
|
||||
raw_presets = proj.get("view_presets", [])
|
||||
if isinstance(raw_presets, dict):
|
||||
self.view_presets = [models.NamedViewPreset.from_dict({"name": name, **data}) for name, data in raw_presets.items()]
|
||||
else:
|
||||
self.view_presets = [models.NamedViewPreset.from_dict(p) for p in raw_presets if isinstance(p, dict)]
|
||||
|
||||
if self.rag_config and self.rag_config.enabled:
|
||||
self._rebuild_rag_index()
|
||||
|
||||
@@ -2561,6 +2568,41 @@ class AppController:
|
||||
self.persona_manager.delete_persona(name, scope)
|
||||
self.personas = self.persona_manager.load_all()
|
||||
|
||||
def _cb_save_view_preset(self, name: str, f_item: models.FileItem) -> None:
|
||||
"""
|
||||
[C: src/gui_2.py:App._render_files_panel]
|
||||
"""
|
||||
preset = models.NamedViewPreset(
|
||||
name=name,
|
||||
view_mode=f_item.view_mode,
|
||||
ast_mask=copy.deepcopy(f_item.ast_mask) if hasattr(f_item, "ast_mask") else {},
|
||||
custom_slices=copy.deepcopy(f_item.custom_slices) if hasattr(f_item, "custom_slices") else []
|
||||
)
|
||||
for i, vp in enumerate(self.view_presets):
|
||||
if vp.name == name:
|
||||
self.view_presets[i] = preset
|
||||
break
|
||||
else:
|
||||
self.view_presets.append(preset)
|
||||
self._flush_to_project()
|
||||
|
||||
def _cb_apply_view_preset(self, name: str, f_item: models.FileItem) -> None:
|
||||
"""
|
||||
[C: src/gui_2.py:App._render_files_panel]
|
||||
"""
|
||||
preset = next((vp for vp in self.view_presets if vp.name == name), None)
|
||||
if preset:
|
||||
f_item.view_mode = preset.view_mode
|
||||
f_item.ast_mask = copy.deepcopy(preset.ast_mask)
|
||||
f_item.custom_slices = copy.deepcopy(preset.custom_slices)
|
||||
|
||||
def _cb_delete_view_preset(self, name: str) -> None:
|
||||
"""
|
||||
[C: src/gui_2.py:App._render_files_panel]
|
||||
"""
|
||||
self.view_presets = [vp for vp in self.view_presets if vp.name != name]
|
||||
self._flush_to_project()
|
||||
|
||||
|
||||
def _cb_load_track(self, track_id: str) -> None:
|
||||
"""
|
||||
@@ -3011,6 +3053,7 @@ class AppController:
|
||||
disc_sec["roles"] = self.disc_roles
|
||||
disc_sec["active"] = self.active_discussion
|
||||
disc_sec["auto_add"] = self.ui_auto_add_history
|
||||
proj["view_presets"] = [vp.to_dict() for vp in self.view_presets]
|
||||
# Save MMA State
|
||||
mma_sec = proj.setdefault("mma", {})
|
||||
mma_sec["epic"] = self.ui_epic_input
|
||||
|
||||
@@ -238,6 +238,7 @@ class App:
|
||||
self.shader_uniforms = {'crt': 1.0, 'scanline': 0.5, 'bloom': 0.8}
|
||||
self.shader_uniforms = {'crt': 1.0, 'scanline': 0.5, 'bloom': 0.8}
|
||||
self.ui_new_context_preset_name = ""
|
||||
self.ui_new_vp_name = ""
|
||||
self._focus_md_cache: dict[str, str] = {}
|
||||
self.ui_inspecting_ast_file = None
|
||||
self._show_ast_inspector = False
|
||||
@@ -3048,6 +3049,34 @@ class App:
|
||||
changed_vm, new_idx = imgui.combo(f"##vm{i}", current_idx, view_modes)
|
||||
if changed_vm:
|
||||
f_item.view_mode = view_modes[new_idx]
|
||||
|
||||
imgui.same_line()
|
||||
if imgui.button(f"[Save]##vpsave{i}"):
|
||||
imgui.open_popup(f"save_vp_popup{i}")
|
||||
|
||||
if imgui.begin_popup(f"save_vp_popup{i}"):
|
||||
imgui.text("Preset Name:")
|
||||
changed_pname, self.ui_new_vp_name = imgui.input_text(f"##pname{i}", self.ui_new_vp_name)
|
||||
if imgui.button("OK"):
|
||||
if self.ui_new_vp_name.strip():
|
||||
self.controller._cb_save_view_preset(self.ui_new_vp_name.strip(), f_item)
|
||||
self.ui_new_vp_name = ""
|
||||
imgui.close_current_popup()
|
||||
imgui.end_popup()
|
||||
|
||||
imgui.same_line()
|
||||
if imgui.button(f"[Load]##vpload{i}"):
|
||||
imgui.open_popup(f"load_vp_popup{i}")
|
||||
|
||||
if imgui.begin_popup(f"load_vp_popup{i}"):
|
||||
vp_names = sorted([vp.name for vp in self.controller.view_presets])
|
||||
if not vp_names:
|
||||
imgui.text("No presets saved.")
|
||||
for vp_name in vp_names:
|
||||
if imgui.selectable(vp_name):
|
||||
self.controller._cb_apply_view_preset(vp_name, f_item)
|
||||
imgui.close_current_popup()
|
||||
imgui.end_popup()
|
||||
if hasattr(f_item, "custom_slices") and f_item.custom_slices:
|
||||
imgui.same_line()
|
||||
imgui.text_colored(imgui.ImVec4(1.0, 0.5, 0.0, 1.0), "[Slices Active]")
|
||||
|
||||
@@ -939,6 +939,30 @@ class FileViewPreset:
|
||||
view_mode=data.get("view_mode", "summary")
|
||||
)
|
||||
|
||||
@dataclass
|
||||
class NamedViewPreset:
|
||||
name: str
|
||||
view_mode: str
|
||||
ast_mask: dict = field(default_factory=dict)
|
||||
custom_slices: list = field(default_factory=list)
|
||||
|
||||
def to_dict(self) -> dict[str, Any]:
|
||||
return {
|
||||
"name": self.name,
|
||||
"view_mode": self.view_mode,
|
||||
"ast_mask": self.ast_mask,
|
||||
"custom_slices": self.custom_slices
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, data: dict[str, Any]) -> "NamedViewPreset":
|
||||
return cls(
|
||||
name=data.get("name", ""),
|
||||
view_mode=data.get("view_mode", "summary"),
|
||||
ast_mask=data.get("ast_mask", {}),
|
||||
custom_slices=data.get("custom_slices", [])
|
||||
)
|
||||
|
||||
@dataclass
|
||||
class ContextPreset:
|
||||
name: str
|
||||
|
||||
Reference in New Issue
Block a user