From 66f11763fc079358d062835894303caa7ee1157d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20L=C3=B3pez=20Barr=C3=B3n?= Date: Sun, 8 Dec 2024 20:50:36 +1100 Subject: [PATCH] small update to test graph and word fix when pydot is not present MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian López Barrón --- grill/views/_graph.py | 14 ++- tests/test_data/_mini_graph.dot | 26 +++--- tests/test_data/_mini_graph.svg | 160 ++++++++++++++++++-------------- tests/test_views.py | 54 ++++++----- 4 files changed, 149 insertions(+), 105 deletions(-) diff --git a/grill/views/_graph.py b/grill/views/_graph.py index b40a6529..4311f913 100644 --- a/grill/views/_graph.py +++ b/grill/views/_graph.py @@ -44,12 +44,14 @@ _NO_PEN = QtGui.QPen(QtCore.Qt.NoPen) -_DOT_ENVIRONMENT_ERROR = """In order to display composition arcs in a graph, +_DOT_ENVIRONMENT_ERROR = """In order to display content in this graph view, the 'dot' command must be available on the current environment. Please make sure graphviz is installed and 'dot' available on the system's PATH environment variable. -For more details on installing graphviz, visit https://graphviz.org/download/ or https://grill.readthedocs.io/en/latest/install.html#conda-environment-example +For more details on installing graphviz, visit: + - https://graphviz.org/download/ or + - https://grill.readthedocs.io/en/latest/install.html#conda-environment-example """ @@ -591,21 +593,24 @@ def _load_graph(self, graph): self.scene().clear() self.viewport().update() + _default_text_interaction = QtCore.Qt.LinksAccessibleByMouse if _IS_QT5 else QtCore.Qt.TextBrowserInteraction + if not _core._which("dot"): # dot has not been installed print(_DOT_ENVIRONMENT_ERROR) text_item = QtWidgets.QGraphicsTextItem() text_item.setPlainText(_DOT_ENVIRONMENT_ERROR) - text_item.setTextInteractionFlags(QtCore.Qt.LinksAccessibleByMouse if _IS_QT5 else QtCore.Qt.TextBrowserInteraction) + text_item.setTextInteractionFlags(_default_text_interaction) self.scene().addItem(text_item) return try: # exit early if pydot is not installed, needed for positions positions = drawing.nx_pydot.graphviz_layout(graph, prog='dot') except ImportError as exc: - message = str(exc) + message = f"{exc}\n\n{_DOT_ENVIRONMENT_ERROR}" print(message) text_item = QtWidgets.QGraphicsTextItem() text_item.setPlainText(message) + text_item.setTextInteractionFlags(_default_text_interaction) self.scene().addItem(text_item) return @@ -752,6 +757,7 @@ def __init__(self, *args, **kwargs): layout.addWidget(self._error_view) layout.setContentsMargins(0, 0, 0, 0) self._error_view.setVisible(False) + self._error_view.setLineWrapMode(QtWidgets.QTextBrowser.NoWrap) self.setLayout(layout) self._dot2svg = None self._threadpool = QtCore.QThreadPool() diff --git a/tests/test_data/_mini_graph.dot b/tests/test_data/_mini_graph.dot index 4ee61255..eee049be 100644 --- a/tests/test_data/_mini_graph.dot +++ b/tests/test_data/_mini_graph.dot @@ -1,17 +1,21 @@ digraph { rankdir=LR; edge [color=crimson]; -1 [label="{<0>x:y:z|<1>z}", style="rounded,filled", shape=record]; -2 [label="{<0>a|<1>b}", style="rounded,filled", shape=record]; -3 [label="{<0>c|<1>d}", style="rounded,filled", shape=record]; -4 [label="{<0>k}", style=invis]; -ancestor [active_plugs="{'surface', 'cycle_out', 'cycle_in', 'roughness'}", shape=none, connections="{'surface': [('successor', 'surface')], 'cycle_out': [('ancestor', 'cycle_in')]}", label=<
ancestor
cycle_in
roughness
cycle_out
surface
>]; -successor [active_plugs="{'surface'}", shape=none, connections="{}", label=<
successor
surface
>]; +1 [label="{x:y:z|z}", style=rounded, shape=record]; +2 [label="{a|b}", style=rounded, shape=record]; +3 [label="{c|d}", style=rounded, shape=record]; +parent [shape=box, fillcolor="#afd7ff", color="#1E90FF", style="filled,rounded"]; +child1 [shape=box, fillcolor="#afd7ff", color="#1E90FF", style="filled,rounded"]; +child2 [shape=box, fillcolor="#afd7ff", color="#1E90FF", style=invis]; +ancestor [shape=none, label=<
ancestor
cycle_in
roughness
cycle_out
surface
>]; +successor [shape=none, label=<
successor
surface
>]; 1 -> 1 [key=0, color="sienna:crimson:orange"]; 1 -> 2 [key=0, color=crimson]; -2 -> 1 [key=0, color=green]; -2 -> 4 [key=0, color=yellow, label="edge_label"]; -3 -> 2 [key=0, color=blue, tailport=0]; -ancestor -> ancestor [key=0, tailport="cycle_in", headport="cycle_out", tooltip="ancestor.cycle_in -> ancestor.cycle_out"]; -successor -> ancestor [key=0, tailport=surface, headport=surface, tooltip="successor.surface -> ancestor.surface"]; +2 -> 1 [key=0, color=seagreen]; +3 -> 2 [key=0, color=steelblue, tailport=five]; +3 -> 1 [key=0, color=hotpink, tailport=five]; +parent -> child1 [key=0]; +parent -> child2 [key=0, label=invis]; +ancestor -> ancestor [key=0, tailport="cycle_out", headport="cycle_in", tooltip="ancestor.cycle_out -> ancestor.cycle_in"]; +ancestor -> successor [key=0, tailport=surface, headport=surface, tooltip="ancestor.surface -> successor.surface"]; } diff --git a/tests/test_data/_mini_graph.svg b/tests/test_data/_mini_graph.svg index 266b65be..c94b0774 100644 --- a/tests/test_data/_mini_graph.svg +++ b/tests/test_data/_mini_graph.svg @@ -4,109 +4,133 @@ - - - + + + 1 - -x:y:z - -z + +x:y:z + +z 1->1 - - - - + + + + 2 - -a - -b + +a + +b 1->2 - - + + 2->1 - - - - - - -2->4 - - -edge_label + + 3 - -c - -d + +c + +d - + -3:0->2 - - +3:five->1 + + - + + +3:five->2 + + + + + +parent + +parent + + +child1 + +child1 + + + +parent->child1 + + + + + + +parent->child2 + + +invis + + + ancestor - - -ancestor - -cycle_in - -roughness - -cycle_out - -surface - + + +ancestor + +cycle_in + +roughness + +cycle_out + +surface + - -ancestor:cycle_in->ancestor:cycle_out - - - + +ancestor:cycle_out->ancestor:cycle_in + + + - + successor - - -successor - -surface - - - - -successor:surface->ancestor:surface - - - + + +successor + +surface + + + + +ancestor:surface->successor:surface + + + diff --git a/tests/test_views.py b/tests/test_views.py index 4f780f45..b53e7fe2 100644 --- a/tests/test_views.py +++ b/tests/test_views.py @@ -558,31 +558,38 @@ def test_graph_views(self): nodes_info = { 1: dict( - label="{<0>x:y:z|<1>z}", - style="rounded,filled", + label="{x:y:z|z}", + style="rounded", # these can be set at the graph level shape="record", ), 2: dict( - label="{<0>a|<1>b}", - style="rounded,filled", + label="{a|b}", + style='rounded', shape="record", ), 3: dict( - label="{<0>c|<1>d}", - style="rounded,filled", + label="{c|d}", + style='rounded', shape="record", ), - 4: dict( - label="{<0>k}", - style="invis", + "parent": dict( + shape="box", fillcolor="#afd7ff", color="#1E90FF", style="filled,rounded" + ), + "child1": dict( + shape="box", fillcolor="#afd7ff", color="#1E90FF", style="filled,rounded" + ), + "child2": dict( + shape="box", fillcolor="#afd7ff", color="#1E90FF", style="invis" ), } edges_info = ( (1, 1, dict(color='sienna:crimson:orange')), (1, 2, dict(color='crimson')), - (2, 1, dict(color='green')), - (3, 2, dict(color='blue', tailport='0')), - (2, 4, dict(color='yellow', label='edge_label')), + (2, 1, dict(color='seagreen')), + (3, 2, dict(color='steelblue', tailport='five')), + (3, 1, dict(color='hotpink', tailport='five')), + ("parent", "child1"), + ("parent", "child2", dict(label='invis')), ) graph = _graph.nx.MultiDiGraph() @@ -603,16 +610,14 @@ def test_graph_views(self): 'cycle_out': 3, 'surface': 4 }, - active_plugs={'cycle_in', 'cycle_out', 'roughness', 'surface'}, shape='none', connections=dict( surface=[('successor', 'surface')], cycle_out=[('ancestor', 'cycle_in')], - ) + ), ), successor=dict( plugs={'': 0, 'surface': 1}, - active_plugs={'surface'}, shape='none', connections=dict(), ) @@ -637,10 +642,13 @@ def _add_edges(src_node, src_name, tgt_node, tgt_name): # color = plug_colors[type(plug)] if isinstance(plug, UsdShade.Output) or sources else background_color label += table_row.format(port=plug_name, color=color, text=f'{plug_name}') for source_node, source_plug in sources: - _add_edges(source_node, source_plug, node, plug_name) + # node_id='ancestor', plug_name='cycle_out', ancestor, source.sourceName='cycle_in' + # tooltip='/TexModel/boardMat/PBRShader.cycle_in -> /TexModel/boardMat/PBRShader.cycle_out' + _add_edges(node, plug_name, source_node, source_plug) label += '>' data['label'] = label + data.pop('connections', None) graph.add_nodes_from(connection_nodes.items()) graph.add_edges_from(connection_edges) @@ -656,12 +664,14 @@ def _use_test_svg(self, filepath): def _test_positions(graph, prog): return { - 1: (40.0, 91.692), - 2: (157.37, 91.692), - 3: (40.0, 36.692), - 4: (332.85, 91.692), - 'ancestor': (157.37, 208.69), - 'successor': (40.0, 174.69), + 1: (218.75, 90.1), + 2: (322.75, 90.1), + 3: (76.125, 61.1), + 'parent': (76.125, 190.1), + 'child1': (218.75, 217.1), + 'child2': (218.75, 163.1), + 'ancestor': (76.125, 316.1), + 'successor': (218.75, 282.1), } with (