def test_partition_helpers(self): test_in_exp = { 'stuff.thing': 'stuff', 'all/other/stuff.another': 'all/other/stuff', '/stuff/and/things': '/stuff/and/things' } for inp, exp in test_in_exp.items(): result = nxt_path.node_path_from_attr_path(inp) self.assertEqual(exp, result) test_in_exp = { 'stuff.thing': 'thing', 'all/other/stuff.another': 'another', '/stuff/and/things': None } for inp, exp in test_in_exp.items(): result = nxt_path.attr_name_from_attr_path(inp) self.assertEqual(exp, result) test_in_exp = { 'all/other/stuff': 'stuff', '/stuff/and/things': 'things' } for inp, exp in test_in_exp.items(): result = nxt_path.node_name_from_node_path(inp) self.assertEqual(exp, result) test_in_exp = { 'all/other/stuff': 'all/other', '/stuff/and/things': '/stuff/and' } for inp, exp in test_in_exp.items(): result = nxt_path.get_parent_path(inp) self.assertEqual(exp, result) test_in_exp = { '/all/other/stuff': '/all', '/stuff/and/things': '/stuff' } for inp, exp in test_in_exp.items(): result = nxt_path.get_root_path(inp) self.assertEqual(exp, result)
def update_from_model(self): """Sync the visible state of this node with the model.""" # Shortened var names comp = self.model.comp_layer node_path = self.node_path # update position if nxt_path.get_parent_path(node_path) == nxt_path.WORLD: pos = self.model.get_node_pos(node_path) self.setPos(pos[0], pos[1]) self.is_real = self.model.node_exists(node_path) self.is_proxy = self.model.get_node_is_proxy(node_path) self.collapse_state = self.model.get_node_collapse( self.node_path, comp) self.node_enabled = self.model.get_node_enabled(self.node_path) self.update_color() self.update_build_focus() self._update_collapse() self.error_list = self.model.get_node_error(node_path, comp) self.update_fonts() # update exec plugs # update attributes # 0 = no attributes # 1 = only local attributes # 2 = local and instanced attributes # 3 = local, instanced, and inherited attributes attr_display_state = self.model.get_attr_display_state(node_path) if attr_display_state == 1: attr_names = self.model.get_node_local_attr_names(node_path, comp) elif attr_display_state == 2: local_attr_names = self.model.get_node_local_attr_names( node_path, comp) inst_attrs = self.model.get_node_instanced_attr_names( node_path, comp) attr_names = set(local_attr_names + inst_attrs) elif attr_display_state == 3: attr_names = self.model.get_node_attr_names(node_path, comp) else: attr_names = [] removed_attr_names = set(self.user_attr_names).difference(attr_names) self.user_attr_names = sorted(attr_names) for removed_name in removed_attr_names: if removed_name in self._attribute_draw_details: self._attribute_draw_details.pop(removed_name) if removed_name not in self._attr_plug_graphics: continue plug_grpahics = self._attr_plug_graphics.pop(removed_name) plug = plug_grpahics.get('in_plug') if plug: self.scene().removeItem(plug) plug = plug_grpahics.get('out_plug') if plug: self.scene().removeItem(plug) self.calculate_attribute_draw_details() for key, value in self._attribute_draw_details.items(): in_plug = value.get('in_plug') if in_plug: in_plug.update() out_plug = value.get('out_plug') if out_plug: out_plug.update() self.is_break = self.model.get_is_node_breakpoint(node_path, comp) self.is_start = self.model.get_is_node_start(node_path, comp) sp_attr = INTERNAL_ATTRS.START_POINT self.start_color = self.model.get_node_attr_color( node_path, sp_attr, comp) if attr_display_state == 1: self.attr_dots = [True, False, False] elif attr_display_state == 2: self.attr_dots = [True, True, False] elif attr_display_state == 3: self.attr_dots = [True, True, True] else: self.attr_dots = [False, False, False] self.update()
def draw_title(self, painter, lod=1.): """Draw title of the node. Called exclusively in paint. :param painter: painter from paint. :type painter: QtGui.QPainter """ # draw bg painter.setPen(QtCore.Qt.NoPen) bg = painter.background() bgm = painter.backgroundMode() if self.error_item: self.scene().removeItem(self.error_item) self.error_item.deleteLater() self.error_item = None if self.is_real: painter.setBackgroundMode(QtCore.Qt.OpaqueMode) else: painter.setBackgroundMode(QtCore.Qt.TransparentMode) [c.setAlphaF(self.color_alpha) for c in self.colors] color_count = len(self.colors) color_band_width = 10 for i in range(color_count): color = self.colors[i] if self.is_proxy: painter.setBackground(color.darker(self.dim_factor)) brush = QtGui.QBrush(color.darker(self.dim_factor * 2), QtCore.Qt.FDiagPattern) painter.setBrush(brush) else: painter.setBrush(color.darker(self.dim_factor)) # Top Opinion if i + 1 == color_count: remaining_width = self.max_width - (i * color_band_width) painter.drawRect(0, 0, remaining_width, self.title_rect_height) # Lower Opinions else: x_pos = self.max_width - (i + 1) * color_band_width painter.drawRect(x_pos, 0, color_band_width, self.title_rect_height) painter.setBackground(bg) painter.setBackgroundMode(bgm) # draw exec plugs exec_attr = nxt_node.INTERNAL_ATTRS.EXECUTE_IN exec_in_pos = self.get_attr_in_pos(exec_attr, scene=False) exec_radius = self.EXEC_PLUG_RADIUS if nxt_path.get_parent_path(self.node_path) == nxt_path.WORLD: if self.is_start: color = self.start_color elif self.is_break: color = QtCore.Qt.red else: color = QtCore.Qt.white if not self.exec_in_plug: is_break = self.is_break if self.is_start: is_break = False self.exec_in_plug = NodeGraphicsPlug(pos=exec_in_pos, radius=exec_radius, color=color, is_exec=True, is_input=True, is_break=is_break, is_start=self.is_start) self.exec_in_plug.setParentItem(self) else: self.exec_in_plug.color = QtGui.QColor(color) self.exec_in_plug.is_break = self.is_break self.exec_in_plug.is_start = self.is_start self.exec_in_plug.setPos(exec_in_pos) self.exec_in_plug.update() out_pos = self.get_attr_out_pos(exec_attr, scene=False) if not self.exec_out_plug: self.exec_out_plug = NodeGraphicsPlug(pos=out_pos, radius=exec_radius, color=QtCore.Qt.white, is_exec=True, is_input=False) self.exec_out_plug.setParentItem(self) else: self.exec_out_plug.setPos(out_pos) else: if not self.exec_in_plug and self.is_break: self.exec_in_plug = NodeGraphicsPlug(pos=exec_in_pos, radius=exec_radius, color=QtCore.Qt.red, is_exec=True, is_input=True, is_break=self.is_break) self.exec_in_plug.setParentItem(self) elif self.exec_in_plug and not self.is_break: self.scene().removeItem(self.exec_in_plug) self.exec_in_plug = None if self.exec_out_plug: self.scene().removeItem(self.exec_out_plug) self.exec_out_plug = None if lod > MIN_LOD: # draw attr dots offset = -6 for fill in self.attr_dots: painter.setBrush(QtCore.Qt.white) if fill: painter.setBrush(QtCore.Qt.white) else: painter.setBrush(QtCore.Qt.NoBrush) dots_color = QtGui.QColor(QtCore.Qt.white).darker( self.dim_factor) painter.setPen(QtGui.QPen(dots_color, 0.5)) dot_x = self.max_width - 15 dot_y = (self.title_rect_height / 2) + offset painter.drawEllipse(QtCore.QPointF(dot_x, dot_y), 2, 2) offset += 6 # draw title painter.setFont(self.title_font) title_str = nxt_path.node_name_from_node_path(self.node_path) font_metrics = QtGui.QFontMetrics(self.title_font) width = self.max_width - 40 if self.error_list: width -= 20 if lod > MIN_LOD: painter.setPen( QtGui.QColor(QtCore.Qt.white).darker(self.dim_factor)) if not self.node_enabled: painter.setPen(QtGui.QColor(QtCore.Qt.white).darker(150)) title = font_metrics.elidedText(title_str, QtCore.Qt.ElideRight, width) painter.drawText(15, 0, self.max_width - 15, self.title_rect_height, QtCore.Qt.AlignVCenter, title) else: painter.setBrush( QtGui.QColor(QtCore.Qt.white).darker(self.dim_factor)) if not self.node_enabled: painter.setBrush(QtGui.QColor(QtCore.Qt.white).darker(150)) proxy_rect = font_metrics.boundingRect(title_str) r_width = proxy_rect.width() * .8 height = proxy_rect.height() painter.drawRect(15, height * .8, min(r_width, width), height * .2) if lod > MIN_LOD: # draw error if self.error_list: pos = QtCore.QPointF(self.max_width - 45, self.title_rect_height / 4) error_item = ErrorItem(font=QtGui.QFont('Roboto', 16, 75), pos=pos, text='!') error_item.setParentItem(self) error_item.setZValue(50) self.error_item = error_item # draw collapse state arrow for arrow in self.collapse_arrows: self.scene().removeItem(arrow) if lod > MIN_LOD: self.collapse_arrows = [] # TODO calculation needed arrows should be done outside drawing if self.collapse_state: des_colors = self.model.get_descendant_colors(self.node_path) filled = self.model.has_children(self.node_path) if not filled: des_colors = [QtCore.Qt.white] elif not des_colors: disp = self.model.comp_layer des_colors = [ self.model.get_node_color(self.node_path, disp) ] i = 0 num = len(des_colors) for c in des_colors: arrow = CollapseArrow(self, filled=filled, color=c) arrow_width = arrow.width * 1.1 center_offset = (arrow_width * (num * .5) - arrow_width * .5) cur_offset = (i * arrow_width) pos = ((self.max_width * .5) + center_offset - cur_offset) arrow.setPos(pos, self.boundingRect().height()) self.collapse_arrows += [arrow] i += 1