-
Notifications
You must be signed in to change notification settings - Fork 226
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature/gv html refactor #136
Changes from all commits
79e751d
2639c77
43f85ae
102c7d6
af196df
94faec5
e3fb39f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -86,44 +86,47 @@ def create_graph(self) -> Graph: | |
if connection_color.to_port is not None: # connect to right | ||
self.connectors[connection_color.to_name].ports_left = True | ||
|
||
for key, connector in self.connectors.items(): | ||
for connector in self.connectors.values(): | ||
|
||
html = [] | ||
|
||
rows = [[connector.name if connector.show_name else None], | ||
[f'P/N: {connector.pn}' if connector.pn else None, | ||
manufacturer_info_field(connector.manufacturer, connector.mpn)], | ||
html_line_breaks(manufacturer_info_field(connector.manufacturer, connector.mpn))], | ||
[html_line_breaks(connector.type), | ||
html_line_breaks(connector.subtype), | ||
f'{connector.pincount}-pin' if connector.show_pincount else None, | ||
connector.color, '<!-- colorbar -->' if connector.color else None], | ||
'<!-- connector table -->' if connector.style != 'simple' else None, | ||
[html_line_breaks(connector.notes)]] | ||
html = nested_html_table(rows) | ||
html.extend(nested_html_table(rows)) | ||
|
||
if connector.color: # add color bar next to color info, if present | ||
colorbar = f' bgcolor="{wv_colors.translate_color(connector.color, "HEX")}" width="4"></td>' # leave out '<td' from string to preserve any existing attributes of the <td> tag | ||
html = html.replace('><!-- colorbar --></td>', colorbar) | ||
html = [row.replace('><!-- colorbar --></td>', colorbar) for row in html] | ||
|
||
if connector.style != 'simple': | ||
pinlist = [] | ||
pinhtml = [] | ||
pinhtml.append('<table border="0" cellspacing="0" cellpadding="3" cellborder="1">') | ||
|
||
for pin, pinlabel in zip(connector.pins, connector.pinlabels): | ||
if connector.hide_disconnected_pins and not connector.visible_pins.get(pin, False): | ||
continue | ||
pinlist.append([f'<td port="p{pin}l">{pin}</td>' if connector.ports_left else None, | ||
f'<td>{pinlabel}</td>' if pinlabel else '', | ||
f'<td port="p{pin}r">{pin}</td>' if connector.ports_right else None]) | ||
pinhtml.append(' <tr>') | ||
if connector.ports_left: | ||
pinhtml.append(f' <td port="p{pin}l">{pin}</td>') | ||
if pinlabel: | ||
pinhtml.append(f' <td>{pinlabel}</td>') | ||
if connector.ports_right: | ||
pinhtml.append(f' <td port="p{pin}r">{pin}</td>') | ||
pinhtml.append(' </tr>') | ||
|
||
pinhtml = '<table border="0" cellspacing="0" cellpadding="3" cellborder="1">' | ||
for i, pin in enumerate(pinlist): | ||
pinhtml = f'{pinhtml}<tr>' | ||
for column in pin: | ||
if column is not None: | ||
pinhtml = f'{pinhtml}{column}' | ||
pinhtml = f'{pinhtml}</tr>' | ||
pinhtml = f'{pinhtml}</table>' | ||
html = html.replace('<!-- connector table -->', pinhtml) | ||
pinhtml.append(' </table>') | ||
|
||
html = [row.replace('<!-- connector table -->', '\n'.join(pinhtml)) for row in html] | ||
|
||
dot.node(key, label=f'<{html}>', shape='none', margin='0', style='filled', fillcolor='white') | ||
html = '\n'.join(html) | ||
dot.node(connector.name, label=f'<\n{html}\n>', shape='none', margin='0', style='filled', fillcolor='white') | ||
|
||
if len(connector.loops) > 0: | ||
dot.attr('edge', color='#000000:#ffffff:#000000') | ||
|
@@ -139,11 +142,14 @@ def create_graph(self) -> Graph: | |
dot.edge(f'{connector.name}:p{loop[0]}{loop_side}:{loop_dir}', | ||
f'{connector.name}:p{loop[1]}{loop_side}:{loop_dir}') | ||
|
||
|
||
# determine if there are double- or triple-colored wires in the harness; | ||
# if so, pad single-color wires to make all wires of equal thickness | ||
pad = any(len(colorstr) > 2 for cable in self.cables.values() for colorstr in cable.colors) | ||
|
||
for _, cable in self.cables.items(): | ||
for cable in self.cables.values(): | ||
|
||
html = [] | ||
|
||
formatc1702 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
awg_fmt = '' | ||
if cable.show_equiv: | ||
|
@@ -155,99 +161,84 @@ def create_graph(self) -> Graph: | |
elif cable.gauge_unit.upper() == 'AWG': | ||
awg_fmt = f' ({mm2_equiv(cable.gauge)} mm\u00B2)' | ||
|
||
identification = [f'P/N: {cable.pn}' if (cable.pn and not isinstance(cable.pn, list)) else '', | ||
manufacturer_info_field(cable.manufacturer if not isinstance(cable.manufacturer, list) else None, | ||
cable.mpn if not isinstance(cable.mpn, list) else None)] | ||
identification = list(filter(None, identification)) | ||
|
||
attributes = [html_line_breaks(cable.type) if cable.type else '', | ||
f'{len(cable.colors)}x' if cable.show_wirecount else '', | ||
f'{cable.gauge} {cable.gauge_unit}{awg_fmt}' if cable.gauge else '', | ||
'+ S' if cable.shield else '', | ||
f'{cable.length} m' if cable.length > 0 else ''] | ||
attributes = list(filter(None, attributes)) | ||
|
||
html = '<table border="0" cellspacing="0" cellpadding="0">' # main table | ||
|
||
if cable.show_name or len(attributes) > 0: | ||
html = f'{html}<tr><td><table border="0" cellspacing="0" cellpadding="3" cellborder="1">' # name+attributes table | ||
if cable.show_name: | ||
html = f'{html}<tr><td colspan="{max(len(attributes), 1)}">{cable.name}</td></tr>' | ||
if(len(identification) > 0): # print an identification row if values specified | ||
html = f'{html}<tr><td colspan="{len(attributes)}" cellpadding="0"><table border="0" cellspacing="0" cellpadding="3" cellborder="1"><tr>' | ||
for attrib in identification[0:-1]: | ||
html = f'{html}<td sides="R">{attrib}</td>' # all columns except last have a border on the right (sides="R") | ||
if len(identification) > 0: | ||
html = f'{html}<td border="0">{identification[-1]}</td>' # last column has no border on the right because the enclosing table borders it | ||
html = f'{html}</tr></table></td></tr>' # end identification row | ||
if(len(attributes) > 0): | ||
html = f'{html}<tr>' # attribute row | ||
for attrib in attributes: | ||
html = f'{html}<td balign="left">{attrib}</td>' | ||
html = f'{html}</tr>' # attribute row | ||
html = f'{html}</table></td></tr>' # name+attributes table | ||
|
||
html = f'{html}<tr><td> </td></tr>' # spacer between attributes and wires | ||
|
||
html = f'{html}<tr><td><table border="0" cellspacing="0" cellborder="0">' # conductor table | ||
rows = [[cable.name if cable.show_name else None], | ||
[f'P/N: {cable.pn}' if (cable.pn and not isinstance(cable.pn, list)) else None, | ||
html_line_breaks(manufacturer_info_field( | ||
cable.manufacturer if not isinstance(cable.manufacturer, list) else None, | ||
cable.mpn if not isinstance(cable.mpn, list) else None))], | ||
[html_line_breaks(cable.type), | ||
f'{cable.wirecount}x' if cable.show_wirecount else None, | ||
f'{cable.gauge} {cable.gauge_unit}{awg_fmt}' if cable.gauge else None, | ||
'+ S' if cable.shield else None, | ||
f'{cable.length} m' if cable.length > 0 else None, | ||
cable.color, '<!-- colorbar -->' if cable.color else None], | ||
'<!-- wire table -->', | ||
[html_line_breaks(cable.notes)]] | ||
html.extend(nested_html_table(rows)) | ||
formatc1702 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
if cable.color: # add color bar next to color info, if present | ||
colorbar = f' bgcolor="{wv_colors.translate_color(cable.color, "HEX")}" width="4"></td>' # leave out '<td' from string to preserve any existing attributes of the <td> tag | ||
html = [row.replace('><!-- colorbar --></td>', colorbar) for row in html] | ||
|
||
wirehtml = [] | ||
wirehtml.append('<table border="0" cellspacing="0" cellborder="0">') # conductor table | ||
wirehtml.append(' <tr><td> </td></tr>') | ||
|
||
for i, connection_color in enumerate(cable.colors, 1): | ||
p = [] | ||
p.append(f'<!-- {i}_in -->') | ||
p.append(wv_colors.translate_color(connection_color, self.color_mode)) | ||
p.append(f'<!-- {i}_out -->') | ||
html = f'{html}<tr>' | ||
for bla in p: | ||
html = f'{html}<td>{bla}</td>' | ||
html = f'{html}</tr>' | ||
wirehtml.append(' <tr>') | ||
wirehtml.append(f' <td><!-- {i}_in --></td>') | ||
wirehtml.append(f' <td>{wv_colors.translate_color(connection_color, self.color_mode)}</td>') | ||
wirehtml.append(f' <td><!-- {i}_out --></td>') | ||
wirehtml.append(' </tr>') | ||
|
||
bgcolors = ['#000000'] + get_color_hex(connection_color, pad=pad) + ['#000000'] | ||
html = f'{html}<tr><td colspan="{len(p)}" border="0" cellspacing="0" cellpadding="0" port="w{i}" height="{(2 * len(bgcolors))}"><table cellspacing="0" cellborder="0" border = "0">' | ||
wirehtml.append(f' <tr>') | ||
wirehtml.append(f' <td colspan="3" border="0" cellspacing="0" cellpadding="0" port="w{i}" height="{(2 * len(bgcolors))}">') | ||
wirehtml.append(' <table cellspacing="0" cellborder="0" border="0">') | ||
for j, bgcolor in enumerate(bgcolors[::-1]): # Reverse to match the curved wires when more than 2 colors | ||
html = f'{html}<tr><td colspan="{len(p)}" cellpadding="0" height="2" bgcolor="{bgcolor if bgcolor != "" else wv_colors.default_color}" border="0"></td></tr>' | ||
html = html + '</table></td></tr>' | ||
wirehtml.append(f' <tr><td colspan="3" cellpadding="0" height="2" bgcolor="{bgcolor if bgcolor != "" else wv_colors.default_color}" border="0"></td></tr>') | ||
wirehtml.append(' </table>') | ||
wirehtml.append(' </td>') | ||
wirehtml.append(' </tr>') | ||
if(cable.category == 'bundle'): # for bundles individual wires can have part information | ||
# create a list of wire parameters | ||
wireidentification = [] | ||
if isinstance(cable.pn, list): | ||
wireidentification.append(f'P/N: {cable.pn[i - 1]}') | ||
manufacturer_info = manufacturer_info_field(cable.manufacturer[i - 1] if isinstance(cable.manufacturer, list) else None, | ||
cable.mpn[i - 1] if isinstance(cable.mpn, list) else None) | ||
manufacturer_info = manufacturer_info_field( | ||
cable.manufacturer[i - 1] if isinstance(cable.manufacturer, list) else None, | ||
cable.mpn[i - 1] if isinstance(cable.mpn, list) else None) | ||
if manufacturer_info: | ||
wireidentification.append(manufacturer_info) | ||
wireidentification.append(html_line_breaks(manufacturer_info)) | ||
# print parameters into a table row under the wire | ||
if(len(wireidentification) > 0): | ||
html = f'{html}<tr><td colspan="{len(p)}"><table border="0" cellspacing="0" cellborder="0"><tr>' | ||
wirehtml.append(' <tr><td colspan="3">') | ||
wirehtml.append(' <table border="0" cellspacing="0" cellborder="0"><tr>') | ||
for attrib in wireidentification: | ||
html = f'{html}<td>{attrib}</td>' | ||
html = f'{html}</tr></table></td></tr>' | ||
wirehtml.append(f' <td>{attrib}</td>') | ||
wirehtml.append(' </tr></table>') | ||
wirehtml.append(' </td></tr>') | ||
|
||
if cable.shield: | ||
p = ['<!-- s_in -->', 'Shield', '<!-- s_out -->'] | ||
html = f'{html}<tr><td> </td></tr>' # spacer | ||
html = f'{html}<tr>' | ||
for bla in p: | ||
html = html + f'<td>{bla}</td>' | ||
html = f'{html}</tr>' | ||
wirehtml.append(' <tr><td> </td></tr>') # spacer | ||
wirehtml.append(' <tr>') | ||
wirehtml.append(' <td><!-- s_in --></td>') | ||
wirehtml.append(' <td>Shield</td>') | ||
wirehtml.append(' <td><!-- s_out --></td>') | ||
wirehtml.append(' </tr>') | ||
if isinstance(cable.shield, str): | ||
# shield is shown with specified color and black borders | ||
shield_color_hex = wv_colors.get_color_hex(cable.shield)[0] | ||
attributes = f'height="6" bgcolor="{shield_color_hex}" border="2" sides="tb"' | ||
else: | ||
# shield is shown as a thin black wire | ||
attributes = f'height="2" bgcolor="#000000" border="0"' | ||
html = f'{html}<tr><td colspan="{len(p)}" cellpadding="0" {attributes} port="ws"></td></tr>' | ||
|
||
html = f'{html}<tr><td> </td></tr>' # spacer at the end | ||
|
||
html = f'{html}</table>' # conductor table | ||
wirehtml.append(f' <tr><td colspan="3" cellpadding="0" {attributes} port="ws"></td></tr>') | ||
|
||
html = f'{html}</td></tr>' # main table | ||
if cable.notes: | ||
html = f'{html}<tr><td cellpadding="3" balign="left">{html_line_breaks(cable.notes)}</td></tr>' # notes table | ||
html = f'{html}<tr><td> </td></tr>' # spacer at the end | ||
wirehtml.append(' <tr><td> </td></tr>') | ||
wirehtml.append(' </table>') | ||
|
||
html = f'{html}</table>' # main table | ||
html = [row.replace('<!-- wire table -->', '\n'.join(wirehtml)) for row in html] | ||
|
||
# connections | ||
for connection_color in cable.connections: | ||
|
@@ -262,16 +253,17 @@ def create_graph(self) -> Graph: | |
code_left_2 = f'{cable.name}:w{connection_color.via_port}:w' | ||
dot.edge(code_left_1, code_left_2) | ||
from_string = f'{connection_color.from_name}:{connection_color.from_port}' if self.connectors[connection_color.from_name].show_name else '' | ||
html = html.replace(f'<!-- {connection_color.via_port}_in -->', from_string) | ||
html = [row.replace(f'<!-- {connection_color.via_port}_in -->', from_string) for row in html] | ||
if connection_color.to_port is not None: # connect to right | ||
code_right_1 = f'{cable.name}:w{connection_color.via_port}:e' | ||
to_port = f':p{connection_color.to_port}l' if self.connectors[connection_color.to_name].style != 'simple' else '' | ||
code_right_2 = f'{connection_color.to_name}{to_port}:w' | ||
dot.edge(code_right_1, code_right_2) | ||
to_string = f'{connection_color.to_name}:{connection_color.to_port}' if self.connectors[connection_color.to_name].show_name else '' | ||
html = html.replace(f'<!-- {connection_color.via_port}_out -->', to_string) | ||
html = [row.replace(f'<!-- {connection_color.via_port}_out -->', to_string) for row in html] | ||
|
||
dot.node(cable.name, label=f'<{html}>', shape='box', | ||
html = '\n'.join(html) | ||
dot.node(cable.name, label=f'<\n{html}\n>', shape='box', | ||
Comment on lines
+265
to
+266
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In this case I will leave it as is, since the |
||
style='filled,dashed' if cable.category == 'bundle' else '', margin='0', fillcolor='white') | ||
|
||
return dot | ||
|
@@ -355,7 +347,7 @@ def bom(self): | |
conn_color = f', {shared.color}' if shared.color else '' | ||
name = f'Connector{conn_type}{conn_subtype}{conn_pincount}{conn_color}' | ||
item = {'item': name, 'qty': len(designators), 'unit': '', 'designators': designators if shared.show_name else '', | ||
'manufacturer': shared.manufacturer, 'mpn': shared.mpn, 'pn': shared.pn} | ||
'manufacturer': remove_line_breaks(shared.manufacturer), 'mpn': remove_line_breaks(shared.mpn), 'pn': shared.pn} | ||
bom_connectors.append(item) | ||
bom_connectors = sorted(bom_connectors, key=lambda k: k['item']) # https://stackoverflow.com/a/73050 | ||
bom.extend(bom_connectors) | ||
|
@@ -374,7 +366,7 @@ def bom(self): | |
shield_name = ' shielded' if shared.shield else '' | ||
name = f'Cable{cable_type}, {shared.wirecount}{gauge_name}{shield_name}' | ||
item = {'item': name, 'qty': round(total_length, 3), 'unit': 'm', 'designators': designators, | ||
'manufacturer': shared.manufacturer, 'mpn': shared.mpn, 'pn': shared.pn} | ||
'manufacturer': remove_line_breaks(shared.manufacturer), 'mpn': remove_line_breaks(shared.mpn), 'pn': shared.pn} | ||
bom_cables.append(item) | ||
# bundles (ignores wirecount) | ||
wirelist = [] | ||
|
@@ -384,8 +376,8 @@ def bom(self): | |
# add each wire from each bundle to the wirelist | ||
for index, color in enumerate(bundle.colors, 0): | ||
wirelist.append({'type': bundle.type, 'gauge': bundle.gauge, 'gauge_unit': bundle.gauge_unit, 'length': bundle.length, 'color': color, 'designator': bundle.name, | ||
'manufacturer': index_if_list(bundle.manufacturer, index), | ||
'mpn': index_if_list(bundle.mpn, index), | ||
'manufacturer': remove_line_breaks(index_if_list(bundle.manufacturer, index)), | ||
'mpn': remove_line_breaks(index_if_list(bundle.mpn, index)), | ||
'pn': index_if_list(bundle.pn, index)}) | ||
# join similar wires from all the bundles to a single BOM item | ||
wire_group = lambda w: (w.get('type', None), w['gauge'], w['gauge_unit'], w['color'], w['manufacturer'], w['mpn'], w['pn']) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider
html = nested_html_table(rows)
instead, or is there a good reason behind extending an empty list?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this case I find it more understandable to start with an empty list (line 91) and then populate it slowly... a matter of style, nothing else.