Ejemplo n.º 1
0
    def rename_node(self):
        """Presents a rename dialog pop-up over the node item. The new name is sent to the model."""
        # get dialog geometry
        scale_factor = self.view.transform().m11()
        scale = scale_factor if scale_factor > 0.75 else 0.75
        title_rect = self.title_bounding_rect.toRect()
        width = title_rect.width() * scale
        height = title_rect.height() * scale
        pos = self.screen_pos
        geometry = QtCore.QRect(pos.x(), pos.y(), width, height)

        # rename dialog
        name = nxt_path.node_name_from_node_path(self.node_path)
        dialog = NameEditDialog(name=name, geometry=geometry, parent=None)
        color_name = self.colors[-1].name()
        dialog.setStyleSheet('background-color: %s; color: white' % color_name)
        font = QtGui.QFont(self.title_font.family(),
                           self.title_font.pointSizeF() * scale)
        dialog.line_edit.setFont(font)
        dialog.exec_()

        # rename node
        if dialog.result():
            new_name = dialog.value
            self.model.set_node_name(self.node_path, new_name,
                                     self.model.target_layer)
Ejemplo n.º 2
0
    def __init__(self, node_path, parent=None):
        super(CheckBox, self).__init__(parent=parent)
        self.setStyleSheet('QWidget {margin-top: -4; margin-bottom: -4;}')

        # internal setup
        self._parent = parent
        self.stage_model = parent.stage_model
        self.node_path = node_path

        attr_data = get_resolved_attr_values(node_path=node_path,
                                             stage_model=self.stage_model)

        # layout
        self.main_layout = QtWidgets.QHBoxLayout(self)
        self.main_layout.setContentsMargins(0, 0, 0, 0)
        self.main_layout.setSpacing(0)
        alignment = attr_data.get(self.ALIGNMENT_ATTR)
        layout_alignment = self.ALIGNMENT.get(alignment)
        if layout_alignment:
            self.main_layout.setAlignment(layout_alignment)
        self.setLayout(self.main_layout)

        # checkbox
        text_color = attr_data.get(self.TEXT_COLOR_ATTR) or 'white'
        is_checked = attr_data.get(self.IS_CHECKED_ATTR)
        checked = True if is_checked == 'True' else False
        text = (attr_data.get(self.TEXT_ATTR)
                or nxt_path.node_name_from_node_path(self.node_path))
        style = 'QCheckBox {color: %s;}' % text_color
        self.checkbox = QtWidgets.QCheckBox(text=text, checked=checked)
        self.checkbox.setStyleSheet(style)
        self.checkbox.toggled.connect(self.execute_node_path)
        self.main_layout.addWidget(self.checkbox)

        text_align = attr_data.get(self.TEXT_ALIGN_ATTR)
        label_alignment = self.LABEL_ALIGNMENT.get(text_align)
        if label_alignment:
            self.checkbox.setLayoutDirection(label_alignment)

        # add context menu
        ContextMenu(stage_model=self.stage_model,
                    node_path=node_path,
                    widget=self.checkbox,
                    items=None,
                    parent=self)
Ejemplo n.º 3
0
def get_widget_type(node_path, stage_model):
    node = stage_model.comp_layer.lookup(node_path)
    if not node:
        return

    instance_trace_list = stage_model.stage.get_instance_sources(
        node=node, trace_list=[], comp_layer=stage_model.comp_layer)
    if not instance_trace_list:
        return

    instance_node = instance_trace_list[-1]
    instance_path = stage_model.comp_layer.get_node_path(instance_node)
    if not instance_path:
        return

    instance_name = nxt_path.node_name_from_node_path(instance_path)
    widget_type = instance_name if instance_name in WIDGET_TYPES else None
    return widget_type
Ejemplo n.º 4
0
 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)
Ejemplo n.º 5
0
    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
Ejemplo n.º 6
0
    def __init__(self, node_path, parent=None):
        super(Button, self).__init__(parent=parent)

        # internal setup
        self._parent = parent
        self.stage_model = parent.stage_model
        self.node_path = node_path

        attr_data = get_resolved_attr_values(node_path=node_path,
                                             stage_model=self.stage_model)

        # button setup
        text = (attr_data.get(self.TEXT_ATTR)
                or nxt_path.node_name_from_node_path(node_path))
        self.setText(text)
        self.pressed.connect(lambda p=self.node_path, a=self.EXEC_PATH_ATTR:
                             self.execute_node_path(p, a))

        background_color = attr_data.get(
            self.BACKGROUND_COLOR_ATTR) or '#606060'
        border_color = attr_data.get(self.BORDER_COLOR_ATTR) or 'none'
        text_color = attr_data.get(self.TEXT_COLOR_ATTR) or 'white'
        style = '''
                QPushButton {
                    color: %s;
                    background-color: %s;
                    border-radius: 9px;
                    border: none;
                    }

                QPushButton:hover {
                    padding-bottom: -1;
                    padding-top: -1;
                    border: 2px solid %s;
                    }
                ''' % (text_color, background_color, border_color)
        self.setStyleSheet(style)

        # add context menu
        items = []
        for menu_item_path in self.get_menu_item_paths():
            menu_data = get_resolved_attr_values(node_path=menu_item_path,
                                                 stage_model=self.stage_model)
            if menu_data.get(self.SEPARATOR_ATTR) == 'True':
                items.append('separator')
            else:
                text = menu_data.get(self.TEXT_ATTR)
                action = QtWidgets.QAction(text, self)
                if menu_data.get(self.SELECTOR_ITEM_ATTR) == 'True':
                    title = menu_data.get(self.SELECTOR_TITLE_ATTR)
                    action.triggered.connect(lambda p=menu_item_path, t=title:
                                             self.selection_widget(p, t))
                else:
                    action.triggered.connect(
                        lambda p=menu_item_path, a=self.ITEM_PATH_ATTR: self.
                        execute_node_path(p, a))
                items.append(action)

        ContextMenu(stage_model=self.stage_model,
                    node_path=self.node_path,
                    widget=self,
                    items=items,
                    parent=self)
Ejemplo n.º 7
0
    def __init__(self, node_path, parent=None):
        super(DropDownMenu, self).__init__(parent=parent)
        size_policy = QtWidgets.QSizePolicy()
        size_policy.setHorizontalPolicy(QtWidgets.QSizePolicy.Preferred)
        size_policy.setHorizontalStretch(1)
        self.setSizePolicy(size_policy)

        # internal setup
        self._parent = parent
        self.stage_model = parent.stage_model
        self.node_path = node_path

        attr_data = get_resolved_attr_values(node_path=node_path,
                                             stage_model=self.stage_model)

        # layout
        self.main_layout = QtWidgets.QHBoxLayout(self)
        self.main_layout.setContentsMargins(0, 0, 0, 0)
        self.main_layout.setSpacing(0)
        self.setLayout(self.main_layout)

        # label
        text = (attr_data.get(self.TEXT_ATTR)
                or nxt_path.node_name_from_node_path(self.node_path))
        text_color = attr_data.get(self.TEXT_COLOR_ATTR) or 'white'
        self.label = QtWidgets.QLabel(text)
        self.label.setStyleSheet('QLabel {color: %s}' % text_color)
        self.main_layout.addWidget(self.label)

        # style
        background_color = attr_data.get(
            self.BACKGROUND_COLOR_ATTR) or '#232323'
        border_color = attr_data.get(self.BORDER_COLOR_ATTR) or 'transparent'
        border_line = '2px solid %s' % border_color if border_color != 'transparent' else 'none'
        padding = '4' if border_color != 'transparent' else '6'
        style = '''
                QComboBox {
                    color: %s;
                    background: %s;
                    border-radius: 9px;
                    border: none;
                    padding-left: 6;
                    overflow: hidden;
                    }

                QComboBox:hover {
                    padding-left: %s;
                    border: %s;
                    }
                ''' % (text_color, background_color, padding, border_line)
        view_style = '''
                     QComboBox QAbstractItemView {
                         selection-color: white;
                         selection-background-color: #148CD2;
                         background: %s;
                         border-top-left-radius: 0px;
                         border-top-right-radius: 0px;
                         border-bottom-left-radius: 9px;
                         border-bottom-right-radius: 9px;
                         border-width: 2px;
                         border-style: solid;
                         border-color: transparent %s %s %s;
                         margin-right: 9px;
                         margin-left: 9px;
                         outline: 0;
                     }
                     ''' % (background_color, border_color, border_color,
                            border_color)

        # combo box
        self.combo_box = QtWidgets.QComboBox(self)
        self.combo_box.setStyleSheet(style)
        self.combo_box.view().window().setWindowFlags(
            QtCore.Qt.Popup | QtCore.Qt.FramelessWindowHint
            | QtCore.Qt.NoDropShadowWindowHint)
        self.combo_box.view().setStyleSheet(view_style)
        self.combo_box.view().window().setAttribute(
            QtCore.Qt.WA_TranslucentBackground)
        self.main_layout.addWidget(self.combo_box, 1)

        # menu items
        menu_items = attr_data.get(self.MENU_ITEMS_ATTR)
        if not menu_items:
            return

        menu_items_list = menu_items.split(' ')
        self.combo_box.addItems(menu_items_list)
        menu_value = self.stage_model.get_node_attr_value(
            node_path=self.node_path,
            attr_name=self.MENU_VALUE_ATTR,
            layer=self.stage_model.comp_layer,
            data_state=DATA_STATE.RESOLVED)
        if menu_value in menu_items_list:
            self.combo_box.setCurrentText(menu_value)
        self.combo_box.currentIndexChanged.connect(self.execute_node_path)

        # add context menus
        ContextMenu(stage_model=self.stage_model,
                    node_path=node_path,
                    widget=self,
                    items=None,
                    parent=self)

        ContextMenu(stage_model=self.stage_model,
                    node_path=node_path,
                    widget=self.combo_box,
                    items=None,
                    parent=self)