Implement BOM bubbles

This commit is contained in:
Daniel Rojas 2021-10-25 20:04:24 +02:00 committed by KV
parent df1e972b17
commit b15658b926
4 changed files with 66 additions and 18 deletions

View File

@ -364,12 +364,12 @@ def parse(
# mate two connectors as a whole # mate two connectors as a whole
harness.add_mate_component(from_name, to_name, designator) harness.add_mate_component(from_name, to_name, designator)
# harness population completed =============================================
if "additional_bom_items" in yaml_data: if "additional_bom_items" in yaml_data:
for line in yaml_data["additional_bom_items"]: for line in yaml_data["additional_bom_items"]:
harness.add_additional_bom_item(line) harness.add_additional_bom_item(line)
# harness population completed =============================================
harness.populate_bom() harness.populate_bom()
if output_formats: if output_formats:

View File

@ -479,11 +479,14 @@ class WireClass:
id: str id: str
label: str label: str
color: MultiColor color: MultiColor
# ...
bom_id: Optional[str] = None # to be filled after harness is built
# inheritable from parent cable # inheritable from parent cable
type: Union[MultilineHypertext, List[MultilineHypertext]] = None type: Union[MultilineHypertext, List[MultilineHypertext]] = None
subtype: Union[MultilineHypertext, List[MultilineHypertext]] = None subtype: Union[MultilineHypertext, List[MultilineHypertext]] = None
gauge: Optional[NumberAndUnit] = None gauge: Optional[NumberAndUnit] = None
length: Optional[NumberAndUnit] = None length: Optional[NumberAndUnit] = None
ignore_in_bom: Optional[bool] = False
sum_amounts_in_bom: bool = True sum_amounts_in_bom: bool = True
partnumbers: PartNumberInfo = None partnumbers: PartNumberInfo = None
@ -700,6 +703,7 @@ class Cable(TopLevelGraphicalComponent):
gauge=self.gauge, gauge=self.gauge,
length=self.length, length=self.length,
sum_amounts_in_bom=self.sum_amounts_in_bom, sum_amounts_in_bom=self.sum_amounts_in_bom,
ignore_in_bom=self.ignore_in_bom
# TODO partnumbers # TODO partnumbers
) )

View File

@ -44,6 +44,7 @@ def gv_node_component(component: Component) -> Table:
if isinstance(component, Connector): if isinstance(component, Connector):
line_info = [ line_info = [
bom_bubble(component.bom_id),
html_line_breaks(component.type), html_line_breaks(component.type),
html_line_breaks(component.subtype), html_line_breaks(component.subtype),
f"{component.pincount}-pin" if component.show_pincount else None, f"{component.pincount}-pin" if component.show_pincount else None,
@ -52,6 +53,7 @@ def gv_node_component(component: Component) -> Table:
] ]
elif isinstance(component, Cable): elif isinstance(component, Cable):
line_info = [ line_info = [
bom_bubble(component.bom_id) if component.category != "bundle" else None,
html_line_breaks(component.type), html_line_breaks(component.type),
f"{component.wirecount}x" if component.show_wirecount else None, f"{component.wirecount}x" if component.show_wirecount else None,
component.gauge_str_with_equiv, component.gauge_str_with_equiv,
@ -135,6 +137,15 @@ def calculate_node_bgcolor(component, harness_options):
return harness_options.bgcolor_cable.html return harness_options.bgcolor_cable.html
def bom_bubble(id) -> Table:
if id is None:
return None
else:
return Table(
Tr(Td(f" {id} ", border=0, cellpadding=0)), border=1, style="rounded"
)
def make_list_of_cells(inp) -> List[Td]: def make_list_of_cells(inp) -> List[Td]:
# inp may be List, # inp may be List,
if isinstance(inp, List): if isinstance(inp, List):
@ -252,14 +263,17 @@ def gv_conductor_table(cable) -> Table:
outs.append(str(conn.to)) outs.append(str(conn.to))
cells_above = [ cells_above = [
Td(", ".join(ins), align="left"), Td(" " + ", ".join(ins), align="left"),
# Td(":-)"),
Td(bom_bubble(wire.bom_id)) if cable.category == "bundle" else None,
Td(":".join([wi for wi in wireinfo if wi is not None and wi != ""])), Td(":".join([wi for wi in wireinfo if wi is not None and wi != ""])),
Td(", ".join(outs), align="right"), Td(", ".join(outs) + " ", align="right"),
] ]
cells_above = [cell for cell in cells_above if cell is not None]
rows.append(Tr(cells_above)) rows.append(Tr(cells_above))
# the wire itself # the wire itself
rows.append(Tr(gv_wire_cell(wire))) rows.append(Tr(gv_wire_cell(wire, len(cells_above))))
# row below the wire # row below the wire
# TODO: PN stuff for bundles # TODO: PN stuff for bundles
@ -270,7 +284,7 @@ def gv_conductor_table(cable) -> Table:
return tbl return tbl
def gv_wire_cell(wire: Union[WireClass, ShieldClass]) -> Td: def gv_wire_cell(wire: Union[WireClass, ShieldClass], colspan: int) -> Td:
if wire.color: if wire.color:
color_list = ["#000000"] + wire.color.html_padded_list + ["#000000"] color_list = ["#000000"] + wire.color.html_padded_list + ["#000000"]
else: else:
@ -282,7 +296,7 @@ def gv_wire_cell(wire: Union[WireClass, ShieldClass]) -> Td:
"bgcolor": bgcolor if bgcolor != "" else "#000000", "bgcolor": bgcolor if bgcolor != "" else "#000000",
"border": 0, "border": 0,
"cellpadding": 0, "cellpadding": 0,
"colspan": 3, "colspan": colspan,
"height": 2, "height": 2,
} }
wire_inner_rows.append(Tr(Td("", **wire_inner_cell_attribs))) wire_inner_rows.append(Tr(Td("", **wire_inner_cell_attribs)))
@ -291,7 +305,7 @@ def gv_wire_cell(wire: Union[WireClass, ShieldClass]) -> Td:
"border": 0, "border": 0,
"cellspacing": 0, "cellspacing": 0,
"cellpadding": 0, "cellpadding": 0,
"colspan": 3, "colspan": colspan,
"height": 2 * len(color_list), "height": 2 * len(color_list),
"port": f"w{wire.index+1}", "port": f"w{wire.index+1}",
} }

View File

@ -8,7 +8,7 @@ from typing import List
from graphviz import Graph from graphviz import Graph
import wireviz.wv_colors import wireviz.wv_colors
from wireviz.wv_bom import BomEntry, print_bom_debug, BomCategory from wireviz.wv_bom import BomCategory, BomEntry, print_bom_debug
from wireviz.wv_dataclasses import ( from wireviz.wv_dataclasses import (
AUTOGENERATED_PREFIX, AUTOGENERATED_PREFIX,
AdditionalComponent, AdditionalComponent,
@ -83,24 +83,54 @@ class Harness:
self.mates.append(MateComponent(from_name, to_name, arrow)) self.mates.append(MateComponent(from_name, to_name, arrow))
def populate_bom(self): def populate_bom(self):
for item in self.connectors.values(): # helper lists
self._add_to_internal_bom(item) all_toplevel_items = (
for item in self.cables.values(): list(self.connectors.values())
self._add_to_internal_bom(item) + list(self.cables.values())
for item in self.additional_bom_items: + self.additional_bom_items
self._add_to_internal_bom(item) )
all_subitems = [
subitem
for item in all_toplevel_items
for subitem in item.additional_components
]
all_bom_relevant_items = (
list(self.connectors.values())
+ [cable for cable in self.cables.values() if cable.category != "bundle"]
+ [
wire
for cable in self.cables.values()
if cable.category == "bundle"
for wire in cable.wire_objects.values()
]
+ all_subitems
)
# add items to BOM
for item in all_toplevel_items:
self._add_to_internal_bom(item) # nested subitems are also handled
# sort BOM by category first, then alphabetically by description within category # sort BOM by category first, then alphabetically by description within category
self.bom = dict( self.bom = dict(
sorted( sorted(
self.bom.items(), self.bom.items(),
key=lambda x: (x[1]["category"], x[0].description) key=lambda x: (
x[1]["category"],
x[0].description,
), # x[0] = key, x[1] = value
) )
) )
# assign BOM IDs # assign BOM IDs
for id, key in enumerate(self.bom.keys(), 1): for id, key in enumerate(self.bom.keys(), 1):
self.bom[key]["id"] = id self.bom[key]["id"] = id
# set BOM IDs within components (for BOM bubbles)
for item in all_bom_relevant_items:
if item.ignore_in_bom:
continue
if not item.bom_hash in self.bom:
print(f"{item}'s hash' not found in BOM dict.")
continue
item.bom_id = self.bom[item.bom_hash]["id"]
# import pudb; pudb.set_trace()
print_bom_debug(self.bom) print_bom_debug(self.bom)