fixing bugs in gui_2.py

This commit is contained in:
2026-05-11 22:19:04 -04:00
parent 26ef81a30e
commit 5e947d50fe
+141 -130
View File
@@ -8,6 +8,7 @@ import sys
import os import os
import shutil import shutil
import copy import copy
import threading
from pathlib import Path from pathlib import Path
from tkinter import filedialog, Tk from tkinter import filedialog, Tk
from typing import Optional, Any from typing import Optional, Any
@@ -1769,133 +1770,144 @@ class App:
if self._show_ast_inspector: if self._show_ast_inspector:
imgui.open_popup('AST Inspector') imgui.open_popup('AST Inspector')
self._show_ast_inspector = False self._show_ast_inspector = False
#region: AST Inspector
expanded, opened = imgui.begin_popup_modal('AST Inspector', True, imgui.WindowFlags_.always_auto_resize) expanded, opened = imgui.begin_popup_modal('AST Inspector', True, imgui.WindowFlags_.always_auto_resize)
if not opened: if opened:
return if expanded:
if self.ui_inspecting_ast_file is None: if self.ui_inspecting_ast_file is None:
imgui.close_current_popup() imgui.close_current_popup()
imgui.end_popup()
return
f_item = self.ui_inspecting_ast_file
f_path = f_item.path if hasattr(f_item, "path") else str(f_item)
if f_path != self._cached_ast_file_path:
outline = ""
try:
if f_path.lower().endswith('.py'):
outline = mcp_client.py_get_code_outline(f_path)
elif f_path.lower().endswith(('.c', '.h')):
outline = mcp_client.ts_c_get_code_outline(f_path)
else: else:
outline = mcp_client.ts_cpp_get_code_outline(f_path) f_item = self.ui_inspecting_ast_file
except Exception as e: f_path = f_item.path if hasattr(f_item, "path") else str(f_item)
outline = f"Error fetching outline: {e}"
self._cached_ast_nodes = [] if f_path != self._cached_ast_file_path:
import re outline = ""
pattern = re.compile(r'^(\s*)\[(.*?)\] (.*?) \(Lines (\d+)-(\d+)\)') try:
stack = [] # (indent, name) if f_path.lower().endswith('.py'):
for line in outline.splitlines(): outline = mcp_client.py_get_code_outline(f_path)
m = pattern.match(line) elif f_path.lower().endswith(('.c', '.h')):
if m: outline = mcp_client.ts_c_get_code_outline(f_path)
indent_str, kind, name, start_ln, end_ln = m.groups() else:
indent = len(indent_str) outline = mcp_client.ts_cpp_get_code_outline(f_path)
while stack and stack[-1][0] >= indent: except Exception as e:
stack.pop() outline = f"Error fetching outline: {e}"
stack.append((indent, name))
full_path = '::'.join([s[1] for s in stack])
self._cached_ast_nodes.append({
'indent': indent,
'kind': kind,
'name': name,
'full_path': full_path,
'start_line': int(start_ln),
'end_line': int(end_ln)
})
try:
content = mcp_client.read_file(f_path)
self._cached_ast_file_lines = content.splitlines()
except Exception:
self._cached_ast_file_lines = ["Error loading file content."]
self._cached_ast_file_path = f_path
imgui.text(f"Inspecting AST: {f_path}") self._cached_ast_nodes = []
imgui.separator() import re
pattern = re.compile(r'^(\s*)\[(.*?)\] (.*?) \(Lines (\d+)-(\d+)\)')
stack = [] # (indent, name)
for line in outline.splitlines():
m = pattern.match(line)
if m:
indent_str, kind, name, start_ln, end_ln = m.groups()
indent = len(indent_str)
while stack and stack[-1][0] >= indent:
stack.pop()
stack.append((indent, name))
full_path = '::'.join([s[1] for s in stack])
self._cached_ast_nodes.append({
'indent': indent,
'kind': kind,
'name': name,
'full_path': full_path,
'start_line': int(start_ln),
'end_line': int(end_ln)
})
try:
content = mcp_client.read_file(f_path)
self._cached_ast_file_lines = content.splitlines()
except Exception:
self._cached_ast_file_lines = ["Error loading file content."]
self._cached_ast_file_path = f_path
if imgui.begin_table('ast_dual_pane', 2, imgui.TableFlags_.resizable | imgui.TableFlags_.borders_inner_v): imgui.text(f"Inspecting AST: {f_path}")
imgui.table_next_column() imgui.separator()
# --- LEFT COLUMN (Tree) --- #region: ast_dual_pane
imgui.begin_child("ast_tree_scroll", imgui.ImVec2(0, 600), True) if imgui.begin_table('ast_dual_pane', 2, imgui.TableFlags_.resizable | imgui.TableFlags_.borders_inner_v):
if not self._cached_ast_nodes: imgui.table_next_column()
imgui.text("No AST nodes found or error fetching outline.")
else:
for node in self._cached_ast_nodes:
indent = node['indent']
kind = node['kind']
name = node['name']
full_path = node['full_path']
imgui.dummy(imgui.ImVec2(indent * 10, 0)) #region: LEFT COLUMN (Tree) ---
imgui.same_line() if imgui.begin_child("ast_tree_scroll", imgui.ImVec2(0, 600), True):
imgui.text(f"[{kind}] {name}") if not self._cached_ast_nodes:
imgui.same_line(imgui.get_window_width() - 200) imgui.text("No AST nodes found or error fetching outline.")
else:
for node in self._cached_ast_nodes:
indent = node['indent']
kind = node['kind']
name = node['name']
full_path = node['full_path']
current_mode = f_item.ast_mask.get(full_path, 'hide') imgui.dummy(imgui.ImVec2(indent * 10, 0))
imgui.same_line()
imgui.text(f"[{kind}] {name}")
imgui.same_line(imgui.get_window_width() - 200)
imgui.push_id(full_path) current_mode = f_item.ast_mask.get(full_path, 'hide')
if imgui.radio_button("Def", current_mode == 'def'):
f_item.ast_mask[full_path] = 'def'
imgui.same_line()
if imgui.radio_button("Sig", current_mode == 'sig'):
f_item.ast_mask[full_path] = 'sig'
imgui.same_line()
if imgui.radio_button("Hide", current_mode == 'hide'):
f_item.ast_mask[full_path] = 'hide'
imgui.pop_id()
imgui.end_child()
imgui.table_next_column() imgui.push_id(full_path)
if imgui.radio_button("Def", current_mode == 'def'):
f_item.ast_mask[full_path] = 'def'
imgui.same_line()
if imgui.radio_button("Sig", current_mode == 'sig'):
f_item.ast_mask[full_path] = 'sig'
imgui.same_line()
if imgui.radio_button("Hide", current_mode == 'hide'):
f_item.ast_mask[full_path] = 'hide'
imgui.pop_id()
imgui.end_child()
#endregion: LEFT COLUMN (Tree)
# --- RIGHT COLUMN (Content) --- imgui.table_next_column()
imgui.begin_child("ast_content_scroll", imgui.ImVec2(0, 600), True)
if not hasattr(self, '_cached_ast_file_lines') or not self._cached_ast_file_lines:
imgui.text("No file content loaded.")
else:
draw_list = imgui.get_window_draw_list()
for i, line_text in enumerate(self._cached_ast_file_lines):
line_num = i + 1
# Prioritize the most specific node (deepest indent) that covers the line #region: RIGHT COLUMN (Content) ---
deepest_node = None if imgui.begin_child("ast_content_scroll", imgui.ImVec2(0, 600), True):
for node in self._cached_ast_nodes: if not hasattr(self, '_cached_ast_file_lines') or not self._cached_ast_file_lines:
if node['start_line'] <= line_num <= node['end_line']: imgui.text("No file content loaded.")
if deepest_node is None or node['indent'] > deepest_node['indent']: else:
deepest_node = node draw_list = imgui.get_window_draw_list()
for i, line_text in enumerate(self._cached_ast_file_lines):
line_num = i + 1
mode = 'hide' # Prioritize the most specific node (deepest indent) that covers the line
if deepest_node: deepest_node = None
mode = f_item.ast_mask.get(deepest_node['full_path'], 'hide') for node in self._cached_ast_nodes:
if node['start_line'] <= line_num <= node['end_line']:
if deepest_node is None or node['indent'] > deepest_node['indent']:
deepest_node = node
pos = imgui.get_cursor_screen_pos() mode = 'hide'
line_height = imgui.get_text_line_height() if deepest_node:
mode = f_item.ast_mask.get(deepest_node['full_path'], 'hide')
if mode == 'def': pos = imgui.get_cursor_screen_pos()
# Green, alpha 0.2 line_height = imgui.get_text_line_height()
draw_list.add_rect_filled(pos, imgui.ImVec2(pos.x + imgui.get_content_region_avail().x, pos.y + line_height), imgui.get_color_u32(vec4(0, 255, 0, 0.2)))
elif mode == 'sig':
# Blue, alpha 0.2
draw_list.add_rect_filled(pos, imgui.ImVec2(pos.x + imgui.get_content_region_avail().x, pos.y + line_height), imgui.get_color_u32(vec4(0, 0, 255, 0.2)))
imgui.text(f"{line_num:4} | {line_text}") if mode == 'def':
imgui.end_child() # Green, alpha 0.2
imgui.end_table() draw_list.add_rect_filled(pos, imgui.ImVec2(pos.x + imgui.get_content_region_avail().x, pos.y + line_height), imgui.get_color_u32(vec4(0, 255, 0, 0.2)))
elif mode == 'sig':
# Blue, alpha 0.2
draw_list.add_rect_filled(pos, imgui.ImVec2(pos.x + imgui.get_content_region_avail().x, pos.y + line_height), imgui.get_color_u32(vec4(0, 0, 255, 0.2)))
imgui.separator() imgui.text(f"{line_num:4} | {line_text}")
if imgui.button("Close", imgui.ImVec2(120, 0)): imgui.end_child()
#endregion: RIGHT COLUMN (Content) ---
imgui.end_table()
#endregion: ast_dual_pane
imgui.separator()
if imgui.button("Close", imgui.ImVec2(120, 0)):
self.ui_inspecting_ast_file = None
imgui.close_current_popup()
imgui.end_popup()
#endregion: AST Inspector
if not opened:
self.ui_inspecting_ast_file = None self.ui_inspecting_ast_file = None
imgui.close_current_popup()
imgui.end_popup()
def _render_save_workspace_profile_modal(self) -> None: def _render_save_workspace_profile_modal(self) -> None:
if self._show_save_workspace_profile_modal: if self._show_save_workspace_profile_modal:
@@ -1929,26 +1941,25 @@ class App:
def _render_add_context_files_modal(self) -> None: def _render_add_context_files_modal(self) -> None:
if imgui.begin_popup_modal("Select Context Files", None, imgui.WindowFlags_.always_auto_resize)[0]: if imgui.begin_popup_modal("Select Context Files", None, imgui.WindowFlags_.always_auto_resize)[0]:
imgui.text("Select files from project to add to context:") imgui.text("Select files from project to add to context:")
imgui.begin_child("ctx_picker_list", imgui.ImVec2(600, 300), True) if imgui.begin_child("ctx_picker_list", imgui.ImVec2(600, 300), True):
from src import models
# Create a temporary selection set if not initialized
if not hasattr(self, '_ui_picker_selected'):
self._ui_picker_selected = set()
from src import models for f in self.files:
# Create a temporary selection set if not initialized fpath = f.path if hasattr(f, 'path') else str(f)
if not hasattr(self, '_ui_picker_selected'): # Skip if already in context
self._ui_picker_selected = set() if any((cf.path if hasattr(cf, 'path') else str(cf)) == fpath for cf in self.context_files):
continue
for f in self.files: is_sel = fpath in self._ui_picker_selected
fpath = f.path if hasattr(f, 'path') else str(f) clicked, new_sel = imgui.checkbox(f"{fpath}##picker_{fpath}", is_sel)
# Skip if already in context if clicked:
if any((cf.path if hasattr(cf, 'path') else str(cf)) == fpath for cf in self.context_files): if new_sel:
continue self._ui_picker_selected.add(fpath)
is_sel = fpath in self._ui_picker_selected else:
clicked, new_sel = imgui.checkbox(f"{fpath}##picker_{fpath}", is_sel) self._ui_picker_selected.discard(fpath)
if clicked: imgui.end_child()
if new_sel:
self._ui_picker_selected.add(fpath)
else:
self._ui_picker_selected.discard(fpath)
imgui.end_child()
imgui.separator() imgui.separator()
if imgui.button("Add Selected", imgui.ImVec2(120, 0)): if imgui.button("Add Selected", imgui.ImVec2(120, 0)):
@@ -3021,11 +3032,10 @@ class App:
finally: finally:
self._file_stats_worker_active = False self._file_stats_worker_active = False
import threading
threading.Thread(target=_stats_worker, daemon=True).start() threading.Thread(target=_stats_worker, daemon=True).start()
#region: Batch Action Bar imgui.text("Batch:") #region: Batch Action Bar imgui.text("Batch:")
imgui.same_line() # imgui.same_line()
for mode in ["full", "summary", "skeleton", "outline", "masked", "none"]: for mode in ["full", "summary", "skeleton", "outline", "masked", "none"]:
if imgui.button(f"{mode.capitalize()}##batch"): if imgui.button(f"{mode.capitalize()}##batch"):
for f in self.context_files: for f in self.context_files:
@@ -3180,6 +3190,7 @@ class App:
imgui.same_line() imgui.same_line()
imgui.text_colored(imgui.ImVec4(1.0, 0.5, 0.0, 1.0), "[Slices Active]") imgui.text_colored(imgui.ImVec4(1.0, 0.5, 0.0, 1.0), "[Slices Active]")
imgui.tree_pop() imgui.tree_pop()
imgui.end_table() imgui.end_table()
# Context Composition collasping header # Context Composition collasping header