Kit Manager: split available kits by dependency compatibility

Renamed "Kits to be installed" to "Kits available on the computer"
for kits whose dependencies are all in the app. Kits with unmet
dependencies go into a greyed-out "Other kits on the computer" section
that cannot be selected or ticked.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-09-09 08:20:09 +03:00
co-authored by Claude Opus 4.6
parent 4591353453
commit 61888396a5
2 changed files with 40 additions and 5 deletions
+39 -4
View File
@@ -21,12 +21,14 @@ from tkinter import messagebox, ttk
import app_state
import palette
import sax_file
import schema
NOT_DECLARED = "—" # em dash, for a column with nothing to report
NO_CHECKSUM = "(no checksum)"
REMOVE_ACTION = "REMOVE from app"
SECTION_TAG = "section"
UNAVAILABLE_TAG = "unavailable"
CHECKBOX_SIZE = 13
@@ -128,10 +130,17 @@ def collect_rows():
required = sax_file.required_kit_names()
installed = palette.list_kits()
# A kit the schema declares but Sedona home does not hold still gets a row: it is the
# clearest place to see that the file points at something missing.
others = [name for name in installed if name not in declared_names]
suitable = []
unsuitable = []
for name in others:
deps = schema.read_kit_dependencies(name)
if all(d in declared_names for d in deps):
suitable.append(name)
else:
unsuitable.append(name)
groups = [
("Installed kits", [
(name, checksum) for name, checksum in declared if name in required
@@ -139,7 +148,7 @@ def collect_rows():
("Installed but not used kits", [
(name, checksum) for name, checksum in declared if name not in required
]),
("Kits to be installed", [(name, None) for name in others]),
("Kits available on the computer", [(name, None) for name in suitable]),
]
rows = []
@@ -173,9 +182,30 @@ def collect_rows():
"latest_text": column_label(*latest) if latest else NOT_DECLARED,
"options": options,
"choice": 0,
# The tick reflects the file as it stands: declared kits start ticked.
"checked": is_declared,
"unavailable": False,
})
if unsuitable:
rows.append({"section": "Other kits on the computer (dependencies not in app)"})
for name in unsuitable:
builds = palette.kit_builds(name)
latest = builds[0] if builds else None
rows.append({
"kit": name,
"declared": False,
"required": False,
"checksum": None,
"builds": builds,
"latest": latest,
"installed_text": NOT_DECLARED,
"latest_text": column_label(*latest) if latest else NOT_DECLARED,
"options": [("Not available", None)],
"choice": 0,
"checked": False,
"unavailable": True,
})
return rows
@@ -239,6 +269,7 @@ class KitsPanel:
self.table.pack(fill=tk.BOTH, expand=True)
self.table.tag_configure(SECTION_TAG, background="#dcdcdc")
self.table.tag_configure(UNAVAILABLE_TAG, foreground="#999999")
self.boxes = {
(True, True): make_checkbox_image(True, True),
@@ -315,8 +346,10 @@ class KitsPanel:
"", "end", values=(row["section"], "", "", ""), tags=(SECTION_TAG,),
)
continue
tags = (UNAVAILABLE_TAG,) if row.get("unavailable") else ()
item = self.table.insert(
"", "end", image=self._row_image(row), values=self._row_values(row),
tags=tags,
)
self.row_by_item[item] = row
@@ -378,6 +411,8 @@ class KitsPanel:
item = self.table.identify_row(event.y)
if item not in self.row_by_item:
return
if self.row_by_item[item].get("unavailable"):
return
column = self.table.identify_column(event.x)
if column == "#0":